diff options
author | Clyne Sullivan <tullivan99@gmail.com> | 2018-03-29 13:36:29 -0400 |
---|---|---|
committer | Clyne Sullivan <tullivan99@gmail.com> | 2018-03-29 13:36:29 -0400 |
commit | 3b33fa0aeb5262335cd708b167caad8f41b8a5dd (patch) | |
tree | cb34ba93ecca6f3bbc936acdf92e6d347219a9cc /parser.c | |
parent | 7faeef296d8b0041ae340c3febf7eb0a78e60b0f (diff) |
documentation, error fixes, organization
Diffstat (limited to 'parser.c')
-rw-r--r-- | parser.c | 275 |
1 files changed, 83 insertions, 192 deletions
@@ -22,67 +22,26 @@ #include "builtins.h" #include "ops.h" +#include "string.h" +#include "variable.h" #include <ctype.h> #include <stdlib.h> #include <stdio.h> -#include <string.h> + +/** + * Limitations for an instance. TODO make dynamic (no limits). + */ #define MAX_VARS 256 #define MAX_STACK 64 #define MAX_LINES 1000 -int bracket_open(instance *it) -{ - it->indent++; - if (it->sindent & SKIP) { - ipush(it, SKIP_SIG); - ipush(it, 0); - } - return 0; -} -int bracket_close(instance *it) -{ - it->indent--; - if (it->indent < (it->sindent & ~(SKIP))) - it->sindent = 0; - bn_end(it); - return 0; -} -static variable bopen = { - 0, CFUNC, 0, {.p = (uint32_t)bracket_open} -}; -static variable bclose = { - 0, CFUNC, 0, {.p = (uint32_t)bracket_close} -}; - -char *strnclone(const char *s, size_t c) -{ - char *b = strncpy((char *)malloc(c + 1), s, c); - b[c] = '\0'; - return b; -} -char *strclone(const char *s) -{ - return strnclone(s, strlen(s)); -} -char *fixstring(const char *s) -{ - char *n = malloc(strlen(s) + 1 - 2); - int j = 0; - for (int i = 1; s[i] != '\"'; i++, j++) { - if (s[i] == '\\') { - if (s[i + 1] == 'n') - n[j] = '\n'; - i++; - } else { - n[j] = s[i]; - } - } - n[j] = '\0'; - return n; -} - +/** + * Attempts to free memory used by a variable, if the variable is temporary. + * Nothing is done if the variable can't be free'd. + * @param v the variable to free + */ void itryfree(variable *v) { if (v == 0 || v->tmp == 0) @@ -92,6 +51,10 @@ void itryfree(variable *v) free(v); } +// +// instance construction/deconstruction +// + instance *inewinstance(void) { instance *it = (instance *)malloc(sizeof(instance)); @@ -109,26 +72,10 @@ instance *inewinstance(void) return it; } -void idelline(variable **ops) -{ - for (int j = 0; j < 32; j++) { - variable *v = ops[j]; - if (v != 0) { - if (((uint32_t)v & OP_MAGIC) == OP_MAGIC) - continue; - - if (v->type == FUNC || v->type == CFUNC) - j++; // argcount - - if (v->tmp == 1) - itryfree(v); - } - } -} - +void idelline(variable **ops); void idelinstance(instance *it) { - for (uint32_t i = 0; i < MAX_LINES; i++) {// TODO free vars! + for (uint32_t i = 0; i < MAX_LINES; i++) { if (it->lines[i] == 0) continue; @@ -147,6 +94,27 @@ void idelinstance(instance *it) free(it); } +void idelline(variable **ops) +{ + for (int j = 0; j < 32; j++) { + variable *v = ops[j]; + if (v != 0) { + if (((uint32_t)v & OP_MAGIC) == OP_MAGIC) + continue; + + if (v->type == FUNC || v->type == CFUNC) + j++; // argcount + + if (v->tmp == 1) + itryfree(v); + } + } +} + +// +// stack operations +// + void ipush(instance *it, uint32_t v) { it->stack[it->stidx++] = v; @@ -167,7 +135,27 @@ variable *igetarg(instance *it, uint32_t n) return (variable *)it->stack[it->stidx - n - 1]; } -variable *igetvar(instance *it, const char *name); +// +// variable creation +// + +variable *igetvar(instance *it, const char *name) +{ + if (isalpha(name[0])) { + for (uint32_t i = 0; i < MAX_VARS; i++) { + if (it->names[i] == 0) { + it->names[i] = strclone(name); + // default to 0 float + return make_varf(&it->vars[i], 0.0f); + } else if (!strcmp(name, it->names[i])) { + return &it->vars[i]; + } + } + } + + return igetop(name, 0); +} + void inew_cfunc(instance *it, const char *name, func_t func) { variable *v = igetvar(it, name); @@ -189,100 +177,6 @@ void inew_string(instance *it, const char *name, const char *s) v->value.p = (uint32_t)strclone(s); } -variable *varclone(variable *n) -{ - variable *v = (variable *)malloc(sizeof(variable)); - v->tmp = 1; - v->type = n->type; - if (n->type == STRING) - v->value.p = (uint32_t)strclone((char *)n->value.p); - else - v->value.p = n->value.p; - return v; -} - -variable *make_varf(variable *v, float f) -{ - if (v == 0) { - v = (variable *)malloc(sizeof(variable)); - v->tmp = 1; - } - v->type = NUMBER; - v->value.f = f; - return v; -} - -variable *make_vars(variable *v, const char *s) -{ - if (v == 0) { - v = (variable *)malloc(sizeof(variable)); - v->tmp = 1; - } - v->type = STRING; - v->value.p = (uint32_t)strclone(s); - return v; -} - -variable *make_num(const char *text) -{ - int decimal = -1; - char valid = 0; - - int i = 0; - if (text[0] == '-') - i++; - do { - if (text[i] == '.') { - if (decimal >= 0) { - valid = 0; - break; - } - decimal = i; - } else if (isdigit(text[i])) { - valid |= 1; - } else { - break; - } - } while (text[++i] != '\0'); - - if (valid == 0) - return 0; - - char *buf = (char *)malloc(i + 1); - strncpy(buf, text, i); - buf[i] = '\0'; - - variable *v = make_varf(0, strtof(buf, 0)); - free(buf); - return v; -} - -variable *igetop(const char *name) -{ - for (uint32_t i = 0; i < OPS_COUNT; i++) { - if (opnames[i] != 0 && !strcmp(name, opnames[i])) { - return &opvars[i]; - } - } - return 0; -} -variable *igetvar(instance *it, const char *name) -{ - if (isalpha(name[0])) { - for (uint32_t i = 0; i < MAX_VARS; i++) { - if (it->names[i] == 0) { - it->names[i] = strclone(name); - // default to 0 float - return make_varf(&it->vars[i], 0.0f); - } else if (!strcmp(name, it->names[i])) { - return &it->vars[i]; - } - } - } - - return igetop(name); -} - int idoline(instance *it, const char *s) { variable **ops = iparse(it, s); @@ -296,6 +190,8 @@ loop: // itryfree(it->ret); //it->ret = 0; + // clone the 'ops' array carefully, as isolve() frees/deletes used + // variables as it goes copy = (variable **)malloc(32 * sizeof(variable *)); for (int i = 0; i < 32; i++) { variable *v = it->lines[it->lnidx][i]; @@ -318,9 +214,11 @@ loop: } } it->ret = isolve(it, copy, 0); + if (it->ret == 0) { idelline(copy); } else { + // move result global variable "ANS" variable *ret = igetvar(it, "ANS"); ret->type = it->ret->type; ret->value.p = it->ret->value.p; @@ -437,7 +335,7 @@ variable *isolve_(instance *it, variable **ops, uint32_t count) return 0; uint32_t bidx = i + 1; while (ops[bidx] == 0 && ++bidx < count); - if (bidx == count) + if (bidx >= count) return 0; if (!(it->sindent & SKIP)) { @@ -474,13 +372,18 @@ variable **iparse(instance *it, const char *s) int32_t boffset = 1; size_t offset = 0; + // advance to first character + // and insure there's runnable script on the line while (isblank(s[offset])) offset++; if (s[offset] == '#' || s[offset] == '\0' || s[offset] == '\n') goto fail; + // iterate through script to assemble line of 'ops' + // that isolve() can run through ops = (variable **)calloc(32, sizeof(variable *)); while (s[offset] != '\0' && s[offset] != '\n') { + // variable or function if (isalpha(s[offset])) { size_t end = offset + 1; while (isalnum(s[end])) @@ -565,44 +468,32 @@ variable **iparse(instance *it, const char *s) ops[parenidx] = (variable *)(OP_MAGIC | count); offset = i; } else if (!isblank(s[offset])) { - size_t end = offset + 1; - while (!isblank(s[end]) && !isalnum(s[end]) && s[end] != '\0') - end++; - char *word = strnclone(s + offset, end - offset); - - // bracket? - if (!strcmp(word, "{") || !strcmp(word, "}")) { + if (s[offset] == '{' || s[offset] == '}') { for (int32_t i = ooffset - 1; i >= boffset - 1; i--) ops[i + 2] = ops[i]; - if (word[0] == '{') + if (s[offset] == '{') ops[boffset - 1] = &bopen; else ops[boffset - 1] = &bclose; ops[boffset] = (variable *)1; // arg count + 1 boffset += 2; ooffset += 2; + offset++; } else { - variable *v = igetop(word); - if (v == 0) { - free(word); + int len = 0; + variable *v = igetop(s + offset, &len); + if (v == 0) goto fail; - } else { - if (ooffset == 0) { - variable *a; - if (it->ret != 0) - a = it->ret; - else - a = make_varf(0, 0.0f); - ops[ooffset++] = a; - } else if (ops[ooffset - 1]->type == OPERATOR) { - free(word); - goto fail; - } - } + if (ooffset == 0) { + variable *a = (it->ret != 0) ? + a = it->ret : make_varf(0, 0.0f); + ops[ooffset++] = a; + } /*else if (ops[ooffset - 1]->type == OPERATOR) { + goto fail; + }*/ ops[ooffset++] = v; + offset += len; } - free(word); - offset = end; } else { offset++; } |