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)