/*
-Copyright (C) 2017 Keziah Wesley
+Copyright (C) 2017-2018 Keziah Wesley
You can redistribute and/or modify this file under the terms of the
GNU Affero General Public License as published by the Free Software
#include "read.h"
#include "object.h"
+#include "oblist.h"
#include <assert.h>
#include <stdio.h>
}
*/
+static int
+read_num (const char *p, reader_stack * st)
+{
+ int i = 0;
+ // Use an unsigned intermediate to simplify overflow checks.
+ uint64_t x = 0;
+ // Disallow "number" composed of ancillary number components only.
+ bool gotdigits = false;
+ // Skip for now, later we'll check again to potentially negate.
+ if (p[0] == '-')
+ i++;
+ // TODO: asterisk-deliminated *octal*
+ // TODO: other bases?
+ for (; p[i]; i++)
+ {
+ if (p[i] >= '0' && p[i] <= '9')
+ {
+ if (x * 10 + (p[i] - '0') < x)
+ goto read_float;
+ x = x * 10 + (p[i] - '0');
+ gotdigits = true;
+ continue;
+ }
+
+ // TODO: decimal points, exponent notation
+ // NB. a terminal decimal denotes a FIX
+ // NB. exponent notation doesn't necessarily indicate a float
+
+ // TODO: distinguish 'delimiter' characters that terminate
+ // number from 'identifier' chars that cause parsing to fail
+ // (and potentially be parsed as an atom)
+ break;
+ }
+ if (!gotdigits)
+ return 0;
+ if (p[0] != '-')
+ {
+ if (x <= INT32_MAX)
+ (--(st->pos))->fix32 = new_fix32 ((int32_t) x);
+ else if (x <= INT64_MAX)
+ (--(st->pos))->fix64 = new_fix64 (x);
+ else
+ goto read_float;
+ }
+ else
+ {
+ if (-x >= (uint64_t) INT32_MIN)
+ (--(st->pos))->fix32 = new_fix32 (0 - (int32_t) x);
+ else if (-x >= (uint64_t) INT64_MIN)
+ (--(st->pos))->fix64 = new_fix64 (0 - (int64_t) x);
+ else
+ goto read_float;
+ }
+ st->framelen++;
+ return i;
+read_float:
+ assert (0 && "unimplemented: promote num to float");
+ return i;
+}
+
// stack[0..len]: objs in current list
// stack[len]: parent len
const char *
}
*--(st->pos) = (object)
{
- .fix32.type = type,.fix32.rest = 0,.fix32.val = st->framelen,};
+ .fix32.type = type,.fix32.rest = 0,.fix32.val = (fix32_val)
+ {
+ .n = st->framelen}
+ ,};
st->framelen = 0;
break;
}
// pop frame, push new LIST
st->pos += st->framelen;
assert (st->pos->type == type);
- st->framelen = st->pos->fix32.val + 1;
+ st->framelen = st->pos->fix32.val.n + 1;
// overwrite the frame marker with the collection it became
- st->pos->list = (list_object)
- {
- .type = type,.rest = 0,.head = o};
+ st->pos->list = new_list (o);
+ st->pos->list.type = type;
break;
}
case ']':
uint32_t len = st->framelen;
st->pos += st->framelen;
assert (st->pos->type == EVALTYPE_VECTOR);
- st->framelen = st->pos->fix32.val + 1;
+ st->framelen = st->pos->fix32.val.n + 1;
st->pos->vector = new_vector (h, len);
break;
}
- case '4':
+ default:
{
- p++;
- // push fix obj, extending frame
- (--(st->pos))->fix64 = new_fix64 (4);
- st->framelen++;
- break;
+ int n = read_num (p, st);
+ if (n)
+ return p + n;
+
+ n = count_pname (p);
+ if (n > 0)
+ {
+ (--(st->pos))->atom = oblist_find_or_insert (root, p, n);
+ st->framelen++;
+ return p + n;
+ }
+
+ fprintf (stderr, "read unimplemented for char: '%c'\n", *p);
+ assert (0 && "read unimplemented for char");
}
- default:
- fprintf (stderr, "read unimplemented for char: '%c'\n", *p);
- assert (0 && "read unimplemented for char");
}
return p;
}