aboutsummaryrefslogtreecommitdiffstats
path: root/old/parser.c
diff options
context:
space:
mode:
authorClyne Sullivan <tullivan99@gmail.com>2018-01-29 20:19:22 -0500
committerClyne Sullivan <tullivan99@gmail.com>2018-01-29 20:19:22 -0500
commitb9ceb80c9caa2a4a1659615991e7daa0b1d9fb66 (patch)
treebc0720404a935018c75524555d90a320512398c6 /old/parser.c
parentaccef5f54c0a38b0de3c2dddbaf7b30c6d226541 (diff)
rewrite; a lot better now
Diffstat (limited to 'old/parser.c')
-rw-r--r--old/parser.c225
1 files changed, 225 insertions, 0 deletions
diff --git a/old/parser.c b/old/parser.c
new file mode 100644
index 0000000..5e94e79
--- /dev/null
+++ b/old/parser.c
@@ -0,0 +1,225 @@
+#include <parser.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+static const char *interpreter_operators = "=(";
+
+bool strcmp(const char *a, const char *b)
+{
+ int i = 0;
+ for (; a[i] == b[i] && a[i] != '\0'; i++);
+ return a[i] == b[i];
+}
+
+bool strncmp(const char *a, const char *b, int count)
+{
+ int i = 0;
+ for (; a[i] == b[i] && i < count; i++);
+ return i == count;
+}
+
+uint8_t isalpha(char c)
+{
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
+}
+
+uint8_t isnum(char c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+uint8_t isname(char c)
+{
+ return isalpha(c) || isnum(c);
+}
+
+uint8_t isspace(char c)
+{
+ return (c == ' ' || c == '\t' || c == '\n');
+}
+
+uint8_t isoper(char c)
+{
+ for (uint8_t i = 0; i < sizeof(interpreter_operators); i++) {
+ if (c == interpreter_operators[i])
+ return 1;
+ }
+
+ return 0;
+}
+
+void interpreter_init(interpreter *interp)
+{
+ interp->status = READY;
+ interp->vcount = 0;
+ interp->vars = (variable *)calloc(32, sizeof(variable));
+ interp->names = (char **)calloc(32, sizeof(char *));
+ interp->stack = (stack_t *)calloc(64, sizeof(stack_t));
+}
+
+void interpreter_define_value(interpreter *interp, const char *name, int32_t value)
+{
+ interp->names[interp->vcount] = (char *)name;
+ interp->vars[interp->vcount].nameidx = interp->vcount;
+ interp->vars[interp->vcount].type = VALUE;
+ interp->vars[interp->vcount].value = (uint32_t)value;
+ interp->vcount++;
+}
+
+void interpreter_define_cfunc(interpreter *interp, const char *name, func_t addr)
+{
+ interp->names[interp->vcount] = (char *)name;
+ interp->vars[interp->vcount].nameidx = interp->vcount;
+ interp->vars[interp->vcount].type = CFUNCTION;
+ interp->vars[interp->vcount].value = (uint32_t)addr;
+ interp->vcount++;
+}
+
+int32_t interpreter_get_value(interpreter *interp, const char *name)
+{
+ for (uint16_t i = 0; i < interp->vcount; i++) {
+ if (!strcmp(interp->names[i], name))
+ return (int32_t)interp->vars[i].value;
+ }
+
+ return 0;
+}
+
+/**
+ * doline section
+ */
+
+bool namencmp(const char *name, const char *s)
+{
+ uint16_t i;
+ for (i = 0; name[i] == s[i] && s[i] != '\0'; i++);
+ return (name[i] == '\0' && !isname(s[i]));
+}
+
+uint16_t spacecount(const char *s)
+{
+ uint16_t i;
+ for (i = 0; isspace(s[i]); i++);
+ return i;
+}
+
+char *copystr(const char *s, char end)
+{
+ uint16_t len = 0;
+ while (s[len++] != end);
+ char *buf = (char *)malloc(len);
+ for (uint16_t i = 0; i < len; i++)
+ buf[i] = s[i];
+ return buf;
+}
+
+char *copysubstr(const char *s, int end)
+{
+ char *buf = (char *)malloc(end);
+ for (uint16_t i = 0; i < end; i++)
+ buf[i] = s[i];
+ return buf;
+}
+
+variable *interpreter_getvar(interpreter *interp, const char *line)
+{
+ for (uint16_t i = 0; i < interp->vcount; i++) {
+ if (namencmp(interp->names[i], line))
+ return &interp->vars[i];
+ }
+
+ return 0;
+}
+
+int interpreter_doline(interpreter *interp, const char *line)
+{
+ variable *bits[16];
+ uint16_t offset = 0, boffset = 0;
+
+ // check for var/func set or usage
+ int end;
+getvar:
+ for (end = 0; isname(line[end]); end++);
+ variable *var = interpreter_getvar(interp, line);
+
+ if (var != 0) {
+ bits[boffset++] = var;
+ } else {
+ // defining new variable
+ interpreter_define_value(interp, copysubstr(line, end), 0);
+ goto getvar; // try again
+ }
+
+ // skip whitespace/name
+ offset += end;
+ offset += spacecount(line + offset);
+
+ if (boffset == 0 && line[offset] != '=')
+ return -1; // variable not found
+
+ // find operator
+ if (line[offset] == '\0') {
+ // print value
+ return -99;
+ } else if (line[offset] == '=') {
+ // assignment/expression
+ offset++;
+ offset += spacecount(line + offset);
+ bits[0]->value = (uint32_t)copystr(line + offset, '\0');
+ } else if (line[offset] == '(') {
+ // function call
+ offset++;
+ if (bits[0]->type != FUNCTION && bits[0]->type != CFUNCTION)
+ return -2;
+ offset += spacecount(line + offset);
+
+ // collect arg offsets
+ uint16_t offsets[8];
+ uint8_t ooffset = 0;
+ while (line[offset] != ')' && line[offset] != '\0') {
+ offsets[ooffset] = offset;
+ offset += spacecount(line + offset);
+
+ uint8_t isvn = 1;
+ do {
+ if (line[offset] == ' ' || line[offset] == '\t') {
+ offset += spacecount(line + offset);
+ isvn = 0;
+ }
+
+ if (line[offset] == ',') {
+ offset++;
+ ooffset++;
+ break;
+ } else if (line[offset] == ')') {
+ ooffset++;
+ break;
+ } else if (isvn == 0) {
+ return -3;
+ }
+ } while (++offset);
+ }
+
+ // populate stack
+ for (uint8_t i = 0; i < ooffset; i++) {
+ uint16_t j;
+ for (j = offsets[i]; line[j] != ' ' && line[j] != '\t' &&
+ line[j] != ',' && line[j] != ')'; j++);
+ j -= offsets[i];
+
+ variable *var = interpreter_getvar(interp, line + offsets[i]);
+ if (var != 0)
+ interp->stack[i] = copystr((char *)var->value, '\0');
+ else
+ interp->stack[i] = copysubstr(line + offsets[i], j);
+ }
+
+ ((func_t)bits[0]->value)(interp->stack);
+ } else {
+ return -2; // invalid operation
+ }
+
+ return 0;
+}
+