module Lox 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) def visit_print(expr) = parenthesize("print", expr.expr) def visit_var(expr) exprs = [expr.initializer].reject(&:nil?) parenthesize("var #{expr.name.lexeme}", *exprs) end def visit_variable(expr) "(var #{expr.name.lexeme})" end def visit_assign(expr) parenthesize("assign #{expr.name.lexeme}", expr.value) end def visit_block(expr) parenthesize("block", *expr.stmts) end def visit_if(stmt) exprs = [stmt.cond, stmt.then] exprs << stmt.else if stmt.else parenthesize("if", *exprs) end def visit_expr(expr) expr.expr.accept(self) end def visit_call(call) parenthesize(call.callee.accept(self), *call.args) end private def parenthesize(name, *exprs) inside = [name] inside.concat(exprs.map {|expr| expr.accept(self) }) "(#{inside.join(" ")})" end end end