-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.rb
67 lines (56 loc) · 1.25 KB
/
parser.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
require 'lexer'
module Brainfuck
class ParseTreeNode
attr_accessor :token
attr_accessor :parent
attr_accessor :children
def initialize(token = :start, parent = nil, children = [])
@token = token
@parent = parent
@children = children
end
def accept(visitor)
visitor.send("visit_#{@token}", self)
end
end
class Parser
attr_accessor :ast
def initialize(lexer)
@ast = ParseTreeNode.new
@lexer = lexer
end
def parse
# Start parsing start symbol
parse_statements(@ast)
end
def parse_statements(parent)
begin
token = @lexer.peek
if token == :begin_while
parse_while(parent)
elsif token == :end_while
return
else
# Parse terminal statements
parse_terminal_statement(parent)
end
end while(token != :eof)
end
def parse_terminal_statement(parent)
token = @lexer.recognize!
#puts token.to_s
parent.children << ParseTreeNode.new(token, parent, nil)
end
def parse_while(parent)
expect(:begin_while)
while_node = ParseTreeNode.new(:while, parent)
parse_statements(while_node)
parent.children << while_node
expect(:end_while)
end
def expect(sym)
token = @lexer.recognize!
raise "Unexpected '#{token}' at line #{@lexer.line} on column #{@lexer.column}" if token != sym
end
end
end