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/>.
29 // Return the number of whitespace characters at the beginning of the input.
31 count_whitespace (const char *p)
51 // Return the number of characters at the beginning of the input
52 // constituting a valid PNAME.
53 // If the input ends with '\', it is incomplete, and -1 is returned.
55 count_pname (const char *p)
57 // rule (1): valid FLOAT / FIX isn't a PNAME.
58 // Caller must try to read as number first!
60 // rule (2): dot can't be first
64 // rule (3): "if you can't type it interactively, it's only valid non-interactively"
65 // (not currently enforced; just don't give your atoms names like ^L)
71 // separators end the PNAME
72 // rule (4): whitespace
73 // rule (5): special characters
97 // escape: next char becomes normal
110 static uint32_t obj_get_fix32(const object *o) {
111 assert(o->type == EVALTYPE_FIX32);
117 read_num (const char *p, reader_stack *st)
120 // Use an unsigned intermediate to simplify overflow checks.
122 // Disallow "number" composed of ancillary number components only.
123 bool gotdigits = false;
124 // Skip for now, later we'll check again to potentially negate.
127 // TODO: asterisk-deliminated *octal*
128 // TODO: other bases?
131 if (p[i] >= '0' && p[i] <= '9')
133 if (x * 10 + (p[i] - '0') < x)
135 x = x * 10 + (p[i] - '0');
140 // TODO: decimal points, exponent notation
141 // NB. a terminal decimal denotes a FIX
142 // NB. exponent notation doesn't necessarily indicate a float
144 // TODO: distinguish 'delimiter' characters that terminate
145 // number from 'identifier' chars that cause parsing to fail
146 // (and potentially be parsed as an atom)
154 (--(st->pos))->fix32 = new_fix32 ((int32_t)x);
155 else if (x <= INT64_MAX)
156 (--(st->pos))->fix64 = new_fix64 (x);
162 if (-x >= (uint64_t)INT32_MIN)
163 (--(st->pos))->fix32 = new_fix32 (0 - (int32_t)x);
164 else if (-x >= (uint64_t)INT64_MIN)
165 (--(st->pos))->fix64 = new_fix64 (0 - (int64_t)x);
172 assert(0 && "unimplemented: promote num to float");
176 // stack[0..len]: objs in current list
177 // stack[len]: parent len
179 read_token (const char *p, reader_stack *st)
181 p += count_whitespace (p);
190 // opener: push current framelen; start new frame
191 // store child type and parent framelen in a pseudo-object together
196 type = EVALTYPE_LIST;
199 type = EVALTYPE_FORM;
202 type = EVALTYPE_VECTOR;
205 assert (0 && "martian opener token?");
207 *--(st->pos) = (object)
209 .fix32.type = type,.fix32.rest = 0,.fix32.val = st->framelen,};
220 type = EVALTYPE_LIST;
223 type = EVALTYPE_FORM;
226 assert (0 && "martian list closer token?");
228 // build list from current stack frame
230 pool_copy_array_rev ((pool_object *) st->pos, st->framelen);
231 // pop frame, push new LIST
232 st->pos += st->framelen;
233 assert (st->pos->type == type);
234 st->framelen = st->pos->fix32.val + 1;
235 // overwrite the frame marker with the collection it became
236 st->pos->list = (list_object)
238 .type = type,.rest = 0,.head = o};
244 // build vector from current stack frame
245 heap_ptr h = heap_copy_array_rev (st->pos, st->framelen);
246 // pop frame, push new VECTOR
247 uint32_t len = st->framelen;
248 st->pos += st->framelen;
249 assert (st->pos->type == EVALTYPE_VECTOR);
250 st->framelen = st->pos->fix32.val + 1;
251 st->pos->vector = new_vector (h, len);
256 int n = read_num (p, st);
260 // TODO: try read pname
262 fprintf (stderr, "read unimplemented for char: '%c'\n", *p);
263 assert (0 && "read unimplemented for char");