1
0
Fork 0
mirror of https://github.com/notwa/lips synced 2024-05-17 16:03:24 -07: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 elseif self.chr == '+' or self.chr == '-' then
local sign_chr = self.chr local sign_chr = self.chr
local sign = sign_chr == '+' and 1 or -1 local sign = sign_chr == '+' and 1 or -1
local buff = self:read_chars('%'..self.chr) local signs = self:read_chars('%'..self.chr)
if #buff == 1 and self.chr == ':' then local name = ''
if self.chr:find('[%a_]') then
name = self:read_chars('[%w_]')
end
if #signs == 1 and self.chr == ':' then
self:nextc() self:nextc()
yield('RELLABEL', sign_chr) yield('RELLABEL', signs..name)
else else
self:read_spaces() self:read_spaces()
local n = self:read_number() local n = self:read_number()
if n then if n then
yield('NUM', sign*n) yield('NUM', sign*n)
elseif #buff == 1 then elseif #signs == 1 and name == '' then
-- this could be a RELLABELSYM -- this could be a RELLABELSYM
-- we'll have to let the preproc figure it out -- we'll have to let the preproc figure it out
yield('UNARY', sign) yield('UNARY', sign)
else else
yield('RELLABELSYM', sign*#buff) yield('RELLABELSYM', signs..name)
end end
end end
else else

View File

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