From 693294bef2d6ab7a6f157a92cdc6f6dfa4c9b126 Mon Sep 17 00:00:00 2001 From: Connor Olding Date: Sun, 24 Apr 2016 04:41:30 -0700 Subject: [PATCH] fix labels and variables in data directives --- lips/Collector.lua | 33 +++++++++++++++++++++++---------- lips/Dumper.lua | 6 +++++- lips/util.lua | 19 +++++++++++++++++-- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/lips/Collector.lua b/lips/Collector.lua index 0e3a5b2..a3a8a51 100644 --- a/lips/Collector.lua +++ b/lips/Collector.lua @@ -35,6 +35,10 @@ function Collector:push_data(datum, size) -- TODO: consider not scrunching data statements, just their tokens + if type(datum) == 'number' then + datum = self:token(datum) + end + local last_statement = self.statements[#self.statements] local s if last_statement and last_statement.type == '!DATA' then @@ -44,16 +48,25 @@ function Collector:push_data(datum, size) insert(self.statements, s) end - if type(datum) == 'string' and size == 'WORD' then - -- labels will be assembled to words - insert(s, Token('LABEL', datum)) - return - end - if size ~= 'BYTE' and size ~= 'HALFWORD' and size ~= 'WORD' then error('Internal Error: unknown data size argument') end + if datum.tt == 'LABELSYM' then + if size == 'WORD' then + -- labels will be assembled to words + insert(s, datum) + return + else + self:error('labels are too large to be used in this directive') + end + elseif datum.tt == 'VARSYM' then + insert(s, datum:set('size', size)) + return + elseif datum.tt ~= 'NUM' then + self:error('unsupported data type', datum.tt) + end + local sizes = size..'S' local last_token = s[#s] @@ -65,7 +78,7 @@ function Collector:push_data(datum, size) insert(s, t) s:validate() end - insert(t.tok, datum) + insert(t.tok, datum.tok) end function Collector:variable() @@ -104,10 +117,10 @@ function Collector:directive() end end elseif name == 'BYTE' or name == 'HALFWORD' or name == 'WORD' then - self:push_data(self:const().tok, name) + self:push_data(self:const(), name) while not self:is_EOL() do self:optional_comma() - self:push_data(self:const().tok, name) + self:push_data(self:const(), name) end elseif name == 'HEX' then if self.tt ~= 'OPEN' then @@ -119,7 +132,7 @@ function Collector:directive() if self.tt == 'EOL' then self:advance() else - self:push_data(self:const().tok, 'BYTE') + self:push_data(self:const(), 'BYTE') end end self:advance() diff --git a/lips/Dumper.lua b/lips/Dumper.lua index 3563eaf..6a7c0db 100644 --- a/lips/Dumper.lua +++ b/lips/Dumper.lua @@ -365,13 +365,17 @@ function Dumper:load(statements) insert(new_statements, new) elseif s.type == '!DATA' then for i, t in ipairs(s) do - if t.tt == 'LABEL' then + if t.tt == 'LABELSYM' then local label = self.labels[t.tok] if label == nil then self:error('undefined label', t.tok) end t.tt = 'WORDS' t.tok = {label} + elseif t.tt == 'NUM' then + t.tt = t.size..'S' + t.tok = {t.tok} + t.size = nil end end self.pos = self.pos + (s.length or util.measure_data(s)) diff --git a/lips/util.lua b/lips/util.lua index 4b80607..145ecca 100644 --- a/lips/util.lua +++ b/lips/util.lua @@ -39,12 +39,27 @@ else -- 5.2, 5.3 end end +local data_sizes = { + BYTE = 1, + HALFWORD = 2, + WORD = 4, +} + local function measure_data(s) assert(s and s.type == '!DATA', 'Internal Error: expected !DATA statement') local n = 0 for i, t in ipairs(s) do - if t.tt == 'LABEL' then + if t.tt == 'LABELSYM' then n = n + 4 + elseif t.tt == 'NUM' then + if t.size == nil then + error('Internal Error: unspecified data size in NUM') + end + local size = data_sizes[t.size] + if size == nil then + error('Internal Error: unknown data size in NUM, got '..tostring(t.size)) + end + n = n + size elseif t.tt == 'WORDS' then n = n + #t.tok * 4 elseif t.tt == 'HALFWORDS' then @@ -52,7 +67,7 @@ local function measure_data(s) elseif t.tt == 'BYTES' then n = n + #t.tok * 1 else - error('Internal Error: unknown data type in !DATA') + error('Internal Error: unknown data type in !DATA, got '..tostring(t.tt)) end end return n