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:
parent
a58ad83c92
commit
b8601031f3
2 changed files with 51 additions and 17 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue