From 2e4377b600a0cdf9ef6bbb3b69d91ca2abe9e754 Mon Sep 17 00:00:00 2001 From: alpha Date: Wed, 20 Jul 2022 04:16:42 +0000 Subject: [PATCH] implement AstPrinter FossilOrigin-Name: ed84fb6a6150359d3756c8636af19f487cb4da6fc2f21a6147b335751416a06f --- ruby/lox.rb | 33 +++++++++++++++++++++++++++++++++ ruby/test_lox.rb | 17 +++++++++++++++++ 2 files changed, 50 insertions(+) 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