]> code.bitgloo.com Git - clyne/interpreter.git/commitdiff
implicit multiply, negatives, solve
authorClyne Sullivan <tullivan99@gmail.com>
Thu, 8 Mar 2018 17:17:12 +0000 (12:17 -0500)
committerClyne Sullivan <tullivan99@gmail.com>
Thu, 8 Mar 2018 17:17:12 +0000 (12:17 -0500)
builtins.c
parser.c
parser.h
script
shell.c [new file with mode: 0644]
variable.c
variable.h

index 5186e8b962d9cfc3cfdd5afd480dedba047e0952..0ab6f3b993d3e6ea657fe7607a98e1fb09a3f843 100644 (file)
@@ -13,6 +13,7 @@ int ifunc_do(interpreter *it);
 int ifunc_while(interpreter *it);
 int ifunc_ret(interpreter *it);
 int ifunc_else(interpreter *it);
+int ifunc_solve(interpreter *it);
 
 const func_t indent_up[IUP_COUNT] = {
        ifunc_if, ifunc_do, ifunc_label
@@ -32,6 +33,24 @@ void iload_core(interpreter *interp)
        inew_cfunc(interp, "while", ifunc_while);
        inew_cfunc(interp, "ret", ifunc_ret);
        inew_cfunc(interp, "else", ifunc_else);
+       inew_cfunc(interp, "solve", ifunc_solve);
+}
+
+int ifunc_solve(interpreter *it)
+{
+       const char *expr = igetarg_string(it, 0);
+       int len = strlen(expr);
+       char *buf = (char *)malloc(len + 2);
+       strcpy(buf, expr);
+       buf[len] = ')';
+       buf[len + 1] = '\0';
+       variable *r = idoexpr(it, buf);
+       free(buf);
+       if (r == 0)
+               r = make_varn(0, 0.0f);
+       iret(it, r);
+       free(r);
+       return 0;
 }
 
 int ifunc_set(interpreter *it)
index d7ba5acaeec6b5cf52598ff3533fbef99f04a8af..886d27bdbe0460851d6f426b93ce608839dfaef2 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -14,9 +14,6 @@
 #define MAX_STACK 32
 #define MAX_LINES 1000
 
-extern int atoi(const char *);
-extern float strtof(const char *, char **);
-
 void iinit(interpreter *interp)
 {
        interp->vars = (variable *)calloc(MAX_VARS, sizeof(variable));
@@ -47,6 +44,9 @@ void iend(interpreter *it)
                        for (unsigned int j = 0; (int32_t)it->lines[i][j] > 0; j++) {
                                switch (it->lines[i][j]->valtype) {
                                case STRING:
+                                       if (!it->lines[i][j]->used)
+                                               free(it->lines[i][j]);
+                                       break;
                                case EXPR:
                                        free((void *)it->lines[i][j]->value.p);
                                        free(it->lines[i][j]);
@@ -156,44 +156,22 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next)
                variable *v = make_vare(0, expr);
                free(expr);
                return v;
-       } 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;
-               variable *v = interpreter_get_variable(interp, name);
-               free(name);
-               return v;
-       } 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;
-                               }
-                       }
+       } else {
+               variable *v = make_varn(0, 0.0f);
+               int inc = try_number(v, line);
+               if (inc != 0) {
+                       *next = inc;
+                       return v;
+               }
+               free(v);
+               char *name = 0;
+               inc = try_variable(&name, line);
+               if (inc != 0) {
+                       *next = (inc > 0) ? inc : -inc;
+                       variable *v = interpreter_get_variable(interp, name);
+                       free(name);
+                       return v;
                }
-               char *copy = (char *)malloc(end + 1);
-               strncpy(copy, line, end);
-               copy[end] = '\0';
-               variable *v;
-               if (dec)
-                       v = make_varn(0, strtof(copy, 0));
-               else
-                       v = make_varn(0, (float)atoi(copy));
-               free(copy);
-               *next = end;
-               return v;
        }
        return 0;
 }
@@ -364,7 +342,6 @@ variable *idoexpr(interpreter *interp, const char *line)
        void *ops[16];
        uint32_t ooffset = 0;
        uint32_t offset = 0;
-       uint32_t next = 0;
 
        // step 1 - break apart line
        for (uint8_t i = 0; i < 16; i++)
@@ -392,17 +369,33 @@ variable *idoexpr(interpreter *interp, const char *line)
                        ops[ooffset] = idoexpr(interp, line + offset + 1);
                        offset = i + 1;
                } else {
-                       uint32_t len = offset;
-                       for (; isalnum(line[len]) || line[len] == '.'; len++);
-                       len -= offset;
-                       char *copy = (char *)malloc(len + 1);
-                       strncpy(copy, line + offset, len);
-                       copy[len] = '\0';
-                       variable *v = make_var(interp, copy, &next);
-                       free(copy);
-                       ops[ooffset] = v;
-                       offset += next;
+                       variable *v = make_varn(0, 0.0f);
+                       int inc = try_number(v, line + offset);
+                       if (inc != 0) {
+                               ops[ooffset] = v;
+                               offset += inc;
+                       } else {
+                               free(v);
+                               char *name;
+                               inc = try_variable(&name, line + offset);
+                               if (inc != 0) {
+                                       v = interpreter_get_variable(interp, name);
+                                       ops[ooffset] = v;
+                                       free(name);
+                                       if (inc < 0) {
+                                               inc = -inc;
+                                               ops[ooffset + 2] = v;
+                                               ops[ooffset + 1] = (void *)5; // -
+                                               ops[ooffset] = make_varn(0, 0.0f);
+                                               ooffset += 2;
+                                       }
+                                       offset += inc;
+                               } else {
+                                       return 0;
+                               }
+                       }
                }
