1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
module Lox
  module Expr
    def self.expr(name, *children)
      klass = Struct.new(name.to_s, *children) do
        def accept(visitor)
          klass = self.class.to_s.split("::").last.downcase
          visitor.send("visit_#{klass}", self)
        end
      end
      const_set(name, klass)
    end

    expr :Assign, :name, :value
    expr :Binary, :left, :op, :right
    expr :Call, :callee, :paren, :args
    expr :Get, :object, :name
    expr :Grouping, :expr
    expr :Literal, :value
    expr :Logical, :left, :op, :right
    expr :Set, :object, :name, :value
    expr :Super, :keyword, :method
    expr :This, :keyword
    expr :Unary, :op, :right
    expr :Variable, :name
  end
end