1 function gettoken(tokenlist)
2 local token = table.remove(tokenlist, 1)
6 function peektoken(tokenlist, n)
10 local token = tokenlist[n]
14 function expecttoken(token, expected)
16 error("unexpected EOF", 1)
18 for k,v in pairs(expected) do
19 if token.type == v then
23 error("unexpected token "..token.type,1)
26 function parser_global(tokenlist, parsetree)
27 -- GLOBAL = (VARIABLE | FUNCTION)
28 local token = peektoken(tokenlist)
30 if token.type == "int" then
32 expecttoken(peektoken(tokenlist, 2), {"identifier"})
33 subtoken = peektoken(tokenlist, 3)
35 error("unexpected EOF")
37 if subtoken.type == "(" then
38 table.insert(parsetree, parser_function(tokenlist))
39 elseif subtoken.type == ";" or subtoken.type == "=" then
40 table.insert(parsetree, parser_variable(tokenlist))
42 error("unexpected token "..subtoken.type.." following 'int <identifier>'")
45 error("unexpected token "..token.type)
47 token = peektoken(tokenlist)
51 function parser_function(tokenlist)
52 -- FUNCTION = TYPE IDENTIFIER ARGSLIST STMTLIST
55 myfunction.type = "function"
56 myfunction.returntype = parser_type(tokenlist)
57 local token = expecttoken(gettoken(tokenlist), {"identifier"})
58 myfunction.name = token.value
59 myfunction.args = parser_argslist(tokenlist)
60 myfunction.body = parser_stmtlist(tokenlist)
64 function parser_type(tokenlist)
66 return expecttoken(gettoken(tokenlist), { "int" }).type
69 function parser_istype(tokenlist)
70 if peektoken(tokenlist).type == "int" then
76 function parser_argslist(tokenlist)
77 -- ARGSLIST = ( [TYPE IDENTIFIER [, TYPE IDENTIFIER]*] )
81 expecttoken(gettoken(tokenlist), { "(" })
84 token = peektoken(tokenlist)
85 if token.type == ")" then
90 expecttoken(gettoken(tokenlist), { "," })
91 token = peektoken(tokenlist)
94 type = parser_type(tokenlist)
95 token = expecttoken(gettoken(tokenlist), { "identifier" })
97 table.insert(argslist, { type = type, name = ident })
101 function parser_stmtlist(tokenlist)
102 -- STMTLIST = { [( VARIABLE | STATEMENT | STMTLIST)]* }
106 stmtlist.type = "stmtlist"
108 expecttoken(gettoken(tokenlist), {"{"})
110 token = peektoken(tokenlist)
111 if token.type == "}" then
115 if parser_istype(tokenlist) then
116 table.insert(stmtlist.body, parser_variable(tokenlist))
117 elseif token.type == "{" then
118 table.insert(stmtlist.body, parser_stmtlist(tokenlist))
120 table.insert(stmtlist.body, parser_statement(tokenlist))
125 function parser_variable(tokenlist)
126 -- VARIABLE = TYPE IDENTIFIER [ = TYPEINITIALIZER ] ;
128 variable.type = "variable"
129 variable.vtype = parser_type(tokenlist)
130 variable.name = expecttoken(gettoken(tokenlist), { "identifier" }).value
131 expecttoken(peektoken(tokenlist), { ";", "=" })
132 local token = gettoken(tokenlist)
133 if token.type == ";" then
136 if token.type == '=' then
137 if variable.vtype == "int" then
138 variable.initializer = parser_getinitializer_int(tokenlist)
140 error("internal error")
142 expecttoken(gettoken(tokenlist), { ";" })
145 error("internal error")
148 function parser_getinitializer_int(tokenlist)
149 return expecttoken(gettoken(tokenlist), { "number" }).value
152 function parser_statement(tokenlist)
153 -- STATEMENT = ; | EXPRESSION ; | (WHILE | IF)
154 local token = peektoken(tokenlist)
155 if token.type == ";" then
157 elseif token.type == "while" then
158 return parser_while(tokenlist)
159 elseif token.type == "if" then
160 return parser_if(tokenlist)
161 elseif token.type == "return" then
162 return parser_return(tokenlist)
164 local result = parser_expression(tokenlist)
165 expecttoken(gettoken(tokenlist), { ";" })
170 function parser_while(tokenlist)
171 -- WHILE = WHILE ( EXPRESSION ) CHUNK
173 result.type = "while"
174 expecttoken(gettoken(tokenlist), { "while" })
175 expecttoken(gettoken(tokenlist), { "(" })
176 result.expression = parser_expression(tokenlist)
177 expecttoken(gettoken(tokenlist), { ")" })
178 result.chunk = parser_chunk(tokenlist)
182 function parser_if(tokenlist)
183 -- IF = IF ( EXPRESSION ) CHUNK
186 expecttoken(gettoken(tokenlist), { "if" })
187 expecttoken(gettoken(tokenlist), { "(" })
188 result.expression = parser_expression(tokenlist)
189 expecttoken(gettoken(tokenlist), { ")" })
190 result.chunk = parser_chunk(tokenlist)
194 function parser_return(tokenlist)
195 -- RETURN [EXPRESSION] ;
197 result.type = "return"
198 expecttoken(gettoken(tokenlist), { "return" })
199 if peektoken(tokenlist).type == ";" then
203 result.expression = parser_expression(tokenlist)
204 expecttoken(gettoken(tokenlist), { ";" })
208 function parser_chunk(tokenlist)
209 local token = peektoken(tokenlist)
210 if token.type == "{" then
211 return parser_stmtlist(tokenlist)
213 return parser_statement(tokenlist)
217 function parser_expression(tokenlist)
220 -- of those, ( ) has precedence 0
221 -- + - has precedence 3
222 -- < > has precedence 5
223 -- == has precedence 6
224 -- = has precedence 13
227 ["*"] = { precedence = 2, associative = "left" },
228 ["/"] = { precedence = 2, associative = "left" },
229 ["+"] = { precedence = 3, associative = "left" },
230 ["-"] = { precedence = 3, associative = "left" },
231 ["<"] = { precedence = 5, associative = "left" },
232 [">"] = { precedence = 5, associative = "left" },
233 ["=="] ={ precedence = 6, associative = "left" },
234 ["="] = { precedence = 13, associative = "left" }
237 -- Shunting yard algorithm
241 local addopertooutstack = function(oper)
242 assert(table.getn(outstack) >= 2, "attempted to add operator "..oper.value.." to stack containing "..table.getn(outstack).." elements")
243 oper.right = table.remove(outstack, table.getn(outstack))
244 oper.left = table.remove(outstack, table.getn(outstack))
245 table.insert(outstack, oper)
249 local token = peektoken(tokenlist)
250 if token.type == "identifier" or token.type == "number" then
253 if peektoken(tokenlist).type == "(" then -- function call guyz!
255 local outp = { type = "funccall", name = token.value, args = {} }
256 local token = peektoken(tokenlist)
257 while token.type ~= ")" do
258 table.insert(outp.args, parser_expression(tokenlist))
259 token = expecttoken(peektoken(tokenlist), { ")", "," })
260 if token.type == "," then
266 table.insert(outstack, outp)
268 table.insert(outstack, { type = token.type, value = token.value })
270 elseif token.type == "(" then
273 local outp = parser_expression(tokenlist)
274 expecttoken(gettoken(tokenlist), { ")" })
275 table.insert(outstack, outp)
276 elseif operators[token.type] then
279 while table.getn(opstack) > 0 and
280 ((operators[token.type].associative == "left" and
281 operators[token.type].precedence >= operators[opstack[table.getn(opstack)].value].precedence) or
282 (operators[token.type].associative == "right" and
283 operators[token.type].precedence > operators[opstack[table.getn(opstack)].value].precedence)) do
284 addopertooutstack(table.remove(opstack, table.getn(opstack)))
286 table.insert(opstack, { type = "operator", value = token.type })
287 elseif token.type == ")" or token.type == ";" or token.type == "," then
292 while table.getn(opstack) > 0 do
293 addopertooutstack(table.remove(opstack, table.getn(opstack)))
295 assert(table.getn(outstack) == 1, "wrong number of objects ("..table.getn(outstack)..") on output stack after expression parse")
296 return { type = "expression", value = outstack[1] }
299 function parse(tokenlist)
301 parser_global(tokenlist, parsetree)