diff --git a/ruby/lib/lox/ast_printer.rb b/ruby/lib/lox/ast_printer.rb index be30643..d394311 100644 --- a/ruby/lib/lox/ast_printer.rb +++ b/ruby/lib/lox/ast_printer.rb @@ -8,7 +8,14 @@ module Lox def visit_unary(expr) = parenthesize(expr.op.lexeme, expr.right) def visit_print(expr) = parenthesize("print", expr.expr) - def visit_var(expr) = "(var #{expr.name.lexeme} #{expr.initializer.value})" + + def visit_var(expr) + if init = expr.initializer + "(assign #{expr.name.lexeme} #{expr.initializer.value})" + else + "(var #{expr.name.lexeme})" + end + end private diff --git a/ruby/lib/lox/expr.rb b/ruby/lib/lox/expr.rb index 0f81c8f..606e5dd 100644 --- a/ruby/lib/lox/expr.rb +++ b/ruby/lib/lox/expr.rb @@ -2,6 +2,10 @@ require_relative "visitable" module Lox module Expr + Assign = Struct.new(:name, :value) do + include Visitable + end + Binary = Struct.new(:left, :op, :right) do include Visitable end diff --git a/ruby/lib/lox/parser.rb b/ruby/lib/lox/parser.rb index c263624..a2dc1dd 100644 --- a/ruby/lib/lox/parser.rb +++ b/ruby/lib/lox/parser.rb @@ -54,6 +54,21 @@ module Lox Stmt::Expr.new(value) end + def assignment + expr = equality + + if match?(:EQUAL) + eq = prev + value = assignment + + raise ParseError.new(eq, "Invalid assignment target.") unless expr.instance_of?(Expr::Variable) + + Expr::Assign.new(expr.name, value) + end + + expr + end + def expression = equality def equality diff --git a/ruby/test/lox/test_parser.rb b/ruby/test/lox/test_parser.rb index cc9f1e9..579676e 100644 --- a/ruby/test/lox/test_parser.rb +++ b/ruby/test/lox/test_parser.rb @@ -52,7 +52,11 @@ class TestParser < Lox::Test end def test_var - assert_parsed "(var foo 42.0)", :declaration, "var foo = 42.0;" + assert_parsed "(var foo)", :declaration, "var foo;" + end + + def test_assign + assert_parsed "(assign foo 42.0)", :declaration, "var foo = 42.0;" end private