aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--old/parser.c225
-rw-r--r--old/parser.h31
-rw-r--r--old/variable.h24
-rw-r--r--parser.c339
-rw-r--r--parser.h29
-rw-r--r--shell.c40
-rw-r--r--variable.h26
7 files changed, 511 insertions, 203 deletions
diff --git a/old/parser.c b/old/parser.c
new file mode 100644
index 0000000..5e94e79
--- /dev/null
+++ b/old/parser.c
@@ -0,0 +1,225 @@
+#include <parser.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+static const char *interpreter_operators = "=(";
+
+bool strcmp(const char *a, const char *b)
+{
+ int i = 0;
+ for (; a[i] == b[i] && a[i] != '\0'; i++);
+ return a[i] == b[i];
+}
+
+bool strncmp(const char *a, const char *b, int count)
+{
+ int i = 0;
+ for (; a[i] == b[i] && i < count; i++);
+ return i == count;
+}
+
+uint8_t isalpha(char c)
+{
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
+}
+
+uint8_t isnum(char c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+uint8_t isname(char c)
+{
+ return isalpha(c) || isnum(c);
+}
+
+uint8_t isspace(char c)
+{
+ return (c == ' ' || c == '\t' || c == '\n');
+}
+
+uint8_t isoper(char c)
+{
+ for (uint8_t i = 0; i < sizeof(interpreter_operators); i++) {
+ if (c == interpreter_operators[i])
+ return 1;
+ }
+
+ return 0;
+}
+
+void interpreter_init(interpreter *interp)
+{
+ interp->status = READY;
+ interp->vcount = 0;
+ interp->vars = (variable *)calloc(32, sizeof(variable));
+ interp->names = (char **)calloc(32, sizeof(char *));
+ interp->stack = (stack_t *)calloc(64, sizeof(stack_t));
+}
+
+void interpreter_define_value(interpreter *interp, const char *name, int32_t value)
+{
+ interp->names[interp->vcount] = (char *)name;
+ interp->vars[interp->vcount].nameidx = interp->vcount;
+ interp->vars[interp->vcount].type = VALUE;
+ interp->vars[interp->vcount].value = (uint32_t)value;
+ interp->vcount++;
+}
+
+void interpreter_define_cfunc(interpreter *interp, const char *name, func_t addr)
+{
+ interp->names[interp->vcount] = (char *)name;
+ interp->vars[interp->vcount].nameidx = interp->vcount;
+ interp->vars[interp->vcount].type = CFUNCTION;
+ interp->vars[interp->vcount].value = (uint32_t)addr;
+ interp->vcount++;
+}
+
+int32_t interpreter_get_value(interpreter *interp, const char *name)
+{
+ for (uint16_t i = 0; i < interp->vcount; i++) {
+ if (!strcmp(interp->names[i], name))
+ return (int32_t)interp->vars[i].value;
+ }
+
+ return 0;
+}
+
+/**
+ * doline section
+ */
+
+bool namencmp(const char *name, const char *s)
+{
+ uint16_t i;
+ for (i = 0; name[i] == s[i] && s[i] != '\0'; i++);
+ return (name[i] == '\0' && !isname(s[i]));
+}
+
+uint16_t spacecount(const char *s)
+{
+ uint16_t i;
+ for (i = 0; isspace(s[i]); i++);
+ return i;
+}
+
+char *copystr(const char *s, char end)
+{
+ uint16_t len = 0;
+ while (s[len++] != end);
+ char *buf = (char *)malloc(len);
+ for (uint16_t i = 0; i < len; i++)
+ buf[i] = s[i];
+ return buf;
+}
+
+char *copysubstr(const char *s, int end)
+{
+ char *buf = (char *)malloc(end);
+ for (uint16_t i = 0; i < end; i++)
+ buf[i] = s[i];
+ return buf;
+}
+
+variable *interpreter_getvar(interpreter *interp, const char *line)
+{
+ for (uint16_t i = 0; i < interp->vcount; i++) {
+ if (namencmp(interp->names[i], line))
+ return &interp->vars[i];
+ }
+
+ return 0;
+}
+
+int interpreter_doline(interpreter *interp, const char *line)
+{
+ variable *bits[16];
+ uint16_t offset = 0, boffset = 0;
+
+ // check for var/func set or usage
+ int end;
+getvar:
+ for (end = 0; isname(line[end]); end++);
+ variable *var = interpreter_getvar(interp, line);
+
+ if (var != 0) {
+ bits[boffset++] = var;
+ } else {
+ // defining new variable
+ interpreter_define_value(interp, copysubstr(line, end), 0);
+ goto getvar; // try again
+ }
+
+ // skip whitespace/name
+ offset += end;
+ offset += spacecount(line + offset);
+
+ if (boffset == 0 && line[offset] != '=')
+ return -1; // variable not found
+
+ // find operator
+ if (line[offset] == '\0') {
+ // print value
+ return -99;
+ } else if (line[offset] == '=') {
+ // assignment/expression
+ offset++;
+ offset += spacecount(line + offset);
+ bits[0]->value = (uint32_t)copystr(line + offset, '\0');
+ } else if (line[offset] == '(') {
+ // function call
+ offset++;
+ if (bits[0]->type != FUNCTION && bits[0]->type != CFUNCTION)
+ return -2;
+ offset += spacecount(line + offset);
+
+ // collect arg offsets
+ uint16_t offsets[8];
+ uint8_t ooffset = 0;
+ while (line[offset] != ')' && line[offset] != '\0') {
+ offsets[ooffset] = offset;
+ offset += spacecount(line + offset);
+
+ uint8_t isvn = 1;
+ do {
+ if (line[offset] == ' ' || line[offset] == '\t') {
+ offset += spacecount(line + offset);
+ isvn = 0;
+ }
+
+ if (line[offset] == ',') {
+ offset++;
+ ooffset++;
+ break;
+ } else if (line[offset] == ')') {
+ ooffset++;
+ break;
+ } else if (isvn == 0) {
+ return -3;
+ }
+ } while (++offset);
+ }
+
+ // populate stack
+ for (uint8_t i = 0; i < ooffset; i++) {
+ uint16_t j;
+ for (j = offsets[i]; line[j] != ' ' && line[j] != '\t' &&
+ line[j] != ',' && line[j] != ')'; j++);
+ j -= offsets[i];
+
+ variable *var = interpreter_getvar(interp, line + offsets[i]);
+ if (var != 0)
+ interp->stack[i] = copystr((char *)var->value, '\0');
+ else
+ interp->stack[i] = copysubstr(line + offsets[i], j);
+ }
+
+ ((func_t)bits[0]->value)(interp->stack);
+ } else {
+ return -2; // invalid operation
+ }
+
+ return 0;
+}
+
diff --git a/old/parser.h b/old/parser.h
new file mode 100644
index 0000000..c6a2b17
--- /dev/null
+++ b/old/parser.h
@@ -0,0 +1,31 @@
+#ifndef PARSER_H_
+#define PARSER_H_
+
+#include <variable.h>
+
+typedef void *stack_t;
+
+typedef struct {
+ uint16_t status;
+ uint16_t vcount;
+ variable *vars;
+ char **names;
+ stack_t *stack;
+} interpreter;
+
+enum status {
+ READY = 0
+};
+
+typedef void (*func_t)(stack_t *);
+
+void interpreter_init(interpreter *);
+
+void interpreter_define_value(interpreter *, const char *, int32_t);
+void interpreter_define_cfunc(interpreter *, const char *, func_t);
+
+int32_t interpreter_get_value(interpreter *, const char *);
+
+int interpreter_doline(interpreter *, const char *);
+
+#endif // PARSER_H_
diff --git a/old/variable.h b/old/variable.h
new file mode 100644
index 0000000..fd84a6e
--- /dev/null
+++ b/old/variable.h
@@ -0,0 +1,24 @@
+#ifndef TOKEN_H_
+#define TOKEN_H_
+
+#include <stdint.h>
+
+typedef struct {
+ uint16_t nameidx;
+ uint8_t type;
+ uint8_t info;
+ uint32_t value;
+} variable;
+
+#define INFO_ARGS(x) ((x) & 0x07)
+#define INFO_RET (1 << 3)
+
+enum vartype {
+ VALUE = 0,
+ VARIABLE,
+ OPERATOR,
+ FUNCTION,
+ CFUNCTION
+};
+
+#endif // TOKEN_H_
diff --git a/parser.c b/parser.c
index 5e94e79..6ad7daf 100644
--- a/parser.c
+++ b/parser.c
@@ -1,225 +1,238 @@
#include <parser.h>
-#include <stdbool.h>
+#include <ctype.h>
#include <stdlib.h>
+#include <string.h>
-static const char *interpreter_operators = "=(";
+#define MAX_VARS 16
+#define MAX_STACK 32
-bool strcmp(const char *a, const char *b)
+char *strclone(const char *s)
{
- int i = 0;
- for (; a[i] == b[i] && a[i] != '\0'; i++);
- return a[i] == b[i];
+ char *clone = (char *)malloc(strlen(s));
+ strcpy(clone, s);
+ return clone;
}
-bool strncmp(const char *a, const char *b, int count)
+char *strnclone(const char *s, uint32_t n)
{
- int i = 0;
- for (; a[i] == b[i] && i < count; i++);
- return i == count;
+ char *clone = (char *)malloc(n);
+ strncpy(clone, s, n);
+ return clone;
}
-uint8_t isalpha(char c)
+void iinit(interpreter *interp)
{
- return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
+ 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;
}
-uint8_t isnum(char c)
+variable *interpreter_get_variable(interpreter *interp, const char *name)
{
- return (c >= '0' && c <= '9');
+ for (uint32_t i = 0; i < MAX_VARS; i++) {
+ if (!interp->vars[i].used) {
+ interp->vars[i].used = 1;
+ interp->vars[i].valtype = FUNC;
+ interp->vars[i].value = 0;
+ interp->vnames[i] = strclone(name);
+ return &interp->vars[i];
+ } else if (interp->vnames[i] != 0 && !strcmp(interp->vnames[i], name)) {
+ return &interp->vars[i];
+ }
+ }
+ return 0;
}
-uint8_t isname(char c)
+void inew_string(interpreter *interp, const char *name, char *value)
{
- return isalpha(c) || isnum(c);
+ variable *v = interpreter_get_variable(interp, name);
+ if (v != 0) {
+ v->valtype = STRING;
+ v->value = (uint32_t)value;
+ }
}
-uint8_t isspace(char c)
+void inew_integer(interpreter *interp, const char *name, int32_t value)
{
- return (c == ' ' || c == '\t' || c == '\n');
+ variable *v = interpreter_get_variable(interp, name);
+ if (v != 0) {
+ v->valtype = INTEGER;
+ v->value = (uint32_t)value;
+ }
}
-uint8_t isoper(char c)
+void inew_float(interpreter *interp, const char *name, float value)
{
- for (uint8_t i = 0; i < sizeof(interpreter_operators); i++) {
- if (c == interpreter_operators[i])
- return 1;
+ variable *v = interpreter_get_variable(interp, name);
+ if (v != 0) {
+ v->valtype = FLOAT;
+ v->value = (uint32_t)value;
}
-
- return 0;
}
-void interpreter_init(interpreter *interp)
+void inew_cfunc(interpreter *interp, const char *name, func_t func)
{
- interp->status = READY;
- interp->vcount = 0;
- interp->vars = (variable *)calloc(32, sizeof(variable));
- interp->names = (char **)calloc(32, sizeof(char *));
- interp->stack = (stack_t *)calloc(64, sizeof(stack_t));
+ variable *v = interpreter_get_variable(interp, name);
+ if (v != 0) {
+ v->fromc = 1;
+ v->valtype = FUNC;
+ v->value = (uint32_t)func;
+ }
}
-void interpreter_define_value(interpreter *interp, const char *name, int32_t value)
+uint8_t eol(int c)
{
- interp->names[interp->vcount] = (char *)name;
- interp->vars[interp->vcount].nameidx = interp->vcount;
- interp->vars[interp->vcount].type = VALUE;
- interp->vars[interp->vcount].value = (uint32_t)value;
- interp->vcount++;
+ return c == '\n' || c == '\0';
}
-void interpreter_define_cfunc(interpreter *interp, const char *name, func_t addr)
+uint8_t eot(int c)
{
- interp->names[interp->vcount] = (char *)name;
- interp->vars[interp->vcount].nameidx = interp->vcount;
- interp->vars[interp->vcount].type = CFUNCTION;
- interp->vars[interp->vcount].value = (uint32_t)addr;
- interp->vcount++;
+ return eol(c) || c == ' ';
}
-int32_t interpreter_get_value(interpreter *interp, const char *name)
+variable *make_var(interpreter *interp, const char *line, uint32_t *next)
{
- for (uint16_t i = 0; i < interp->vcount; i++) {
- if (!strcmp(interp->names[i], name))
- return (int32_t)interp->vars[i].value;
+ 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->valtype = STRING;
+ v->value = (uint32_t)strnclone(line + 1, end - 1);
+ *next = end + 1;
+ return v;
+ }
+ end++;
+ }
+ return 0;
+ } else if (line[0] == '(') { // equation 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
+ // TODO make var
+ return 0;
+ }
+ end++;
+ }
+ } 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;
+ }
+ return 0;
+ }
+ }
+ variable *v = (variable *)malloc(sizeof(variable));
+ v->valtype = INTEGER;
+ v->value = atoi(line);
+ *next = end;
+ return v;
}
-
return 0;
}
-/**
- * doline section
- */
-
-bool namencmp(const char *name, const char *s)
+int idoline(interpreter *interp, const char *line)
{
- uint16_t i;
- for (i = 0; name[i] == s[i] && s[i] != '\0'; i++);
- return (name[i] == '\0' && !isname(s[i]));
+ variable *ops[8];
+ uint32_t ooffset = 0;
+ uint32_t offset = 0;
+ uint32_t next;
+
+ // 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 = 0; i < ooffset - 1; i++, interp->stidx++)
+ interp->stack[i] = ops[i + 1];
+
+ ((func_t)ops[0]->value)(interp);
+
+ return 0;
}
-uint16_t spacecount(const char *s)
+char *igetarg_string(interpreter *interp, uint32_t index)
{
- uint16_t i;
- for (i = 0; isspace(s[i]); i++);
- return i;
+ if (index >= interp->stidx)
+ return 0;
+ if (interp->stack[index]->valtype != STRING)
+ return 0;
+ return (char *)interp->stack[index]->value;
}
-char *copystr(const char *s, char end)
+int igetarg_integer(interpreter *interp, uint32_t index)
{
- uint16_t len = 0;
- while (s[len++] != end);
- char *buf = (char *)malloc(len);
- for (uint16_t i = 0; i < len; i++)
- buf[i] = s[i];
- return buf;
+ if (index >= interp->stidx)
+ return 0;
+ if (interp->stack[index]->valtype != INTEGER)
+ return 0;
+ return (int)interp->stack[index]->value;
}
-char *copysubstr(const char *s, int end)
+float igetarg_float(interpreter *interp, uint32_t index)
{
- char *buf = (char *)malloc(end);
- for (uint16_t i = 0; i < end; i++)
- buf[i] = s[i];
- return buf;
+ if (index >= interp->stidx)
+ return 0;
+ if (interp->stack[index]->valtype != FLOAT)
+ return 0;
+ return (float)interp->stack[index]->value;
}
-variable *interpreter_getvar(interpreter *interp, const char *line)
+/*char *iget_string(interpreter *, const char *)
{
- for (uint16_t i = 0; i < interp->vcount; i++) {
- if (namencmp(interp->names[i], line))
- return &interp->vars[i];
- }
- return 0;
}
-int interpreter_doline(interpreter *interp, const char *line)
+int iget_integer(interpreter *, const char *)
{
- variable *bits[16];
- uint16_t offset = 0, boffset = 0;
-
- // check for var/func set or usage
- int end;
-getvar:
- for (end = 0; isname(line[end]); end++);
- variable *var = interpreter_getvar(interp, line);
-
- if (var != 0) {
- bits[boffset++] = var;
- } else {
- // defining new variable
- interpreter_define_value(interp, copysubstr(line, end), 0);
- goto getvar; // try again
- }
- // skip whitespace/name
- offset += end;
- offset += spacecount(line + offset);
-
- if (boffset == 0 && line[offset] != '=')
- return -1; // variable not found
-
- // find operator
- if (line[offset] == '\0') {
- // print value
- return -99;
- } else if (line[offset] == '=') {
- // assignment/expression
- offset++;
- offset += spacecount(line + offset);
- bits[0]->value = (uint32_t)copystr(line + offset, '\0');
- } else if (line[offset] == '(') {
- // function call
- offset++;
- if (bits[0]->type != FUNCTION && bits[0]->type != CFUNCTION)
- return -2;
- offset += spacecount(line + offset);
-
- // collect arg offsets
- uint16_t offsets[8];
- uint8_t ooffset = 0;
- while (line[offset] != ')' && line[offset] != '\0') {
- offsets[ooffset] = offset;
- offset += spacecount(line + offset);
-
- uint8_t isvn = 1;
- do {
- if (line[offset] == ' ' || line[offset] == '\t') {
- offset += spacecount(line + offset);
- isvn = 0;
- }
-
- if (line[offset] == ',') {
- offset++;
- ooffset++;
- break;
- } else if (line[offset] == ')') {
- ooffset++;
- break;
- } else if (isvn == 0) {
- return -3;
- }
- } while (++offset);
- }
-
- // populate stack
- for (uint8_t i = 0; i < ooffset; i++) {
- uint16_t j;
- for (j = offsets[i]; line[j] != ' ' && line[j] != '\t' &&
- line[j] != ',' && line[j] != ')'; j++);
- j -= offsets[i];
-
- variable *var = interpreter_getvar(interp, line + offsets[i]);
- if (var != 0)
- interp->stack[i] = copystr((char *)var->value, '\0');
- else
- interp->stack[i] = copysubstr(line + offsets[i], j);
- }
+}
- ((func_t)bits[0]->value)(interp->stack);
- } else {
- return -2; // invalid operation
- }
+float iget_float(interpreter *, const char *)
+{
- return 0;
-}
+}*/
diff --git a/parser.h b/parser.h
index c6a2b17..c2efba3 100644
--- a/parser.h
+++ b/parser.h
@@ -3,29 +3,32 @@
#include <variable.h>
-typedef void *stack_t;
+typedef variable *stack_t;
typedef struct {
- uint16_t status;
- uint16_t vcount;
variable *vars;
- char **names;
+ char **vnames;
stack_t *stack;
+ uint32_t stidx;
} interpreter;
-enum status {
- READY = 0
-};
+typedef void (*func_t)(interpreter *);
-typedef void (*func_t)(stack_t *);
+void iinit(interpreter *);
-void interpreter_init(interpreter *);
+void inew_string(interpreter *, const char *, char *);
+void inew_integer(interpreter *, const char *, int32_t);
+void inew_float(interpreter *, const char *, float);
+void inew_cfunc(interpreter *, const char *, func_t);
-void interpreter_define_value(interpreter *, const char *, int32_t);
-void interpreter_define_cfunc(interpreter *, const char *, func_t);
+int idoline(interpreter *, const char *);
-int32_t interpreter_get_value(interpreter *, const char *);
+char *igetarg_string(interpreter *, uint32_t);
+int igetarg_integer(interpreter *, uint32_t);
+float igetarg_float(interpreter *, uint32_t);
-int interpreter_doline(interpreter *, const char *);
+char *iget_string(interpreter *, const char *);
+int iget_integer(interpreter *, const char *);
+float iget_float(interpreter *, const char *);
#endif // PARSER_H_
diff --git a/shell.c b/shell.c
index b19add8..578cabe 100644
--- a/shell.c
+++ b/shell.c
@@ -1,26 +1,42 @@
#include <parser.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
-void test(stack_t *stack)
+void test(interpreter *it)
{
- printf("%s\n", stack[0]);
+ char *s = igetarg_string(it, 0);
+ if (s == 0)
+ s = "(null)";
+ printf("%s\n", s);
}
-int main(int argc, char *argv[])
+void quit(interpreter *it)
+{
+ (void)it;
+ exit(0);
+}
+
+int main()
{
interpreter interp;
- interpreter_init(&interp);
- interpreter_define_value(&interp, "answer", "42");
- interpreter_define_cfunc(&interp, "test", test);
+ iinit(&interp);
+ inew_integer(&interp, "answer", 42);
+ inew_cfunc(&interp, "put", test);
+ inew_cfunc(&interp, "exit", quit);
+
- if (argc > 1) {
- for (int i = 1; i < argc; i++) {
- int result = interpreter_doline(&interp, argv[i]);
- if (result != 0)
- printf("%d\n", result);
- }
+ char *line = 0;
+ unsigned int size;
+ int result;
+ while (1) {
+ getline(&line, &size, stdin);
+ *strchr(line, '\n') = '\0';
+ result = idoline(&interp, line);
+ if (result != 0)
+ printf("Error: %d\n", result);
}
return 0;
diff --git a/variable.h b/variable.h
index fd84a6e..b0f27d2 100644
--- a/variable.h
+++ b/variable.h
@@ -1,24 +1,20 @@
-#ifndef TOKEN_H_
-#define TOKEN_H_
+#ifndef VARIABLE_H_
+#define VARIABLE_H_
#include <stdint.h>
typedef struct {
- uint16_t nameidx;
- uint8_t type;
- uint8_t info;
+ uint8_t used :1;
+ uint8_t fromc :1;
+ uint8_t valtype :2;
uint32_t value;
} variable;
-#define INFO_ARGS(x) ((x) & 0x07)
-#define INFO_RET (1 << 3)
-
-enum vartype {
- VALUE = 0,
- VARIABLE,
- OPERATOR,
- FUNCTION,
- CFUNCTION
+enum valtype {
+ STRING = 0,
+ INTEGER,
+ FLOAT,
+ FUNC
};
-#endif // TOKEN_H_
+#endif // VARIABLE_H_