1
0
Fork 0
mirror of https://github.com/notwa/lips synced 2024-04-22 22:30:46 -07:00
lips/lips/Reader.lua
Connor Olding f851540b24 various fixes, mostly for labels
reimplement modulo by 0x80000000 for labels.
allow numeric label values ("REL") to be "fixed" to bypass label calculation.
add offsets after label calculation instead of before.
properly check for EOL after all expected arguments have been exhausted.
finally, add token properties to debug dumps.
2016-04-24 03:55:12 -07:00

99 lines
2.3 KiB
Lua

local path = string.gsub(..., "[^.]+$", "")
local Base = require(path.."Base")
local Token = require(path.."Token")
local Reader = Base:extend()
-- no base init method
-- Reader expects self.s to be set to a statement, and self.i to a token index
function Reader:error(msg, got)
if got ~= nil then
msg = msg..', got '..tostring(got)
end
error(('%s:%d: Error: %s'):format(self.fn, self.line, msg), 2)
end
function Reader:token(t, ...)
local new
if type(t) == 'table' then
new = Token(t, ...)
else
new = Token(self.fn, self.line, t, ...)
end
return new
end
function Reader:expect(tts)
local t = self.s[self.i]
if t == nil then
local err = ("expected another argument for %s at position %i"):format(self.s.type, self.i)
self:error(err)
end
self.fn = t.fn
self.line = t.line
for _, tt in pairs(tts) do
if t.tt == tt then
return t.ok
end
end
local err
if #tts == 1 then
err = ("argument %i of %s expected type %s"):format(self.i, self.s.type, tts[1])
else
err = ("unexpected type for argument %i of %s"):format(self.i, self.s.type)
end
self:error(err, t.tt)
end
function Reader:register(registers)
self:expect{'REG'}
local t = self.s[self.i]
local numeric = registers[t.tok]
if not numeric then
self:error('wrong type of register', t.tok)
end
local new = Token(t)
return new
end
function Reader:const(relative, no_label)
self:expect{'NUM', 'LABELSYM', 'LABELREL'}
local t = self.s[self.i]
-- overrides will want to LUI a label; let portioned labels pass
if no_label and not t.portion then
self:expect{'NUM', 'LABELREL'}
end
local new = Token(t)
if relative then -- you probably shouldn't use this in Preproc
if t.tt == 'LABELSYM' then
new.tt = 'LABELREL'
elseif t.tt == 'NUM' then
new.tt = 'REL'
end
end
return new
end
function Reader:deref()
self:expect{'DEREF'}
local t = self.s[self.i]
local new = Token(t)
--new.tt = 'REG'
return new
end
function Reader:peek(tt)
local t = self.s[self.i]
local seen = t and t.tt or nil
if tt ~= nil then
return seen == tt
end
return t
end
return Reader