1
0
Fork 0
mirror of https://github.com/notwa/mm synced 2024-11-05 02:49:02 -08:00
mm/Lua/lib/lips/Muncher.lua

161 lines
3.7 KiB
Lua
Raw Normal View History

2016-01-13 11:20:28 -08:00
local format = string.format
local insert = table.insert
2016-04-21 13:04:49 -07:00
local path = string.gsub(..., "[^.]+$", "")
local data = require(path.."data")
local Base = require(path.."Base")
local Token = require(path.."Token")
2016-01-13 11:20:28 -08:00
local arg_types = {
NUM = true,
REG = true,
2016-04-21 13:04:49 -07:00
VARSYM = true,
2016-01-13 11:20:28 -08:00
LABELSYM = true,
RELLABELSYM = true,
}
2016-04-21 13:04:49 -07:00
local Muncher = Base:extend()
2016-01-13 11:20:28 -08:00
-- no base init method
2016-04-21 13:04:49 -07:00
function Muncher:error(msg, got)
if got ~= nil then
msg = msg..', got '..tostring(got)
end
2016-01-13 11:20:28 -08:00
error(format('%s:%d: Error: %s', self.fn, self.line, msg), 2)
end
function Muncher:token(t, val)
-- note: call Token directly if you want to specify fn and line manually
if type(t) == 'table' then
t.fn = self.fn
t.line = self.line
2016-04-21 13:04:49 -07:00
local token = Token(t)
return token
2016-01-13 11:20:28 -08:00
else
2016-04-21 13:04:49 -07:00
local token = Token(self.fn, self.line, t, val)
return token
2016-01-13 11:20:28 -08:00
end
end
function Muncher:advance()
self.i = self.i + 1
self.t = self.tokens[self.i]
self.tt = self.t.tt
self.tok = self.t.tok
self.fn = self.t.fn
self.line = self.t.line
return self.t
end
function Muncher:is_EOL()
return self.tt == 'EOL' or self.tt == 'EOF'
end
function Muncher:expect_EOL()
if self:is_EOL() then
self:advance()
return
end
2016-04-26 14:48:39 -07:00
self:error('expected end of line', self.tt)
2016-01-13 11:20:28 -08:00
end
function Muncher:optional_comma()
if self.tt == 'SEP' and self.tok == ',' then
self:advance()
return true
end
end
function Muncher:number()
if self.tt ~= 'NUM' then
2016-04-26 14:48:39 -07:00
self:error('expected number', self.tt)
2016-01-13 11:20:28 -08:00
end
local t = self.t
self:advance()
return self:token(t)
end
function Muncher:string()
if self.tt ~= 'STRING' then
2016-04-26 14:48:39 -07:00
self:error('expected string', self.tt)
2016-01-13 11:20:28 -08:00
end
local t = self.t
self:advance()
return self:token(t)
end
function Muncher:register(registers)
registers = registers or data.registers
if self.tt ~= 'REG' then
2016-04-26 14:48:39 -07:00
self:error('expected register', self.tt)
2016-01-13 11:20:28 -08:00
end
local t = self.t
if not registers[t.tok] then
2016-04-26 14:48:39 -07:00
self:error('wrong type of register', t.tok)
2016-01-13 11:20:28 -08:00
end
self:advance()
return self:token(t)
end
function Muncher:deref()
if self.tt ~= 'OPEN' then
2016-04-26 14:48:39 -07:00
self:error('expected opening parenthesis for dereferencing', self.tt)
2016-01-13 11:20:28 -08:00
end
self:advance()
if self.tt ~= 'REG' then
2016-04-26 14:48:39 -07:00
self:error('expected register to dereference', self.tt)
2016-01-13 11:20:28 -08:00
end
local t = self.t
self:advance()
if self.tt ~= 'CLOSE' then
2016-04-26 14:48:39 -07:00
self:error('expected closing parenthesis for dereferencing', self.tt)
2016-01-13 11:20:28 -08:00
end
self:advance()
return self:token(t)
end
function Muncher:const(relative, no_label)
2016-04-21 13:04:49 -07:00
if self.tt ~= 'NUM' and self.tt ~= 'VARSYM' and self.tt ~= 'LABELSYM' then
self:error('expected constant', self.tt)
2016-01-13 11:20:28 -08:00
end
if no_label and self.tt == 'LABELSYM' then
2016-04-26 14:48:39 -07:00
self:error('labels are not allowed here', self.tt)
2016-01-13 11:20:28 -08:00
end
local t = self:token(self.t)
self:advance()
return t
end
function Muncher:special()
if self.tt ~= 'SPECIAL' then
2016-04-26 14:48:39 -07:00
self:error('expected special name to call', self.tt)
2016-01-13 11:20:28 -08:00
end
local name = self.tok
self:advance()
if self.tt ~= 'OPEN' then
2016-04-26 14:48:39 -07:00
self:error('expected opening parenthesis for special call', self.tt)
2016-01-13 11:20:28 -08:00
end
local args = {}
while true do
local arg = self:advance()
if not arg_types[arg.tt] then
2016-04-26 14:48:39 -07:00
self:error('invalid argument type', arg.tt)
2016-01-13 11:20:28 -08:00
else
self:advance()
end
if self.tt == 'SEP' then
insert(args, arg)
elseif self.tt == 'CLOSE' then
insert(args, arg)
break
else
2016-04-26 14:48:39 -07:00
self:error('unexpected token in argument list', self.tt)
2016-01-13 11:20:28 -08:00
end
end
return name, args
end
return Muncher