mirror of
https://github.com/notwa/lips
synced 2024-11-14 09:49:02 -08:00
implement ascii/asciiz directives, basic string lexing
This commit is contained in:
parent
5e12951010
commit
a47c924e75
4 changed files with 86 additions and 13 deletions
11
README.md
11
README.md
|
@ -145,14 +145,17 @@ include an external assembly file as-is at this position.
|
|||
lips will look for the included file
|
||||
in the directory of the file using the directive.
|
||||
|
||||
* `.ascii "some\ntext\0"`
|
||||
writes a string using its characters' ASCII values.
|
||||
a few escapes are currently supported: `\ " a b f n r t v 0`
|
||||
|
||||
* `.asciiz "some\ntext"`
|
||||
same as ascii, but with a null byte added to the end.
|
||||
|
||||
### Unimplemented
|
||||
|
||||
* FLOAT: writes a list of 32-bit floating point numbers until end-of-line.
|
||||
this may not get implemented due to a lack of aliasing in vanilla Lua,
|
||||
and thus accuracy issues.
|
||||
|
||||
* ASCII: writes a string using its characters' ASCII values.
|
||||
|
||||
* ASCIIZ: same as ASCII, but with a null byte added to the end.
|
||||
|
||||
* INCBIN: write an external binary file as-is at this position.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
local insert = table.insert
|
||||
local floor = math.floor
|
||||
local format = string.format
|
||||
local insert = table.insert
|
||||
|
||||
local data = require "lips.data"
|
||||
|
||||
|
|
|
@ -1,10 +1,25 @@
|
|||
local byte = string.byte
|
||||
local char = string.char
|
||||
local find = string.find
|
||||
local format = string.format
|
||||
local insert = table.insert
|
||||
local open = io.open
|
||||
|
||||
local data = require "lips.data"
|
||||
|
||||
local simple_escapes = {
|
||||
['0'] = 0x00,
|
||||
['\\'] = 0x5C,
|
||||
['"'] = 0x22,
|
||||
['a'] = 0x07,
|
||||
['b'] = 0x08,
|
||||
['f'] = 0x0C,
|
||||
['n'] = 0x0A,
|
||||
['r'] = 0x0D,
|
||||
['t'] = 0x09,
|
||||
['v'] = 0x0B,
|
||||
}
|
||||
|
||||
local function readfile(fn)
|
||||
local f = open(fn, 'r')
|
||||
if not f then
|
||||
|
@ -208,12 +223,48 @@ end
|
|||
function Lexer:lex_string(yield)
|
||||
-- TODO: support escaping
|
||||
if self.chr ~= '"' then
|
||||
self:error("expected opening double quote")
|
||||
self:error('expected opening double quote')
|
||||
end
|
||||
self:nextc()
|
||||
|
||||
local bytes = {}
|
||||
while true do
|
||||
if self.chr == '\n' then
|
||||
self:error('unimplemented')
|
||||
self:nextc()
|
||||
yield('EOL', '\n')
|
||||
elseif self.ord == self.EOF then
|
||||
self:nextc()
|
||||
self:error('unexpected EOF; incomplete string')
|
||||
elseif self.chr == '"' then
|
||||
self:nextc()
|
||||
break
|
||||
elseif self.chr == '\\' then
|
||||
self:nextc()
|
||||
local simple = simple_escapes[self.chr]
|
||||
if simple then
|
||||
insert(bytes, simple)
|
||||
else
|
||||
self:error('unknown escape sequence')
|
||||
end
|
||||
self:nextc()
|
||||
else
|
||||
insert(bytes, byte(self.chr))
|
||||
self:nextc()
|
||||
end
|
||||
end
|
||||
|
||||
yield('STRING', bytes)
|
||||
end
|
||||
|
||||
function Lexer:lex_string_naive(yield) -- no escape sequences
|
||||
if self.chr ~= '"' then
|
||||
self:error('expected opening double quote')
|
||||
end
|
||||
self:nextc()
|
||||
local buff = self:read_chars('[^"\n]')
|
||||
if self.chr ~= '"' then
|
||||
self:error("expected closing double quote")
|
||||
self:error('expected closing double quote')
|
||||
end
|
||||
self:nextc()
|
||||
yield('STRING', buff)
|
||||
|
@ -222,7 +273,7 @@ end
|
|||
function Lexer:lex_include(_yield)
|
||||
self:read_chars('%s')
|
||||
local fn
|
||||
self:lex_string(function(tt, tok)
|
||||
self:lex_string_naive(function(tt, tok)
|
||||
fn = tok
|
||||
end)
|
||||
if self.options.path then
|
||||
|
@ -293,6 +344,8 @@ function Lexer:lex(_yield)
|
|||
else
|
||||
yield('DIR', up)
|
||||
end
|
||||
elseif self.chr == '"' then
|
||||
self:lex_string(yield)
|
||||
elseif self.chr == '@' then
|
||||
self:nextc()
|
||||
local buff = self:read_chars('[%w_]')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
local insert = table.insert
|
||||
local format = string.format
|
||||
local insert = table.insert
|
||||
|
||||
local data = require "lips.data"
|
||||
local overrides = require "lips.overrides"
|
||||
|
@ -57,6 +57,15 @@ function Parser:number()
|
|||
return value
|
||||
end
|
||||
|
||||
function Parser:string()
|
||||
if self.tt ~= 'STRING' then
|
||||
self:error('expected string')
|
||||
end
|
||||
local value = self.tok
|
||||
self:advance()
|
||||
return value
|
||||
end
|
||||
|
||||
function Parser:directive()
|
||||
local name = self.tok
|
||||
self:advance()
|
||||
|
@ -84,13 +93,20 @@ function Parser:directive()
|
|||
self.dumper:add_directive(line, name, self:number())
|
||||
end
|
||||
self:expect_EOL()
|
||||
elseif name == 'HEX' then
|
||||
self:error('unimplemented')
|
||||
elseif name == 'INC' then
|
||||
-- noop
|
||||
-- noop, handled by lexer
|
||||
elseif name == 'ASCII' or name == 'ASCIIZ' then
|
||||
local bytes = self:string()
|
||||
for i, number in ipairs(bytes) do
|
||||
self.dumper:add_directive(line, 'BYTE', number)
|
||||
end
|
||||
if name == 'ASCIIZ' then
|
||||
self.dumper:add_directive(line, 'BYTE', 0)
|
||||
end
|
||||
self:expect_EOL()
|
||||
elseif name == 'INCBIN' then
|
||||
self:error('unimplemented')
|
||||
elseif name == 'FLOAT' or name == 'ASCII' or name == 'ASCIIZ' then
|
||||
elseif name == 'FLOAT' then
|
||||
self:error('unimplemented')
|
||||
else
|
||||
self:error('unknown directive')
|
||||
|
|
Loading…
Reference in a new issue