2 Copyright (C) 2017-2018 Keziah Wesley
4 You can redistribute and/or modify this file under the terms of the
5 GNU Affero General Public License as published by the Free Software
6 Foundation, either version 3 of the License, or (at your option) any
9 This file is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Affero General Public License for more details.
14 You should have received a copy of the GNU Affero General Public
15 License along with this file. If not, see
16 <http://www.gnu.org/licenses/>.
30 // Return the number of whitespace characters at the beginning of the input.
32 count_whitespace (const char *p)
52 // Return the number of characters at the beginning of the input
53 // constituting a valid PNAME.
54 // If the input ends with '\', it is incomplete, and -1 is returned.
56 count_pname (const char *p)
58 // rule (1): valid FLOAT / FIX isn't a PNAME.
59 // Caller must try to read as number first!
61 // rule (2): dot can't be first
65 // rule (3): "if you can't type it interactively, it's only valid non-interactively"
66 // (not currently enforced; just don't give your atoms names like ^L)
72 // separators end the PNAME
73 // rule (4): whitespace
74 // rule (5): special characters
98 // escape: next char becomes normal
111 static uint32_t obj_get_fix32(const object *o) {
112 assert(o->type == EVALTYPE_FIX32);
118 read_num (const char *p, reader_stack * st)
121 // Use an unsigned intermediate to simplify overflow checks.
123 // Disallow "number" composed of ancillary number components only.
124 bool gotdigits = false;
125 // Skip for now, later we'll check again to potentially negate.
128 // TODO: asterisk-deliminated *octal*
129 // TODO: other bases?
132 if (p[i] >= '0' && p[i] <= '9')
134 if (x * 10 + (p[i] - '0') < x)
136 x = x * 10 + (p[i] - '0');
141 // TODO: decimal points, exponent notation
142 // NB. a terminal decimal denotes a FIX
143 // NB. exponent notation doesn't necessarily indicate a float
145 // TODO: distinguish 'delimiter' characters that terminate
146 // number from 'identifier' chars that cause parsing to fail
147 // (and potentially be parsed as an atom)
155 (--(st->pos))->fix32 = new_fix32 ((int32_t) x);
156 else if (x <= INT64_MAX)
157 (--(st->pos))->fix64 = new_fix64 (x);
163 if (-x >= (uint64_t) INT32_MIN)
164 (--(st->pos))->fix32 = new_fix32 (0 - (int32_t) x);
165 else if (-x >= (uint64_t) INT64_MIN)
166 (--(st->pos))->fix64 = new_fix64 (0 - (int64_t) x);
173 assert (0 && "unimplemented: promote num to float");
177 // stack[0..len]: objs in current list
178 // stack[len]: parent len
180 read_token (const char *p, reader_stack * st)
182 p += count_whitespace (p);
191 // opener: push current framelen; start new frame
192 // store child type and parent framelen in a pseudo-object together
197 type = EVALTYPE_LIST;
200 type = EVALTYPE_FORM;
203 type = EVALTYPE_VECTOR;
206 assert (0 && "martian opener token?");
208 *--(st->pos) = (object)
210 .fix32.type = type,.fix32.rest = 0,.fix32.val = (fix32_val)
224 type = EVALTYPE_LIST;
227 type = EVALTYPE_FORM;
230 assert (0 && "martian list closer token?");
232 // build list from current stack frame
234 pool_copy_array_rev ((pool_object *) st->pos, st->framelen);
235 // pop frame, push new LIST
236 st->pos += st->framelen;
237 assert (st->pos->type == type);
238 st->framelen = st->pos->fix32.val.n + 1;
239 // overwrite the frame marker with the collection it became
240 st->pos->list = new_list (o);
241 st->pos->list.type = type;
247 // build vector from current stack frame
248 heap_ptr h = heap_copy_array_rev (st->pos, st->framelen);
249 // pop frame, push new VECTOR
250 uint32_t len = st->framelen;
251 st->pos += st->framelen;
252 assert (st->pos->type == EVALTYPE_VECTOR);
253 st->framelen = st->pos->fix32.val.n + 1;
254 st->pos->vector = new_vector (h, len);
259 int n = read_num (p, st);
266 (--(st->pos))->atom = oblist_find_or_insert (root, p, n);
271 fprintf (stderr, "read unimplemented for char: '%c'\n", *p);
272 assert (0 && "read unimplemented for char");