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

use coroutines to lex

this will be relevant due time.
This commit is contained in:
Connor Olding 2015-11-26 18:45:45 -08:00
parent 82af3d531e
commit fa12154420

View file

@ -589,13 +589,14 @@ function Lexer:read_number()
end end
end end
function Lexer:lex() function Lexer:lex(yield)
while true do while true do
if self.chr == '\n' then if self.chr == '\n' then
self:nextc() self:nextc()
return 'EOL', '\n' yield('EOL', '\n')
elseif self.ord == self.EOF then elseif self.ord == self.EOF then
return 'EOF', self.EOF yield('EOF', self.EOF)
break
elseif self.chr == ';' then elseif self.chr == ';' then
self:skip_to_EOL() self:skip_to_EOL()
elseif self.chrchr == '//' then elseif self.chrchr == '//' then
@ -606,7 +607,7 @@ function Lexer:lex()
self:nextc() self:nextc()
elseif self.chr == ',' then elseif self.chr == ',' then
self:nextc() self:nextc()
return 'SEP', ',' yield('SEP', ',')
elseif self.chr == '[' then elseif self.chr == '[' then
self.buff = '' self.buff = ''
self:nextc() self:nextc()
@ -619,7 +620,7 @@ function Lexer:lex()
self:error('define requires a colon') self:error('define requires a colon')
end end
self:nextc() self:nextc()
return 'DEF', self.buff yield('DEF', self.buff)
elseif self.chr == '(' then elseif self.chr == '(' then
self.buff = '' self.buff = ''
self:nextc() self:nextc()
@ -632,7 +633,7 @@ function Lexer:lex()
if not all_registers[up] then if not all_registers[up] then
self:error('not a register') self:error('not a register')
end end
return 'DEREF', up yield('DEREF', up)
elseif self.chr == '.' then elseif self.chr == '.' then
self.buff = '' self.buff = ''
self:nextc() self:nextc()
@ -642,36 +643,36 @@ function Lexer:lex()
self:error('not a directive') self:error('not a directive')
end end
if up == 'INC' or up == 'INCASM' or up == 'INCLUDE' then if up == 'INC' or up == 'INCASM' or up == 'INCLUDE' then
return 'DIR', 'UP' yield('DIR', 'UP')
else
yield('DIR', up)
end end
return 'DIR', up
elseif self.chr == '@' then elseif self.chr == '@' then
self.buff = '' self.buff = ''
self:nextc() self:nextc()
self:read_chars('[%w_]') self:read_chars('[%w_]')
return 'DEFSYM', self.buff yield('DEFSYM', self.buff)
elseif self.chr:find('[%a_]') then elseif self.chr:find('[%a_]') then
self.buff = '' self.buff = ''
self:read_chars('[%w_.]') self:read_chars('[%w_.]')
local up = self.buff:upper()
if self.chr == ':' then if self.chr == ':' then
if self.buff:find('%.') then if self.buff:find('%.') then
self:error('labels cannot contain dots') self:error('labels cannot contain dots')
end end
self:nextc() self:nextc()
return 'LABEL', self.buff yield('LABEL', self.buff)
end elseif up == 'HEX' then
local up = self.buff:upper() yield('DIR', up)
if up == 'HEX' then
return 'DIR', up
elseif all_registers[up] then elseif all_registers[up] then
return 'REG', up yield('REG', up)
elseif all_instructions[up] then elseif all_instructions[up] then
return 'INSTR', up:gsub('%.', '_') yield('INSTR', up:gsub('%.', '_'))
else else
if self.buff:find('%.') then if self.buff:find('%.') then
self:error('labels cannot contain dots') self:error('labels cannot contain dots')
end end
return 'LABELSYM', self.buff yield('LABELSYM', self.buff)
end end
elseif self.chr == ']' then elseif self.chr == ']' then
self:error('unmatched closing bracket') self:error('unmatched closing bracket')
@ -681,19 +682,20 @@ function Lexer:lex()
self:nextc() self:nextc()
local n = self:read_number() local n = self:read_number()
if n then if n then
return 'NUM', -n yield('NUM', -n)
else else
self:error('expected number after minus sign') self:error('expected number after minus sign')
end end
else else
local n = self:read_number() local n = self:read_number()
if n then if n then
return 'NUM', n yield('NUM', n)
end else
self:error('unknown character or control character') self:error('unknown character or control character')
end end
end end
end end
end
function Parser:error(msg) function Parser:error(msg)
error(string.format('%s:%d: Error: %s', self.fn, self.line, msg), 2) error(string.format('%s:%d: Error: %s', self.fn, self.line, msg), 2)
@ -1078,14 +1080,22 @@ function Parser:instruction()
end end
function Parser:tokenize() function Parser:tokenize()
local lexer = Lexer(self.asm, self.fn)
self.tokens = {} self.tokens = {}
self.i = 0 self.i = 0
local line = 1 local line = 1
local routine = coroutine.create(function()
local lexer = Lexer(self.asm, self.fn)
lexer:lex(coroutine.yield)
end)
local lex = function() local lex = function()
local t = {line=line} local t = {line=line}
t.tt, t.tok = lexer:lex() local ok
ok, t.tt, t.tok = coroutine.resume(routine)
if not ok then
error('Internal Error: lexer coroutine has stopped')
end
table.insert(self.tokens, t) table.insert(self.tokens, t)
return t.tt, t.tok return t.tt, t.tok
end end
@ -1124,7 +1134,6 @@ function Parser:tokenize()
end end
end end
end end
return t
end end
function Parser:parse(asm) function Parser:parse(asm)