mirror of
https://github.com/notwa/lips
synced 2024-05-18 16:33:22 -07:00
add relative labels a la asw
This commit is contained in:
parent
7a0aac3b7c
commit
59d4de30fa
66
lips.lua
66
lips.lua
|
@ -788,13 +788,20 @@ function Lexer:lex(_yield)
|
||||||
self:error('unmatched closing bracket')
|
self:error('unmatched closing bracket')
|
||||||
elseif self.chr == ')' then
|
elseif self.chr == ')' then
|
||||||
self:error('unmatched closing parenthesis')
|
self:error('unmatched closing parenthesis')
|
||||||
elseif self.chr == '-' then
|
elseif self.chr == '+' or self.chr == '-' then
|
||||||
self:nextc()
|
local sign_chr = self.chr
|
||||||
local n = self:read_number()
|
local sign = sign_chr == '+' and 1 or -1
|
||||||
if n then
|
local buff = self:read_chars('%'..self.chr)
|
||||||
yield('NUM', -n)
|
if #buff == 1 and self.chr == ':' then
|
||||||
|
self:nextc()
|
||||||
|
yield('RELLABEL', sign_chr)
|
||||||
else
|
else
|
||||||
self:error('expected number after minus sign')
|
local n = self:read_number()
|
||||||
|
if n then
|
||||||
|
yield('NUM', sign*n)
|
||||||
|
else
|
||||||
|
yield('RELLABELSYM', sign*#buff)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local n = self:read_number()
|
local n = self:read_number()
|
||||||
|
@ -1404,12 +1411,14 @@ function Parser:tokenize(asm)
|
||||||
return t.tt, t.tok, t.fn, t.line
|
return t.tt, t.tok, t.fn, t.line
|
||||||
end
|
end
|
||||||
|
|
||||||
-- first pass: collect tokens and constants.
|
-- first pass: collect tokens, constants, and relative labels.
|
||||||
-- can't do more because instruction size can depend on a constant's size
|
-- can't do more because instruction size can depend on a constant's size
|
||||||
-- and labels depend on instruction size.
|
-- and labels depend on instruction size.
|
||||||
-- note however, instruction size does not depend on label size.
|
-- note however, instruction size does not depend on label size.
|
||||||
-- this would cause a recursive problem to solve,
|
-- this would cause a recursive problem to solve,
|
||||||
-- which is too much for our simple assembler.
|
-- which is too much for our simple assembler.
|
||||||
|
local plus_labels = {} -- constructed forwards
|
||||||
|
local minus_labels = {} -- constructed backwards
|
||||||
while true do
|
while true do
|
||||||
local tt, tok, fn, line = lex()
|
local tt, tok, fn, line = lex()
|
||||||
self.fn = fn
|
self.fn = fn
|
||||||
|
@ -1420,6 +1429,14 @@ function Parser:tokenize(asm)
|
||||||
self:error('expected number for define')
|
self:error('expected number for define')
|
||||||
end
|
end
|
||||||
self.defines[tok] = tok2
|
self.defines[tok] = tok2
|
||||||
|
elseif tt == 'RELLABEL' then
|
||||||
|
if tok == '+' then
|
||||||
|
insert(plus_labels, #self.tokens)
|
||||||
|
elseif tok == '-' then
|
||||||
|
insert(minus_labels, 1, #self.tokens)
|
||||||
|
else
|
||||||
|
error('Internal Error: unexpected token for relative label', 1)
|
||||||
|
end
|
||||||
elseif tt == 'EOL' then
|
elseif tt == 'EOL' then
|
||||||
-- noop
|
-- noop
|
||||||
elseif tt == 'EOF' then
|
elseif tt == 'EOF' then
|
||||||
|
@ -1431,7 +1448,7 @@ function Parser:tokenize(asm)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- resolve defines
|
-- resolve defines and relative labels
|
||||||
for i, t in ipairs(self.tokens) do
|
for i, t in ipairs(self.tokens) do
|
||||||
self.fn = t.fn
|
self.fn = t.fn
|
||||||
self.line = t.line
|
self.line = t.line
|
||||||
|
@ -1441,6 +1458,39 @@ function Parser:tokenize(asm)
|
||||||
if t.tok == nil then
|
if t.tok == nil then
|
||||||
self:error('undefined define') -- uhhh nice wording
|
self:error('undefined define') -- uhhh nice wording
|
||||||
end
|
end
|
||||||
|
elseif t.tt == 'RELLABEL' then
|
||||||
|
t.tt = 'LABEL'
|
||||||
|
-- exploits the fact that user labels can't begin with a number
|
||||||
|
t.tok = tostring(i)
|
||||||
|
elseif t.tt == 'RELLABELSYM' then
|
||||||
|
t.tt = 'LABELSYM'
|
||||||
|
local rel = t.tok
|
||||||
|
local seen = 0
|
||||||
|
-- TODO: don't iterate over *every* label, just the ones nearby
|
||||||
|
if rel > 0 then
|
||||||
|
for _, label_i in ipairs(plus_labels) do
|
||||||
|
if label_i > i then
|
||||||
|
seen = seen + 1
|
||||||
|
if seen == rel then
|
||||||
|
t.tok = tostring(label_i)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for _, label_i in ipairs(minus_labels) do
|
||||||
|
if label_i < i then
|
||||||
|
seen = seen - 1
|
||||||
|
if seen == rel then
|
||||||
|
t.tok = tostring(label_i)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if seen ~= rel then
|
||||||
|
self:error('could not find appropriate relative label')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user