1
0
Fork 0
mirror of https://github.com/notwa/lips synced 2024-05-20 17:13:23 -07: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 lips will look for the included file
in the directory of the file using the directive. 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 ### Unimplemented
* FLOAT: writes a list of 32-bit floating point numbers until end-of-line. * 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, this may not get implemented due to a lack of aliasing in vanilla Lua,
and thus accuracy issues. 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. * 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 floor = math.floor
local format = string.format
local insert = table.insert
local data = require "lips.data" local data = require "lips.data"

View File

@ -1,10 +1,25 @@
local byte = string.byte local byte = string.byte
local char = string.char local char = string.char
local find = string.find local find = string.find
local format = string.format
local insert = table.insert
local open = io.open local open = io.open
local data = require "lips.data" 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 function readfile(fn)
local f = open(fn, 'r') local f = open(fn, 'r')
if not f then if not f then
@ -208,12 +223,48 @@ end
function Lexer:lex_string(yield) function Lexer:lex_string(yield)
-- TODO: support escaping -- TODO: support escaping
if self.chr ~= '"' then 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 end
self:nextc() self:nextc()
local buff = self:read_chars('[^"\n]') local buff = self:read_chars('[^"\n]')
if self.chr ~= '"' then if self.chr ~= '"' then
self:error("expected closing double quote") self:error('expected closing double quote')
end end
self:nextc() self:nextc()
yield('STRING', buff) yield('STRING', buff)
@ -222,7 +273,7 @@ end
function Lexer:lex_include(_yield) function Lexer:lex_include(_yield)
self:read_chars('%s') self:read_chars('%s')
local fn local fn
self:lex_string(function(tt, tok) self:lex_string_naive(function(tt, tok)
fn = tok fn = tok
end) end)
if self.options.path then if self.options.path then
@ -293,6 +344,8 @@ function Lexer:lex(_yield)
else else
yield('DIR', up) yield('DIR', up)
end end
elseif self.chr == '"' then
self:lex_string(yield)
elseif self.chr == '@' then elseif self.chr == '@' then
self:nextc() self:nextc()
local buff = self:read_chars('[%w_]') local buff = self:read_chars('[%w_]')

View File

@ -1,5 +1,5 @@
local insert = table.insert
local format = string.format local format = string.format
local insert = table.insert
local data = require "lips.data" local data = require "lips.data"
local overrides = require "lips.overrides" local overrides = require "lips.overrides"
@ -57,6 +57,15 @@ function Parser:number()
return value return value
end 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() function Parser:directive()
local name = self.tok local name = self.tok
self:advance() self:advance()
@ -84,13 +93,20 @@ function Parser:directive()
self.dumper:add_directive(line, name, self:number()) self.dumper:add_directive(line, name, self:number())
end end
self:expect_EOL() self:expect_EOL()
elseif name == 'HEX' then
self:error('unimplemented')
elseif name == 'INC' then 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 elseif name == 'INCBIN' then
self:error('unimplemented') self:error('unimplemented')
elseif name == 'FLOAT' or name == 'ASCII' or name == 'ASCIIZ' then elseif name == 'FLOAT' then
self:error('unimplemented') self:error('unimplemented')
else else
self:error('unknown directive') self:error('unknown directive')