From f160a00a1472485a3aadff2a73cc201c84e8a87c Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Wed, 3 Apr 2024 23:34:19 -0500 Subject: Refactor literals reading and implement number literals that is, #b, #o, #d, #x --- read.lua | 64 ++++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/read.lua b/read.lua index 6b223f8..4fb9b70 100644 --- a/read.lua +++ b/read.lua @@ -44,7 +44,6 @@ function m.inport (source, kind) tok, toktype, self.line = m.scan(self.line)() if tok ~= nil then - print(tok, toktype) return tok, toktype end end @@ -96,6 +95,37 @@ local function consume_comment (cs) return table.concat(comment), "comment", cs end +local function idf (x) + return function () return x end +end + +local function numf (base) + return function (token) + local n = tonumber(token:sub(3), base) + assert(n, "Can't read number: " .. token) + return n + end +end + +local literals = { + literal = { + ["#t"] = idf(true), + ["#true"] = idf(true), + ["#f"] = idf(false), + ["#false"] = idf(false), + ["#\\space"] = idf(t.character(" ")), + ["#\\tab"] = idf(t.character("\t")), + ["#\\newline"] = idf(t.character("\n")), + }, + match = { + ["^#b"] = numf(2), + ["^#o"] = numf(8), + ["^#d"] = numf(10), + ["^#x"] = numf(16), + ["^#\\"] = function (tok) return t.character(tok:sub(3)) end, + } +} + local function consume_literal (cs) -- whitespace and parantheses character literals. -- reverse the match test b/c it's already a complement @@ -105,26 +135,20 @@ local function consume_literal (cs) pop(cs) -- discard '#' local token, value, cs = consume_token(cs) -- todo: vectors #(...) token = "#" .. token -- put '#' back - -- tokens! - if token == "#t" or token == "#true" then -- booleans - value = true - elseif token == "#f" or token == "#false" then - value = false - --[[ To actually *read* nil, I need to change ports from - returning `nil' on eof to an `eof' symbol, i think. - - elseif token == "#n" or token == "#nil" then - value = nil - --]] - elseif token == "#\\space" then -- characters - value = type.character(" ") - elseif token == "#\\newline" then - value = type.character("\n") - elseif token:match("^#\\") then - value = type.character(token:sub(3)) + + if literals.literal[token] then + value = literals.literal[token]() else - error("Bad literal notation: " .. token) + for re, fn in pairs(literals.match) do + if token:match(re) then + value = fn(token) + end + end end + -- TODO : if `nil' is to be a value in lam i'm going to have to figure + -- out some kind of 'lam nil' and 'lua nil' or something.. + assert(value~=nil, "Can't read literal: " .. token) + return value, "literal", cs end @@ -208,7 +232,7 @@ m.readmacros = { table.insert(Q, m.read(port)) return t.list(Q) end, - comment = function () return nil end, + comment = idf(nil), } function m.read (port) -- cgit 1.4.1-21-gabe81