2016-01-13 07:56:18 -08:00
|
|
|
local insert = table.insert
|
|
|
|
|
2016-04-21 13:04:49 -07:00
|
|
|
local path = string.gsub(..., "[^.]+$", "")
|
|
|
|
local Base = require(path.."Base")
|
|
|
|
local Token = require(path.."Token")
|
|
|
|
local Lexer = require(path.."Lexer")
|
|
|
|
local Collector = require(path.."Collector")
|
|
|
|
local Preproc = require(path.."Preproc")
|
2016-11-27 06:09:18 -08:00
|
|
|
local Expander = require(path.."Expander")
|
2016-04-21 13:04:49 -07:00
|
|
|
local Dumper = require(path.."Dumper")
|
|
|
|
|
|
|
|
local Parser = Base:extend()
|
2016-01-13 07:56:18 -08:00
|
|
|
function Parser:init(writer, fn, options)
|
2016-04-21 13:04:49 -07:00
|
|
|
self.writer = writer
|
2016-01-13 07:56:18 -08:00
|
|
|
self.fn = fn or '(string)'
|
|
|
|
self.main_fn = self.fn
|
|
|
|
self.options = options or {}
|
|
|
|
end
|
|
|
|
|
2016-04-21 13:04:49 -07:00
|
|
|
function Parser:tokenize(asm)
|
|
|
|
local lexer = Lexer(asm, self.main_fn, self.options)
|
|
|
|
local tokens = {}
|
2016-01-13 07:56:18 -08:00
|
|
|
|
2016-04-21 13:04:49 -07:00
|
|
|
local loop = true
|
|
|
|
while loop do
|
|
|
|
lexer:lex(function(tt, tok, fn, line)
|
|
|
|
assert(tt, 'Internal Error: missing token')
|
|
|
|
local t = Token(fn, line, tt, tok)
|
|
|
|
insert(tokens, t)
|
|
|
|
-- don't break if this is an included file's EOF
|
|
|
|
if tt == 'EOF' and fn == self.main_fn then
|
|
|
|
loop = false
|
|
|
|
end
|
|
|
|
end)
|
2016-01-13 07:56:18 -08:00
|
|
|
end
|
|
|
|
|
2016-04-21 13:04:49 -07:00
|
|
|
-- the lexer guarantees an EOL and EOF for a blank file
|
|
|
|
assert(#tokens > 0, 'Internal Error: no tokens after preprocessing')
|
2016-01-13 07:56:18 -08:00
|
|
|
|
2016-04-21 13:04:49 -07:00
|
|
|
local collector = Collector(self.options)
|
2016-11-27 06:09:18 -08:00
|
|
|
return collector:collect(tokens, self.main_fn)
|
2016-01-13 07:56:18 -08:00
|
|
|
end
|
|
|
|
|
2016-11-27 06:09:18 -08:00
|
|
|
function Parser:dump()
|
2016-04-21 13:04:49 -07:00
|
|
|
for i, s in ipairs(self.statements) do
|
2016-11-27 06:09:18 -08:00
|
|
|
print(s.line, s.type, s:dump())
|
2016-01-13 07:56:18 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-04-21 13:04:49 -07:00
|
|
|
function Parser:parse(asm)
|
2016-11-27 06:09:18 -08:00
|
|
|
self.statements = self:tokenize(asm)
|
|
|
|
if self.options.debug_token then self:dump() end
|
2016-01-13 07:56:18 -08:00
|
|
|
|
2016-11-27 06:09:18 -08:00
|
|
|
self.statements = Preproc(self.options):process(self.statements)
|
|
|
|
if self.options.debug_pre then self:dump() end
|
2016-01-13 07:56:18 -08:00
|
|
|
|
2016-11-27 06:09:18 -08:00
|
|
|
self.statements = Expander(self.options):expand(self.statements)
|
|
|
|
if self.options.debug_post then self:dump() end
|
2016-04-26 14:48:39 -07:00
|
|
|
|
2016-04-21 13:04:49 -07:00
|
|
|
local dumper = Dumper(self.writer, self.options)
|
|
|
|
self.statements = dumper:load(self.statements)
|
2016-11-27 06:09:18 -08:00
|
|
|
if self.options.debug_asm then self:dump() end
|
2016-01-13 11:20:28 -08:00
|
|
|
|
2016-04-10 06:07:06 -07:00
|
|
|
if self.options.labels then
|
2016-04-21 13:04:49 -07:00
|
|
|
dumper:export_labels(self.options.labels)
|
2016-04-10 06:07:06 -07:00
|
|
|
end
|
2016-04-21 13:04:49 -07:00
|
|
|
return dumper:dump()
|
2016-01-13 07:56:18 -08:00
|
|
|
end
|
|
|
|
|
|
|
|
return Parser
|