223 | 223 |
return t
|
224 | 224 |
end
|
225 | 225 |
|
226 | |
-- Strelnokoff = {Assignment}.
|
227 | |
-- Assignment = Variable [Index] "=" Expression0.
|
228 | |
-- Expression0 = Expression1 {"=" Expression1 | ">" Expression1}.
|
229 | |
-- Expression1 = Expression2 {"+" Expression2 | "-" Expression2}.
|
230 | |
-- Expression2 = Primitive {"*" Primitive | "/" Primitive}.
|
231 | |
-- Primitive = ["PRINT" | "INPUT"] ["CHAR"] Variable [Index]
|
232 | |
-- | IntegerLiteral | CharLiteral
|
233 | |
-- | "(" Expression0 ")".
|
234 | |
-- Index = "[" Expression0 {"," Expression0} "]".
|
235 | |
|
236 | 226 |
function Parser:program()
|
237 | 227 |
local assignments = {}
|
238 | 228 |
while self.scanner.toktype ~= "EOF" do
|
|
278 | 268 |
|
279 | 269 |
function Parser:expression2()
|
280 | 270 |
local expr, t, rhs
|
281 | |
expr = self:primitive()
|
|
271 |
expr = self:expression3()
|
282 | 272 |
assert(expr ~= nil)
|
283 | 273 |
while self.scanner.token == "*" or self.scanner.token == "/" do
|
284 | 274 |
t = self:consume_token()
|
285 | |
rhs = self:primitive()
|
|
275 |
rhs = self:expression3()
|
286 | 276 |
assert(rhs ~= nil)
|
287 | 277 |
expr = BinOp(t, expr, rhs)
|
288 | 278 |
end
|
289 | 279 |
return expr
|
290 | 280 |
end
|
291 | 281 |
|
292 | |
function Parser:primitive()
|
|
282 |
function Parser:expression3()
|
293 | 283 |
local action
|
294 | 284 |
local mode = "int"
|
295 | 285 |
|
296 | |
-- FIXME I feel like this should probably change to be an operator...
|
297 | 286 |
if self.scanner.token == "PRINT" then
|
298 | 287 |
action = "PRINT"
|
299 | 288 |
self.scanner:scan()
|
|
307 | 296 |
self.scanner:scan()
|
308 | 297 |
end
|
309 | 298 |
|
|
299 |
local expr = self:primitive()
|
|
300 |
|
|
301 |
if action == "PRINT" then
|
|
302 |
return Action("print", mode, expr)
|
|
303 |
else
|
|
304 |
-- FIXME what about "INPUT" ... ?
|
|
305 |
return expr
|
|
306 |
end
|
|
307 |
end
|
|
308 |
|
|
309 |
function Parser:primitive()
|
310 | 310 |
debug("parse", "primitive " .. self.scanner.toktype)
|
311 | 311 |
if self.scanner.toktype == "number" then
|
312 | 312 |
local val = tonumber(self.scanner.token)
|
313 | 313 |
local expr = Literal(val)
|
314 | 314 |
self.scanner:scan()
|
315 | |
if action == "PRINT" then
|
316 | |
return Action("print", mode, expr)
|
317 | |
else
|
318 | |
-- FIXME what about "INPUT" ... ?
|
319 | |
return expr
|
320 | |
end
|
|
315 |
return expr
|
321 | 316 |
elseif self.scanner.toktype == "char" then
|
322 | 317 |
local val = string.byte(self.scanner.token, 2)
|
323 | 318 |
local expr = Literal(val)
|
324 | |
-- FIXME just as above
|
325 | |
self.scanner:scan()
|
326 | |
if action == "PRINT" then
|
327 | |
return Action("print", mode, expr)
|
328 | |
else
|
329 | |
-- FIXME what about "INPUT" ... ?
|
330 | |
return expr
|
331 | |
end
|
|
319 |
self.scanner:scan()
|
|
320 |
return expr
|
332 | 321 |
elseif self.scanner.token == "(" then
|
333 | 322 |
self.scanner:scan()
|
334 | 323 |
local expr = self:expression0()
|
335 | 324 |
self.scanner:expect(")")
|
336 | |
-- FIXME just as above
|
337 | |
if action == "PRINT" then
|
338 | |
return Action("print", mode, expr)
|
339 | |
else
|
340 | |
-- FIXME what about "INPUT" ... ?
|
341 | |
return expr
|
342 | |
end
|
|
325 |
return expr
|
343 | 326 |
else
|
344 | 327 |
local name = self:expect_toktype("ident")
|
345 | 328 |
local varindex = "" -- problematic for AST helpers if nil so we use this
|
|
347 | 330 |
varindex = self:varindex()
|
348 | 331 |
end
|
349 | 332 |
debug("parse", "primitive varaccess " .. name .. "[]" .. tostring(varindex))
|
350 | |
local expr = VarAccess(name, varindex)
|
351 | |
if action == "PRINT" then
|
352 | |
expr = Action("print", mode, expr)
|
353 | |
end
|
354 | |
debug("parse", "primitive varaccess expr " .. render(expr))
|
355 | |
-- FIXME what about "INPUT" ... ?
|
356 | |
return expr
|
|
333 |
return VarAccess(name, varindex)
|
357 | 334 |
end
|
358 | 335 |
end
|
359 | 336 |
|