diff options
Diffstat (limited to 'parser.c')
-rw-r--r-- | parser.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/parser.c b/parser.c new file mode 100644 index 0000000..9bbc50b --- /dev/null +++ b/parser.c @@ -0,0 +1,116 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <ctype.h> +#include "stack.h" +#include "parser.h" +#include "eval.h" + +static unsigned int jumpdist; + +static char *readexpr(char *expr){ + char *out = malloc(strlen(expr+1)); + char *c = expr; + stack *s = push(NULL, *c); + int i; + + for (i = 0; s->len != 0; i++){ + out[i] = *c; + c++; + if (*c == '(') s = push(s, '('); + else if (*c == ')' && peek(s) == '(') pop(s); + } + cleanstack(s); + + out[i] = ')'; + out[i+1] = 0; + out = realloc(out, strlen(out)); + jumpdist = i+1; + return out; +} + +static char *readval(char *expr){ + char *out = strdup(expr); + char *gap = strchr(out, ' '); + if (gap == NULL) gap = strchr(out, ')'); + jumpdist = (gap - out)+1; + *gap = 0; + out = realloc(out, strlen(out)); + return out; +} + +static luckyval *readargs(char *expr){ + luckyval *head = malloc(sizeof(luckyval)); + + if (*expr != ')' && expr[0] != 0){ + if (expr[0] == '(' ){ // nested function + char *subexpr = readexpr(expr); + expr += jumpdist + 1; + head->tree = parse(subexpr); + head->type = LUCKYTREE; + free(subexpr); + } + else if (strchr(expr, '.') != NULL){ // float + char *val = readval(expr); + expr += jumpdist; + head->f = atof(val); + head->type = LUCKYFLOAT; + free(val); + } + else if (isdigit(expr[0])){ // int + char *val = readval(expr); + expr += jumpdist; + head->i = atoi(val); + head->type = LUCKYINT; + free(val); + } + else { // var name + char *val = readval(expr); + expr += jumpdist; + head->var = strdup(val); + head->type = LUCKYVAR; + } + } else return NULL; + + head->nextelement = readargs(expr); + return head; +} + +luckytree *parse(char *expr){ + char *c = expr; + stack *s = push(NULL, *c); + while (*c != 0){ + c++; + if (*c == '(') s = push(s, '('); + else if (*c == ')' && peek(s) == '(') pop(s); + } + if (s->len != 0){ + printf("%s\n", expr); + for (int i = 0; i < (c - expr) - 1; i++) printf(" "); + printf("^\n"); + printf("bracket mismatch!\n"); + exit(1); + } + cleanstack(s); + + luckytree *tree = malloc(sizeof(luckytree)); + + int funcnamelen; + if (strchr(expr+1, ' ') == NULL) + funcnamelen = (strchr(expr+1, ')') - expr) - 1; + else + funcnamelen = (strchr(expr+1, ' ') - expr) - 1; + + tree->function = malloc(funcnamelen + 1); + + memcpy(tree->function, expr + 1, funcnamelen); + tree->function[funcnamelen] = 0; + + expr += funcnamelen + 2; + + tree->arguments = readargs(expr); + + return tree; +} + |