aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <tullivan99@gmail.com>2018-03-08 12:17:12 -0500
committerClyne Sullivan <tullivan99@gmail.com>2018-03-08 12:17:12 -0500
commit28447df15ac80d7dad1f4889d3d61fe7bfe42a12 (patch)
treedcc38b9a21e9771af0ce3d243660a59bd4992c52
parent40e157ffa2ae741088d2fbea22c9042b85daf108 (diff)
implicit multiply, negatives, solve
-rw-r--r--builtins.c19
-rw-r--r--parser.c102
-rw-r--r--parser.h6
-rw-r--r--script20
-rw-r--r--shell.c52
-rw-r--r--variable.c64
-rw-r--r--variable.h3
7 files changed, 195 insertions, 71 deletions
diff --git a/builtins.c b/builtins.c
index 5186e8b..0ab6f3b 100644
--- a/builtins.c
+++ b/builtins.c
@@ -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)
diff --git a/parser.c b/parser.c
index d7ba5ac..886d27b 100644
--- 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);
}
diff --git a/parser.h b/parser.h
index 1b821cd..1b0fdd6 100644
--- 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 c3837a3..35497fe 100644
--- 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
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;
+}
diff --git a/variable.c b/variable.c
index c170f79..957a130 100644
--- a/variable.c
+++ b/variable.c
@@ -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;
+}
diff --git a/variable.h b/variable.h
index b4a7c72..da3badc 100644
--- a/variable.h
+++ b/variable.h
@@ -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_