aboutsummaryrefslogtreecommitdiffstats
path: root/src/parser.c
diff options
context:
space:
mode:
authorClyne Sullivan <tullivan99@gmail.com>2018-02-12 11:23:59 -0500
committerClyne Sullivan <tullivan99@gmail.com>2018-02-12 11:23:59 -0500
commit100cb2f84ac5c44a904f7d7145cdc2ce1dcf59ba (patch)
tree73079f311b8ff81069bfd615eed0b55c52a5e4b6 /src/parser.c
parent025ed8530ce92d4a2282af8bba1b9e3e93afbb99 (diff)
libinterp, actually works
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c716
1 files changed, 0 insertions, 716 deletions
diff --git a/src/parser.c b/src/parser.c
deleted file mode 100644
index df2dc21..0000000
--- a/src/parser.c
+++ /dev/null
@@ -1,716 +0,0 @@
-#include <parser.h>
-
-#include <heap.h>
-
-#include <ctype.h>
-#include <string.h>
-
-extern int atoi(char *);
-float strtof(char *s, char **e)
-{ (void)s; (void)e; return 0;}
-#include <stdarg.h>
-extern int ksnprintf(char *, int, const char *, ...);
-
-#define MAX_VARS 32
-#define MAX_STACK 32
-
-#define INT(v) (*((int32_t *)&v->value))
-#define FLOAT(v) (*((float *)&v->value))
-
-static char *str_func = "(func)";
-static char *str_undef = "(undefined)";
-
-char *strclone(const char *s)
-{
- char *clone = (char *)malloc(strlen(s));
- strcpy(clone, s);
- return clone;
-}
-
-char *strnclone(const char *s, uint32_t n)
-{
- char *clone = (char *)malloc(n);
- strncpy(clone, s, n);
- return clone;
-}
-
-void fsetstr(variable *f)
-{
- if (f->svalue == 0)
- f->svalue = (char *)malloc(16);
- ksnprintf(f->svalue, 16, "%f", FLOAT(f));
-}
-
-void isetstr(variable *i)
-{
- if (i->svalue == 0)
- i->svalue = (char *)malloc(12);
- ksnprintf(i->svalue, 12, "%ld", INT(i));
-}
-
-uint8_t eol(int c)
-{
- return c == '\n' || c == '\0';
-}
-
-uint8_t eot(int c)
-{
- return eol(c) || c == ' ';
-}
-
-uint8_t eoe(int c)
-{
- return eol(c) || c == ')';
-}
-
-uint32_t findend(const char *s, char o, char c)
-{
- uint8_t indent = 0;
- uint32_t i;
- for (i = 1; !eol(s[i]); i++) {
- if (s[i] == o) {
- indent++;
- } else if (s[i] == c) {
- if (indent == 0)
- break;
- else
- indent--;
- }
- }
-
- return i;
-}
-
-int ifunc_set(interpreter *it);
-int ifunc_jmp(interpreter *it);
-int ifunc_label(interpreter *it);
-int ifunc_end(interpreter *it);
-
-variable *idoexpr(interpreter *interp, const char *line);
-
-variable *itostring(variable *v);
-variable *itoint(variable *v);
-variable *itofloat(variable *v);
-
-void iinit(interpreter *interp)
-{
- interp->vars = (variable *)calloc(MAX_VARS, sizeof(variable));
- interp->vnames = (char **)calloc(MAX_VARS, sizeof(char *));
- interp->stack = (stack_t *)calloc(MAX_STACK, sizeof(stack_t));
- interp->stidx = 0;
- interp->lines = (char **)calloc(20, sizeof(char *));
- interp->lnidx = 0;
- interp->indent = 0;
-
- inew_cfunc(interp, "set", ifunc_set);
- inew_cfunc(interp, "jmp", ifunc_jmp);
- inew_cfunc(interp, "func", ifunc_label);
- inew_cfunc(interp, "end", ifunc_end);
-}
-
-void ipush(interpreter *it, void *v)
-{
- it->stack[it->stidx++] = v;
-}
-
-void *ipop(interpreter *it)
-{
- return it->stack[--it->stidx];
-}
-
-variable *interpreter_get_variable(interpreter *interp, const char *name)
-{
- for (uint32_t i = 0; i < MAX_VARS; i++) {
- if (!interp->vars[i].used) {
- variable *v = &interp->vars[i];
- v->used = 1;
- v->fromc = 0;
- v->valtype = STRING;
- v->value = 0;
- v->svalue = str_undef;
- interp->vnames[i] = strclone(name);
- return v;
- } else if (interp->vnames[i] != 0 && !strcmp(interp->vnames[i], name)) {
- return &interp->vars[i];
- }
- }
- return 0;
-}
-
-char *interpreter_get_name(interpreter *interp, variable *v)
-{
- for (uint32_t i = 0; i < MAX_VARS; i++) {
- if (v == &interp->vars[i])
- return interp->vnames[i];
- }
- return str_undef;
-}
-
-void inew_string(interpreter *interp, const char *name, char *value)
-{
- variable *v = interpreter_get_variable(interp, name);
- if (v != 0) {
- v->valtype = STRING;
- INT(v) = 0;
- v->svalue = strclone(value);
- }
-}
-
-void inew_integer(interpreter *interp, const char *name, int32_t value)
-{
- variable *v = interpreter_get_variable(interp, name);
- if (v != 0) {
- v->valtype = INTEGER;
- INT(v) = value;
- isetstr(v);
- }
-}
-
-void inew_float(interpreter *interp, const char *name, float value)
-{
- variable *v = interpreter_get_variable(interp, name);
- if (v != 0) {
- v->valtype = FLOAT;
- FLOAT(v) = value;
- fsetstr(v);
- }
-}
-
-void inew_cfunc(interpreter *interp, const char *name, func_t func)
-{
- variable *v = interpreter_get_variable(interp, name);
- if (v != 0) {
- v->fromc = 1;
- v->valtype = FUNC;
- v->value = (uint32_t)func;
- v->svalue = str_func;
- }
-}
-
-variable *make_var(interpreter *interp, const char *line, uint32_t *next)
-{
- if (line[0] == '\"') { // string literal
- uint32_t end = 1;
- while (!eol(line[end])) {
- if (line[end] == '\"'/* && line[end - 1] != '\\'*/) {
- if (!eot(line[end + 1]))
- return 0;
- // TODO string breakdown
- variable *v = (variable *)malloc(sizeof(variable));
- v->used = 0;
- v->valtype = STRING;
- v->svalue = strnclone(line + 1, end - 1);
- *next = end + 1;
- return v;
- }
- end++;
- }
- return 0;
- } else if (line[0] == '(') { // equation literal
- uint32_t end = findend(line, '(', ')');
- if (eot(line[end]))
- return 0;
- *next = end + 1;
- return idoexpr(interp, line + 1);
- } else if (isalpha(line[0])) { // variable/func
- uint32_t end = 1;
- for (; isalnum(line[end]); end++);
- if (!eot(line[end]))
- return 0;
- char *name = (char *)malloc(end + 1);
- strncpy(name, line, end);
- name[end] = '\0';
- *next = end;
- return interpreter_get_variable(interp, name);
- } else if (isdigit(line[0])) { // number
- uint32_t end = 1;
- uint8_t dec = 0;
- for (; !eot(line[end]); end++) {
- if (!isdigit(line[end])) {
- if (line[end] == '.') {
- if (!dec)
- dec = 1;
- else
- return 0;
- } else {
- return 0;
- }
- }
- }
- variable *v = (variable *)malloc(sizeof(variable));
- v->used = 0;
- if (dec) {
- v->valtype = FLOAT;
- FLOAT(v) = strtof(line, 0);
- fsetstr(v);
- } else {
- v->valtype = INTEGER;
- INT(v) = atoi(line);
- isetstr(v);
- }
- *next = end;
- return v;
- }
- return 0;
-}
-
-int idoline(interpreter *interp, const char *line)
-{
- variable *ops[8];
- uint32_t ooffset, offset, next;
-
- interp->lines[interp->lnidx] = strclone(line);
-loop:
- if (line[0] == '#') {
- goto norun;
- } else if (interp->indent > 0) {
- if (!strcmp(line, "end"))
- interp->indent--;
- goto norun;
- }
-
- ooffset = 0;
- offset = 0;
-
- // step 1 - convert to tokens
- while (!eol(line[offset])) {
- ops[ooffset] = make_var(interp, line + offset, &next);
- if (ops[ooffset] == 0) {
- return -4;
- } else {
- ooffset++;
- offset += next;
- }
-
- // skip whitespace
- for (; line[offset] == ' ' && !eol(line[offset]); offset++);
- }
-
- // step 2 - execute
- if (ooffset == 0)
- return -1;
-
- if (ops[0]->valtype != FUNC)
- return -2;
-
- if (ops[0]->value == 0)
- return -3;
-
- for (uint32_t i = ooffset; --i > 0;)
- ipush(interp, ops[i]);
-
- if (ops[0]->fromc) {
- int ret = ((func_t)ops[0]->value)(interp);
- if (ret != 0)
- return ret;
- } else {
- ipush(interp, (void *)(interp->lnidx + 1));
- interp->lnidx = ops[0]->value;
- }
-
- interp->stidx -= ooffset - 1;
-
- if ((int32_t)interp->stidx < 0) {
- interp->stidx = 0;
- return -5;
- }
-
- for (uint32_t i = 0; i < ooffset; i++) {
- if (!ops[i]->used)
- free(ops[i]);
- }
-
-norun:
- interp->lnidx++;
- if (interp->lines[interp->lnidx] != 0) {
- line = interp->lines[interp->lnidx];
- goto loop;
- }
-
- return 0;
-}
-
-typedef void (*operation_t)(variable *, variable *, variable *);
-
-#define IOPS_COUNT 15
-static char *iops[IOPS_COUNT] = {
- "+", "-", "*", "/", "&", "|", "^", ">>", "<<",
- "==", "<", ">", "<=", ">=", "!="
-};
-
-void iop_add(variable *, variable *, variable *);
-void iop_sub(variable *, variable *, variable *);
-void iop_mult(variable *, variable *, variable *);
-void iop_div(variable *, variable *, variable *);
-void iop_and(variable *, variable *, variable *);
-void iop_or(variable *, variable *, variable *);
-void iop_xor(variable *, variable *, variable *);
-void iop_shr(variable *, variable *, variable *);
-void iop_shl(variable *, variable *, variable *);
-void iop_eq(variable *, variable *, variable *);
-void iop_lt(variable *, variable *, variable *);
-void iop_gt(variable *, variable *, variable *);
-void iop_lte(variable *, variable *, variable *);
-void iop_gte(variable *, variable *, variable *);
-void iop_ne(variable *, variable *, variable *);
-
-static operation_t iopfuncs[IOPS_COUNT] = {
- iop_add, iop_sub, iop_mult, iop_div, iop_and,
- iop_or, iop_xor, iop_shr, iop_shl,
- iop_eq, iop_lt, iop_gt, iop_lte, iop_gte, iop_ne
-};
-
-variable *idoexpr(interpreter *interp, const char *line)
-{
- variable *result = (variable *)malloc(sizeof(variable));
- char *mline = line;
- void *ops[16];
- uint32_t ooffset = 0;
- uint32_t offset = 0;
- uint32_t next;
-
- // step 1 - break apart line
-
- // skip whitespace
- for (; line[offset] == ' ' && !eol(line[offset]); offset++);
- while (!eoe(line[offset])) {
- if (line[offset] == '(') {
- uint8_t indent = 0;
- uint32_t i;
- for (i = offset + 1; !eol(line[i]); i++) {
- if (line[i] == '(') {
- indent++;
- } else if (line[i] == ')') {
- if (indent == 0) {
- break;
- } else {
- indent--;
- }
- }
- }
- if (eol(line[i]))
- return 0;
- ops[ooffset] = idoexpr(interp, line + offset + 1);
- offset = i + 1;
- } else {
- uint32_t end = offset;
- char cend = 0;
- if (line[offset] != '\"') {
- for (; isalnum(line[end]) || line[end] == '.'; end++);
- cend = line[end];
- mline[end] = ' ';
- }
- ops[ooffset] = make_var(interp, line + offset, &next);
- if (end != 0)
- mline[end] = cend;
- }
- if (ops[ooffset] == 0)
- return 0;
-
- ooffset++;
- offset += next;
-
- // skip whitespace
- for (; line[offset] == ' ' && !eoe(line[offset]); offset++);
- if (eoe(line[offset]))
- break;
-
- for (uint32_t i = 0; i < IOPS_COUNT; i++) {
- int len = strlen(iops[i]);
- if (!strncmp(iops[i], line + offset, len)) {
- ops[ooffset] = (void *)(i + 1);
- offset += len;
- break;
- }
- }
- if (ops[ooffset] == 0)
- return 0;
- ooffset++;
-
- // skip whitespace
- for (; line[offset] == ' ' && !eol(line[offset]); offset++);
- }
-
- if (ooffset % 2 == 0)
- return 0;
-
- // step 2 - do operations
- result->valtype = ((variable *)ops[0])->valtype;
- result->value = ((variable *)ops[0])->value;
- for (uint32_t i = 1; i < ooffset; i += 2) {
- iopfuncs[(uint32_t)ops[i] - 1](result, result, ops[i + 1]);
- }
-
- for (uint32_t i = 0; i < ooffset; i += 2) {
- if (!((variable *)ops[i])->used)
- free(ops[i]);
- }
-
- if (result->valtype == INTEGER)
- isetstr(result);
- else
- fsetstr(result);
-
- return result;
-}
-
-variable *igetarg(interpreter *interp, uint32_t index)
-{
- return interp->stack[interp->stidx - index - 1];
-}
-
-char *igetarg_string(interpreter *interp, uint32_t index)
-{
- if (index >= interp->stidx)
- return 0;
- variable *v = igetarg(interp, index);
- return v->svalue;
-}
-
-int igetarg_integer(interpreter *interp, uint32_t index)
-{
- if (index >= interp->stidx)
- return 0;
- variable *v = igetarg(interp, index);
- return INT(itoint(v));
-}
-
-float igetarg_float(interpreter *interp, uint32_t index)
-{
- if (index >= interp->stidx)
- return 0;
- variable *v = igetarg(interp, index);
- return FLOAT(itofloat(v));
-}
-
-variable *itostring(variable *v)
-{
- switch (v->valtype) {
- case INTEGER:
- v->valtype = STRING;
- isetstr(v);
- break;
- case FLOAT:
- v->valtype = STRING;
- fsetstr(v);
- break;
- }
- return v;
-}
-
-variable *itoint(variable *v)
-{
- switch (v->valtype) {
- case STRING:
- v->valtype = INTEGER;
- INT(v) = atoi(v->svalue);
- isetstr(v);
- break;
- case FLOAT:
- v->valtype = INTEGER;
- INT(v) = (int32_t)FLOAT(v);
- isetstr(v);
- break;
- }
- return v;
-}
-
-variable *itofloat(variable *v)
-{
- switch (v->valtype) {
- case STRING:
- v->valtype = FLOAT;
- FLOAT(v) = strtof(v->svalue, 0);
- fsetstr(v);
- break;
- case INTEGER:
- v->valtype = FLOAT;
- FLOAT(v) = (float)INT(v);
- fsetstr(v);
- break;
- }
- return v;
-}
-
-/**
- * Builtin functions
- */
-
-int ifunc_set(interpreter *it)
-{
- variable *n = igetarg(it, 0);
- variable *v = igetarg(it, 1);
-
- if (n == 0)
- return -1;
-
- n->valtype = v->valtype;
- n->value = v->value;
- n->svalue = v->svalue;
- return 0;
-}
-
-int ifunc_label(interpreter *it)
-{
- variable *n = igetarg(it, 0);
-
- if (n == 0)
- return -1;
-
- n->valtype = FUNC;
- n->value = it->lnidx;
- n->svalue = str_func;
- it->indent++;
- return 0;
-}
-
-int ifunc_end(interpreter *it)
-{
- if (it->stidx > 0) {
- uint32_t line = (uint32_t)ipop(it);
- it->lnidx = line - 1;
- }
- return 0;
-}
-
-int ifunc_jmp(interpreter *it)
-{
- int newidx = igetarg_integer(it, 0);
- ipop(it);
- ipush(it, (void *)(it->lnidx + 1));
- ipush(it, 0);
- it->lnidx = newidx - 1;
- return 0;
-}
-
-/**
- * Builtin operations
- */
-
-void iop_add(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER) {
- INT(r) = INT(a) + INT(b);
- } else {
- itofloat(a);
- itofloat(b);
- FLOAT(r) = FLOAT(a) + FLOAT(b);
- }
-}
-
-void iop_sub(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER) {
- INT(r) = INT(a) - INT(b);
- } else {
- itofloat(a);
- itofloat(b);
- FLOAT(r) = FLOAT(a) - FLOAT(b);
- }
-}
-
-void iop_mult(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER) {
- INT(r) = INT(a) * INT(b);
- } else {
- itofloat(a);
- itofloat(b);
- FLOAT(r) = FLOAT(a) * FLOAT(b);
- }
-}
-
-void iop_div(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER) {
- INT(r) = INT(a) / INT(b);
- } else {
- itofloat(a);
- itofloat(b);
- FLOAT(r) = FLOAT(a) / FLOAT(b);
- }
-}
-
-void iop_and(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER) {
- INT(r) = INT(a) & INT(b);
- }
-}
-
-void iop_or(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER) {
- INT(r) = INT(a) | INT(b);
- }
-}
-
-void iop_xor(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER) {
- INT(r) = INT(a) ^ INT(b);
- }
-}
-
-void iop_shr(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER) {
- INT(r) = INT(a) >> INT(b);
- }
-}
-
-void iop_shl(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER) {
- INT(r) = INT(a) << INT(b);
- }
-}
-
-void iop_eq(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER)
- INT(r) = INT(a) == INT(b);
- else
- INT(r) = FLOAT(a) == FLOAT(b);
-}
-
-void iop_lt(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER)
- INT(r) = INT(a) < INT(b);
- else
- INT(r) = FLOAT(a) < FLOAT(b);
-}
-
-void iop_gt(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER)
- INT(r) = INT(a) > INT(b);
- else
- INT(r) = FLOAT(a) > FLOAT(b);
-}
-
-void iop_lte(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER)
- INT(r) = INT(a) <= INT(b);
- else
- INT(r) = FLOAT(a) <= FLOAT(b);
-}
-
-void iop_gte(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER)
- INT(r) = INT(a) >= INT(b);
- else
- INT(r) = FLOAT(a) >= FLOAT(b);
-}
-
-void iop_ne(variable *r, variable *a, variable *b)
-{
- if (a->valtype == INTEGER && b->valtype == INTEGER)
- INT(r) = INT(a) != INT(b);
- else
- INT(r) = FLOAT(a) != FLOAT(b);
-}
-