diff --git a/ruby/lib/lox/ast_printer.rb b/ruby/lib/lox/ast_printer.rb index 154c9b9..ae8bdd1 100644 --- a/ruby/lib/lox/ast_printer.rb +++ b/ruby/lib/lox/ast_printer.rb @@ -40,6 +40,11 @@ module Lox parenthesize(call.callee.accept(self), *call.args) end + def visit_return(stmt) + exprs = stmt.value ? [stmt.value] : [] + parenthesize("return", *exprs) + end + private def parenthesize(name, *exprs) diff --git a/ruby/lib/lox/parser.rb b/ruby/lib/lox/parser.rb index 7ac47d3..0728bb4 100644 --- a/ruby/lib/lox/parser.rb +++ b/ruby/lib/lox/parser.rb @@ -50,6 +50,7 @@ module Lox return for_stmt if match?(:FOR) return if_stmt if match?(:IF) return print if match?(:PRINT) + return return_stmt if match?(:RETURN) return while_stmt if match?(:WHILE) return Stmt::Block.new(block) if match?(:LEFT_BRACE) @@ -111,6 +112,13 @@ module Lox Stmt::Print.new(value) end + def return_stmt + keyword = prev + value = check?(:SEMICOLON) ? nil : expression + consume!(:SEMICOLON, "Expect ';' after return value.") + Stmt::Return.new(keyword, value) + end + def expression_stmt value = expression consume!(:SEMICOLON, "Expect ';' after value.") diff --git a/ruby/lib/lox/stmt.rb b/ruby/lib/lox/stmt.rb index 2826c67..e4bfc54 100644 --- a/ruby/lib/lox/stmt.rb +++ b/ruby/lib/lox/stmt.rb @@ -17,6 +17,7 @@ module Lox stmt :Expr, :expr stmt :If, :cond, :then, :else stmt :Print, :expr + stmt :Return, :keyword, :value stmt :Var, :name, :initializer stmt :While, :cond, :body end diff --git a/ruby/test/lox/test_parser.rb b/ruby/test/lox/test_parser.rb index 11a7904..7aee4d2 100644 --- a/ruby/test/lox/test_parser.rb +++ b/ruby/test/lox/test_parser.rb @@ -81,6 +81,11 @@ class TestParser < Lox::Test assert_parsed "((var foo) (var bar) (var baz))", :statement, "foo(bar, baz);" end + def test_return + assert_parsed "(return)", :statement, "return;" + assert_parsed "(return (var foo))", :statement, "return foo;" + end + private def assert_parsed(expected, name, src)