+
                if (ops[ooffset] == 0)
                        return 0;
                
@@ -421,10 +414,11 @@ variable *idoexpr(interpreter *interp, const char *line)
                                break;
                        }
                }
-               if (ops[ooffset] == 0)
-                       return 0;
-               ooffset++;
 
+               if (ops[ooffset] == 0) // implicit multiply
+                       ops[ooffset] = (void *)1;
+
+               ooffset++;
                // skip whitespace
                skipblank(line, eol, &offset);
        }
index 1b821cdb6864763abc5c875c29b27cdb21763481..1b0fdd67f57ac235636ec366e25b4ebb339f5b35 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -22,15 +22,15 @@ typedef struct {
 typedef int (*func_t)(interpreter *);
 
 void iinit(interpreter *);
-void iend(interpreter *it);
+void iend(interpreter *);
 
-void iskip(interpreter *it);
+void iskip(interpreter *);
 
 variable *inew_string(interpreter *, const char *, const char *);
 variable *inew_number(interpreter *, const char *, float);
 variable *inew_cfunc(interpreter *, const char *, func_t);
 
 int idoline(interpreter *, const char *);
-variable *idoexpr(interpreter *interp, const char *line);
+variable *idoexpr(interpreter *, const char *);
 
 #endif // PARSER_H_
diff --git a/script b/script
index c3837a34c8a2bcc35c89e22faf71892134d39b26..35497fe5aad353dbf97303bc0655db1b4e04c9d8 100644 (file)
--- a/script
+++ b/script
@@ -1,15 +1,7 @@
-set a "Het\n"
-set b a
-print b
+set x 42
+set eq ".a/a"
 
-#set a 0
-#do
-#      print "> "
-#      gets text
-#      set input "("
-#      concat input text
-#      concat input ")"
-#      expr input a
-#      print a
-#      print "\n"
-#while (1)
+solve eq > ans
+
+print ans
+print "\n"
diff --git a/shell.c b/shell.c
new file mode 100644 (file)
index 0000000..8704db6
--- /dev/null
+++ b/shell.c
@@ -0,0 +1,52 @@
+#include <parser.h>
+#include <builtins.h>
+
+#include "stack.h"
+
+#include <memory.h>
+#include <stdio.h>
+//#include <stdlib.h>
+#include <string.h>
+
+int s_put(interpreter *it)
+{
+       variable *v = igetarg(it, 0);
+       if (v->valtype == NUMBER)
+               printf("%.f", v->value.f);
+       else
+               printf("%s", (char *)v->value.p);
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       interpreter interp;
+
+       if (argc != 2) {
+               printf("Usage: %s file\n", argv[0]);
+               return -1;
+       }
+
+       FILE *fp = fopen(argv[1], "r");
+       if (fp == 0) {
+               printf("Could not open file: %s\n", argv[1]);
+               return -1;
+       }
+
+       iinit(&interp);
+       inew_cfunc(&interp, "print", s_put);
+
+       char *line = 0;
+       unsigned int size;
+       int result;
+       while (getline(&line, &size, fp) != -1) {
+               *strchr(line, '\n') = '\0';
+               result = idoline(&interp, line);
+               if (result != 0)
+                       printf("Error: %d\n", result);
+       }
+
+       fclose(fp);
+       iend(&interp);
+       return 0;
+}
index c170f799660e6ab22702b9ee234d709496aaa155..957a130190819574198b9cf9da59e3d35aa0f02a 100644 (file)
@@ -1,6 +1,7 @@
 #include "variable.h"
 #include "parser.h"
 
+#include <ctype.h>
 #include <stdlib.h>
 #include <memory.h>
 #include <string.h>
@@ -69,3 +70,66 @@ variable *make_vare(variable *v, const char *expr)
        return v;
 }
 
+int try_variable(char **name, const char *text)
+{
+       if (name == 0)
+               return 0;
+
+       int neg = 1;
+       int i = 0;
+
+       if (text[0] == '-') {
+               neg = -1;
+               i++;
+       }
+       if (!isalpha(text[i]))
+               return 0;
+
+       for (i++; isalnum(text[i]); i++);
+
+       int o = (neg < 0);
+       if (neg < 0)
+               i--;
+       *name = (char *)malloc(i + 1);
+       strncpy(*name, text + o, i);
+       (*name)[i] = '\0';
+       return (neg > 0) ? i : -(i + 1);
+}
+
+int try_number(variable *v, const char *text)
+{
+       if (v == 0)
+               return 0;
+
+       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';
+
+       make_varn(v, strtof(buf, 0));
+
+       free(buf);
+       return i;
+}
index b4a7c72172f0cacf00201acfb95f8d30f79e042c..da3badc0a37d13f6d2d5199df80541e52c8c7314 100644 (file)
@@ -25,4 +25,7 @@ variable *make_vars(variable *v, const char *s);
 variable *make_varf(variable *v, uint8_t fromc, uint32_t func);
 variable *make_vare(variable *v, const char *e);
 
+int try_number(variable *v, const char *text);
+int try_variable(char **name, const char *text);
+
 #endif // VARIABLE_H_