1
0
Fork 0
mirror of https://github.com/notwa/lips synced 2024-11-14 09:49:02 -08:00

add named relative labels

This commit is contained in:
Connor Olding 2016-04-10 05:08:41 -07:00
parent a58ad83c92
commit b8601031f3
2 changed files with 51 additions and 17 deletions

View file

@ -396,21 +396,25 @@ function Lexer:lex(_yield)
elseif self.chr == '+' or self.chr == '-' then
local sign_chr = self.chr
local sign = sign_chr == '+' and 1 or -1
local buff = self:read_chars('%'..self.chr)
if #buff == 1 and self.chr == ':' then
local signs = self:read_chars('%'..self.chr)
local name = ''
if self.chr:find('[%a_]') then
name = self:read_chars('[%w_]')
end
if #signs == 1 and self.chr == ':' then
self:nextc()
yield('RELLABEL', sign_chr)
yield('RELLABEL', signs..name)
else
self:read_spaces()
local n = self:read_number()
if n then
yield('NUM', sign*n)
elseif #buff == 1 then
elseif #signs == 1 and name == '' then
-- this could be a RELLABELSYM
-- we'll have to let the preproc figure it out
yield('UNARY', sign)
else
yield('RELLABELSYM', sign*#buff)
yield('RELLABELSYM', signs..name)
end
end
else

View file

@ -5,6 +5,27 @@ local util = require "lips.util"
local Muncher = require "lips.Muncher"
local Token = require "lips.Token"
local abs = math.abs
local function signs(s)
local start, end_ = s:find('[+-]+')
if start ~= 1 then
return 0
end
if s:sub(1, 1) == '+' then
return end_
elseif s:sub(1, 1) == '-' then
return -end_
end
end
local function RelativeLabel(index, name)
return {
index = index,
name = name,
}
end
local Preproc = util.Class(Muncher)
function Preproc:init(options)
self.options = options or {}
@ -30,6 +51,7 @@ function Preproc:process(tokens)
self:error('unary operators cannot be chained')
elseif peek.tt == 'EOL' or peek.tt == 'SEP' then
t.tt = 'RELLABELSYM'
t.tok = sign == 1 and '+' or sign == -1 and '-'
elseif peek.tt == 'DEFSYM' then
t = self:advance()
else
@ -52,10 +74,12 @@ function Preproc:process(tokens)
end
insert(new_tokens, self:token(tt, tok * sign))
elseif t.tt == 'RELLABEL' then
if t.tok == '+' then
insert(plus_labels, #new_tokens + 1)
elseif t.tok == '-' then
insert(minus_labels, 1, #new_tokens + 1)
local label = t.tok or ''
local rl = RelativeLabel(#new_tokens + 1, label:sub(2))
if label:sub(1, 1) == '+' then
insert(plus_labels, rl)
elseif label:sub(1, 1) == '-' then
insert(minus_labels, rl)
else
error('Internal Error: unexpected token for relative label')
end
@ -72,29 +96,35 @@ function Preproc:process(tokens)
if t.tt == 'RELLABEL' then
t.tt = 'LABEL'
-- exploits the fact that user labels can't begin with a number
t.tok = tostring(i)
local name = t.tok:sub(2)
t.tok = tostring(i)..name
elseif t.tt == 'RELLABELSYM' then
t.tt = 'LABELSYM'
local rel = t.tok
local rel = signs(t.tok)
if rel == 0 then
error('Internal Error: relative label without signs')
end
local name = t.tok:sub(abs(rel) + 1)
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
for _, rl in ipairs(plus_labels) do
if rl.name == name and rl.index > i then
seen = seen + 1
if seen == rel then
t.tok = tostring(label_i)
t.tok = tostring(rl.index)..name
break
end
end
end
else
for _, label_i in ipairs(minus_labels) do
if label_i < i then
for _, rl in ipairs(minus_labels) do
if rl.name == name and rl.index < i then
seen = seen - 1
if seen == rel then
t.tok = tostring(label_i)
t.tok = tostring(rl.index)..name
break
end
end