about summary refs log tree commit diff stats
path: root/read.lua
diff options
context:
space:
mode:
authorCase Duckworth2024-02-21 09:28:49 -0600
committerCase Duckworth2024-02-21 09:28:49 -0600
commit70ec5254814f9531e5ca2024465d0e01130306b7 (patch)
tree45a4d49115eca436a8467ce4cebfc8cee1f6f9c6 /read.lua
downloadlam-70ec5254814f9531e5ca2024465d0e01130306b7.tar.gz
lam-70ec5254814f9531e5ca2024465d0e01130306b7.zip
Initial commit
Diffstat (limited to 'read.lua')
-rw-r--r--read.lua74
1 files changed, 74 insertions, 0 deletions
diff --git a/read.lua b/read.lua new file mode 100644 index 0000000..72bbd4d --- /dev/null +++ b/read.lua
@@ -0,0 +1,74 @@
1--- lam.read
2
3local read = {}
4
5local types = require "types"
6local util = require "util"
7
8function read.tokenize (str)
9 --[[ Convert a string of characters into a list of tokens ]]
10 assert(str, "No program given")
11 local tbl = {}
12 local word = ""
13 local push_word =
14 function ()
15 if word:len() > 0 then
16 table.insert(tbl, word)
17 word = ""
18 end
19 end
20
21 for c = 1, #str do
22 char = string.char(str:byte(c))
23 if char == " " or char == "\t" or char == "\n" then
24 push_word()
25 elseif char == "(" then
26 push_word()
27 table.insert(tbl, "(")
28 elseif char == ")" then
29 push_word()
30 table.insert(tbl, ")")
31 else
32 word = word .. char
33 end
34 end
35 push_word()
36 return tbl
37end
38
39function read.read (str)
40 -- [[ Read a scheme expression from a string ]]
41
42 local function Atom (token)
43 local n = tonumber(token)
44 if n then return n
45 else return tostring(token)
46 end
47 end
48
49 local function read_tokens (tokens)
50 --[[ Read a list of tokens from `tokenize' ]]
51 assert(next(tokens), "Unexpected EOF")
52 token = util.pop(tokens)
53 if token == "(" then
54 local L = {}
55 while tokens[1] ~= ")" do
56 table.insert(L, read_tokens(tokens))
57 end
58 util.pop(tokens) -- remove ")"
59 return L
60 elseif token == ")" then
61 error("Unexpected ')'")
62 else
63 return Atom(token)
64 end
65 end
66
67 return read_tokens(read.tokenize(str))
68end
69
70return setmetatable(read, { __call =
71 function(_, str)
72 return read.read(str)
73 end,
74})