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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
# File 'lib/fam/syntax/parser.rb', line 32
def parse_token t
case t.type
when :LABEL
return LabelNode.new @tokens.current
when :OPCODE
case t.name
when 'HALT'
exit_status = NumericNode.new tokenize('0000', :NUMERIC)
exit_status = parse_token @tokens.next if @tokens.peek.type == @NUMERIC
return HaltNode.new exit_status
when 'GOTO'
label = parse_token @tokens.next
UnexpectedToken @tokens.current unless @tokens.current.type == :IDENT
return GotoNode.new label
when 'STORE'
value = parse_token @tokens.next
@tokens.next
ExpectedToken 'TOKEN<:OPERATOR>(`:`)', @tokens.current unless @tokens.current.name == ':'
to = parse_token @tokens.next
ExpectedToken 'ADDRESS or IDENT', @tokens.current unless @tokens.current.type == :ADDRESS || @tokens.current.type == :IDENT
return StoreNode.new value, to
when 'LOAD'
value = parse_token @tokens.next
@tokens.next
ExpectedToken 'TOKEN<:OPERATOR>(`:`)', @tokens.current unless @tokens.current.name == ':'
reg = parse_token @tokens.next
ExpectedToken 'REGISTER', @tokens.current unless @tokens.current.type == :REGISTER
return LoadNode.new value, reg
when 'DATA'
name = parse_token @tokens.next
UnexpectedValue name unless @tokens.current.type == :IDENT
if @tokens.peek.name == ':'
@tokens.next
value = parse_token @tokens.next
else
value = NumericNode.new tokenize('0000', :NUMERIC)
end
return DataNode.new name, value
when 'ADD', 'SUB', 'MUL', 'DIV', 'MOD'
value = parse_token @tokens.next
@tokens.next
ExpectedToken 'TOKEN<:OPERATOR>(`:`)', @tokens.current unless @tokens.current.name == ':'
to = parse_token @tokens.next
return case t.name
when 'ADD'
AddNode.new value, to
when 'SUB'
SubNode.new value, to
when 'MUL'
MulNode.new value, to
when 'DIV'
DivNode.new value, to
when 'MOD'
ModNode.new value, to
end
when 'EQUAL', 'MORE', 'LESS'
parse_condition
when 'IN'
reg = parse_token @tokens.next
ExpectedToken 'TOKEN<:REGISTER>', @tokens.current unless @tokens.current.type == :REGISTER
return InNode.new reg
when 'OUT', 'ASCII'
value = parse_token @tokens.next
if t.name == 'OUT'
return OutNode.new value
else
return AsciiNode.new value
end
else
abort "Unknown/unparsable OPCODE: `#{t.name}` at [#{t.line}:#{t.col}]!".red.bold
end
when :ADDRESS
return AddressNode.new @tokens.current
when :NUMERIC
return NumericNode.new @tokens.current
when :REGISTER
return RegisterNode.new @tokens.current
when :IDENT
return IdentNode.new @tokens.current
else
return nil
end
end
|