diff options
author | Case Duckworth | 2024-03-31 22:16:37 -0500 |
---|---|---|
committer | Case Duckworth | 2024-03-31 22:16:37 -0500 |
commit | 4eaaedc486d60fde724abf1af70e21fc2b3e5c49 (patch) | |
tree | 491e0e61632cb9595a2dd7ba8dda0c20b2bfc882 | |
parent | Error on unbound variables (diff) | |
download | lam-4eaaedc486d60fde724abf1af70e21fc2b3e5c49.tar.gz lam-4eaaedc486d60fde724abf1af70e21fc2b3e5c49.zip |
Add rest of quotes to reader
-rw-r--r-- | read.lua | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/read.lua b/read.lua index a41816f..f8d6b09 100644 --- a/read.lua +++ b/read.lua | |||
@@ -7,6 +7,12 @@ local pop = require("util").pop | |||
7 | 7 | ||
8 | local pp = require("pp").pp | 8 | local pp = require("pp").pp |
9 | 9 | ||
10 | -- TODO: | ||
11 | -- - string reading | ||
12 | -- - # syntax | ||
13 | -- - comments | ||
14 | -- - probably more | ||
15 | |||
10 | function m.inport (source, kind) | 16 | function m.inport (source, kind) |
11 | -- KIND can be one of "file", "string"; defaults to "file" | 17 | -- KIND can be one of "file", "string"; defaults to "file" |
12 | -- SOURCE is the name of the file or the string to read, or nil; if nil, | 18 | -- SOURCE is the name of the file or the string to read, or nil; if nil, |
@@ -85,6 +91,18 @@ end | |||
85 | m.readtable = { | 91 | m.readtable = { |
86 | ["("] = function (cs) return pop(cs), "open", cs end, | 92 | ["("] = function (cs) return pop(cs), "open", cs end, |
87 | [")"] = function (cs) return pop(cs), "close", cs end, | 93 | [")"] = function (cs) return pop(cs), "close", cs end, |
94 | ["'"] = function (cs) return pop(cs), "quote", cs end, | ||
95 | ["`"] = function (cs) return pop(cs), "quote", cs end, | ||
96 | [","] = | ||
97 | function (cs) | ||
98 | pop(cs) -- remove ',' | ||
99 | if cs[1] == "@" then | ||
100 | pop(cs) -- remove '@' | ||
101 | return ",@", "quote", cs | ||
102 | else | ||
103 | return ",", "quote", cs | ||
104 | end | ||
105 | end, | ||
88 | } | 106 | } |
89 | 107 | ||
90 | -- Return an iterator over a character table, so you can do: | 108 | -- Return an iterator over a character table, so you can do: |
@@ -131,6 +149,24 @@ function m.readchar (port) | |||
131 | end | 149 | end |
132 | end | 150 | end |
133 | 151 | ||
152 | m.readmacros = { | ||
153 | quote = | ||
154 | function (tok, toktype, port) | ||
155 | local qs = { | ||
156 | ["'"] = "quote", | ||
157 | ["`"] = "quasiquote", | ||
158 | [","] = "unquote", | ||
159 | [",@"] = "unquote-splicing", | ||
160 | } | ||
161 | if not qs[tok] then | ||
162 | error(string.format("Bad quote: '%s'\n", tok)) | ||
163 | end | ||
164 | local Q = {qs[tok]} | ||
165 | table.insert(Q, m.read(port)) | ||
166 | return t.list(Q) | ||
167 | end, | ||
168 | } | ||
169 | |||
134 | function m.read (port) | 170 | function m.read (port) |
135 | local function read_ahead (tok, toktype) | 171 | local function read_ahead (tok, toktype) |
136 | if not tok then error("Unexpected EOF") end | 172 | if not tok then error("Unexpected EOF") end |
@@ -151,6 +187,8 @@ function m.read (port) | |||
151 | end | 187 | end |
152 | elseif toktype == "close" then | 188 | elseif toktype == "close" then |
153 | error("Unexpected ')'") | 189 | error("Unexpected ')'") |
190 | elseif m.readmacros[toktype] then | ||
191 | return m.readmacros[toktype](tok, toktype, port) | ||
154 | else return tok | 192 | else return tok |
155 | end | 193 | end |
156 | end | 194 | end |