Skip to content

Commit 2a5de46

Browse files
committed
Parse binary expressions
1 parent f149a7a commit 2a5de46

File tree

3 files changed

+67
-2
lines changed

3 files changed

+67
-2
lines changed

lib/expression_parser.rb

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ def emit(vm_writer, symbol_table)
1313
end
1414
end
1515

16+
BinaryOperation = Struct.new(:operation, :left_node, :right_node) do
17+
def emit(vm_writer, symbol_table)
18+
left_node.emit(vm_writer, symbol_table)
19+
right_node.emit(vm_writer, symbol_table)
20+
vm_writer.write_operation(operation)
21+
end
22+
end
23+
1624
attr_reader :tokenizer
1725
private :tokenizer
1826

@@ -21,15 +29,30 @@ def initialize(tokenizer)
2129
end
2230

2331
def parse
24-
case tokenizer.token_type
32+
left_node = case tokenizer.token_type
2533
when Tokenizer::INT_CONST
2634
number = tokenizer.int_val
2735

2836
Number.new(number)
29-
else
37+
when Tokenizer::IDENTIFIER
3038
identifier = tokenizer.identifier
3139

3240
Variable.new(identifier)
3341
end
42+
43+
return left_node unless tokenizer.has_more_tokens?
44+
45+
tokenizer.advance
46+
47+
if %w[+ - * / & | < > =].include?(tokenizer.symbol)
48+
operation = tokenizer.symbol
49+
tokenizer.advance
50+
51+
right_node = parse
52+
53+
BinaryOperation.new(operation, left_node, right_node)
54+
else
55+
left_node
56+
end
3457
end
3558
end

lib/vm_writer.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ def write_pop(segment, index)
1414
io.puts("pop #{segment} #{index}")
1515
end
1616

17+
def write_operation(operation)
18+
write_arithmetic({ '+' => 'add' }.fetch(operation))
19+
end
20+
1721
def write_arithmetic(command)
1822
io.puts(command)
1923
end

spec/unit/expression_parser_spec.rb

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,42 @@
4141

4242
expect(output.string).to eq("push static 0\n")
4343
end
44+
45+
it 'emits VM code for binary expressions' do
46+
tokenizer = Tokenizer.new('1 + 1')
47+
tokenizer.advance
48+
49+
symbol_table = SymbolTable.new
50+
51+
result = ExpressionParser.new(tokenizer).parse
52+
output = StringIO.new
53+
vm_writer = VMWriter.new(output)
54+
result.emit(vm_writer, symbol_table)
55+
56+
expect(output.string).to eq(<<-VM)
57+
push constant 1
58+
push constant 1
59+
add
60+
VM
61+
end
62+
63+
it 'emits VM code for compound binary expressions' do
64+
tokenizer = Tokenizer.new('1 + 2 + 3')
65+
tokenizer.advance
66+
67+
symbol_table = SymbolTable.new
68+
69+
result = ExpressionParser.new(tokenizer).parse
70+
output = StringIO.new
71+
vm_writer = VMWriter.new(output)
72+
result.emit(vm_writer, symbol_table)
73+
74+
expect(output.string).to eq(<<-VM)
75+
push constant 1
76+
push constant 2
77+
push constant 3
78+
add
79+
add
80+
VM
81+
end
4482
end

0 commit comments

Comments
 (0)