1
0
Fork 0
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:
Connor Olding 2016-01-13 11:18:36 -08:00
parent 5e12951010
commit a47c924e75
4 changed files with 86 additions and 13 deletions

View file

@ -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.

View file

@ -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"

View file

@ -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_]')

View file

@ -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')