Ich habe einen Interpreter (Compiler?) Mit ungefähr 80 Zeilen in Ruby erstellt.

Nachdem ich Ruby studiert hatte, machte ich es wie einen Dolmetscher, der vier Regeln ausführen kann.

Code

Dolmetscher Körper

class Interpreter
  def calc(code)
    create_tokens(code)
    exec(stmt)
  end
  private
  def create_tokens(code)
    @tokens = []
    while !code.empty?
      arr = [
        [/^[0-9]+(\.[0-9]+)?/, "num"],
        [/^[\+\-\*\/]/, "bin"],
        [/^[()]/, "bra"],
        [/^\;/, "semicolon"],
      ]
      token = arr.map { |(regex, type)|
        val = code[regex]
        { type: type, val: val } if !val.nil?
      }.compact.first
      if token.nil?
        code.slice!(0)
      else
        @tokens << token
        code.slice!(0...token[:val].length)
      end
    end
  end
  def stmt
    child = [expr]
    if @tokens.first[:type] == "semicolon"
      item = @tokens.shift
      child << stmt if [email protected]?
      { item: item, child: child }
    end
  end
  def bin(filter, parse)
    node = parse.call
    while [email protected]? && filter.call(@tokens.first[:val])
      node = { item: @tokens.shift, child: [node, parse.call] }
    end
    node
  end
  def expr
    bin(-> (token) { token == "+" || token == "-" }, -> { term })
  end
  def term
    bin(-> (token) { token == "*" || token == "/" }, -> { fact })
  end
  def fact
    if @tokens.first[:val] == "("
      @tokens.shift
      node = expr
      @tokens.shift if @tokens.first[:val] == ")"
      node
    else
      { item: @tokens.shift }
    end
  end
  def exec(node)
    type = node[:item][:type]
    if type == "semicolon"
      left, right = node[:child]
      puts "#{exec(left)}"
      exec(right) if !right.nil?
    elsif type == "bin"
      left, right = node[:child]
      case node[:item][:val]
      when "+"
        exec(left) + exec(right)
      when "-"
        exec(left) - exec(right)
      when "*"
        exec(left) * exec(right)
      when "/"
        exec(left) / exec(right)
      end
    elsif type == "num"
      node[:item][:val].to_f
    end
  end
end

Ausführungsmethode

ip = Interpreter.new
ip.calc "12345679 * 8 + 0.1; 3.1415926535 * 2;"
ip.calc "18782+18782;"

Ausführungsergebnis

$ ruby interpreter.rb
98765432.1
6.283185307
37564.0

Impressionen

Ruby, Mehrfachzuweisung ist gut. Lambda ist auch leicht zu schreiben. Ich wollte es etwas kürzer machen (jemand bitte).

Recommended Posts

Ich habe einen Interpreter (Compiler?) Mit ungefähr 80 Zeilen in Ruby erstellt.
Ich habe eine Anmerkung in Java gemacht.
Ich habe einen Öko-Server mit Scala gemacht
Ich habe mit Ruby einen riskanten Würfel gemacht
Ich habe mit Ruby einen Blackjack gemacht (ich habe versucht, Minitest zu verwenden)
Ich habe eine Ruby-Erweiterungsbibliothek in C erstellt
Ich habe mit Ruby On Rails ein Portfolio erstellt
Ich habe leicht verständlich über Java Downcast geschrieben
[Ruby] Ich habe einen Crawler mit Anemone und Nokogiri gemacht.
Ich habe eine Android-App erstellt, die mit HTTP abgerufen wird
Ich habe DI mit Ruby versucht
Ich möchte eine mit Rails 6 erstellte App an GitHub senden
Ich habe ein Roulette in Java gemacht.
Ich habe einen Adapter für den Kommunikationsunterricht mit Retrofit2 + Rx2 erstellt
Ich habe meinen eigenen mit Ruby erstellten Blackjack für mein Portfolio aktualisiert
Ich habe mit Gem in Ruby nach einem Webframework gesucht
Über reguläre Ausdrücke in Ruby
Ich habe versucht, mit Ruby festzustellen, ob eine Ganzzahl innerhalb eines bestimmten Bereichs eine Capreca-Zahl enthält
Ich habe eine E-Mail in Java gesendet
Ich habe mit Swing eine GUI erstellt
Informationen zum Erstellen von Apps mit Springboot
[Super Einführung] Über Symbole in Ruby
Führen Sie in Java8 geschriebene Anwendungen in Java6 aus
Segfo Ruby in 2 Zeilen
Ich habe versucht, das Problem der Tribonacci-Sequenz in Ruby mit Wiederholung zu lösen.
Ich möchte für jedes Array mit Lambda-Ausdruck in Java
Die Geschichte eines arithmetischen Überlaufs, der in Ruby nicht auftreten sollte
Ich habe ein Kalenderproblem mit Ruby versucht
Senden Sie E-Mails von Google Mail mit Ruby
[Ruby] Ich habe einen einfachen Ping-Client erstellt
Ich habe verschiedene Funktionen der Fibonacci-Sequenz (Ruby) erstellt.
Methoden, die ich in Ruby nützlich fand
Ich habe eine Janken App mit Kotlin gemacht
Ich habe eine Janken App mit Android gemacht