mirror of
https://github.com/notwa/lips
synced 2024-04-22 22:30:46 -07:00
Connor Olding
f851540b24
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.
99 lines
2.3 KiB
Lua
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
|