implement AstPrinter
FossilOrigin-Name: ed84fb6a6150359d3756c8636af19f487cb4da6fc2f21a6147b335751416a06f
diff --git a/ruby/lox.rb b/ruby/lox.rb
index ebce4ab..b7dbda2 100755
--- a/ruby/lox.rb
+++ b/ruby/lox.rb
@@ -195,6 +195,39 @@ module Lox
"#{type} #{lexeme} #{literal}"
end
end
+
+ module Expr
+ Binary = Struct.new(:left, :op, :right) do
+ def accept(visitor) = visitor.visit_binary(self)
+ end
+
+ Grouping = Struct.new(:expr) do
+ def accept(visitor) = visitor.visit_grouping(self)
+ end
+
+ Literal = Struct.new(:value) do
+ def accept(visitor) = visitor.visit_literal(self)
+ end
+
+ Unary = Struct.new(:op, :right) do
+ def accept(visitor) = visitor.visit_unary(self)
+ end
+ end
+
+ class AstPrinter
+ def print(expr) = expr.accept(self)
+
+ def visit_binary(expr) = parenthesize(expr.op.lexeme, expr.left, expr.right)
+ def visit_grouping(expr) = parenthesize("group", expr.expr)
+ def visit_literal(expr) = expr.value&.to_s || "nil"
+ def visit_unary(expr) = parenthesize(expr.op.lexeme, expr.right)
+
+ private
+
+ def parenthesize(name, *exprs)
+ "(#{name} #{exprs.map {|expr| expr.accept(self) }.join(" ")})"
+ end
+ end
end
if __FILE__ == $0
diff --git a/ruby/test_lox.rb b/ruby/test_lox.rb
index 27f4ff3..e217fd1 100644
--- a/ruby/test_lox.rb
+++ b/ruby/test_lox.rb
@@ -137,3 +137,20 @@ class TestScanner < Minitest::Test
end
end
end
+
+class TestAstPrinter < Minitest::Test
+ def test_ast_printer
+ expr = Expr::Binary.new(
+ Expr::Unary.new(
+ Token.new(:MINUS, ?-, nil, 1),
+ Expr::Literal.new(123),
+ ),
+ Token.new(:STAR, ?*, nil, 1),
+ Expr::Grouping.new(
+ Expr::Literal.new(45.67),
+ ),
+ )
+
+ assert_equal "(* (- 123) (group 45.67))", AstPrinter.new.print(expr)
+ end
+end