From 125fb18e49dbef25b97bb546198d3f35603e58f1 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Tue, 6 Feb 2018 08:48:21 -0500 Subject: [PATCH] conditionals: if, do/while --- parser.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-------- script | 5 +++++ shell.c | 18 +++++++++++++---- 3 files changed, 71 insertions(+), 12 deletions(-) create mode 100644 script diff --git a/parser.c b/parser.c index 87a584e..0f75c9e 100644 --- a/parser.c +++ b/parser.c @@ -16,14 +16,14 @@ static char *str_undef = "(undefined)"; char *strclone(const char *s) { - char *clone = (char *)malloc(strlen(s)); + char *clone = (char *)malloc(strlen(s) + 1); strcpy(clone, s); return clone; } char *strnclone(const char *s, uint32_t n) { - char *clone = (char *)malloc(n); + char *clone = (char *)malloc(n + 1); strncpy(clone, s, n); return clone; } @@ -74,10 +74,25 @@ uint32_t findend(const char *s, char o, char c) return i; } + +void skipblank(const char *s, uint8_t (*cmp)(int), uint32_t *offset) +{ + uint32_t i = *offset; + while (!cmp(s[i])) { + if (s[i] != ' ' && s[i] != '\t') + break; + i++; + } + *offset = i; +} + int ifunc_set(interpreter *it); int ifunc_jmp(interpreter *it); int ifunc_label(interpreter *it); int ifunc_end(interpreter *it); +int ifunc_if(interpreter *it); +int ifunc_do(interpreter *it); +int ifunc_while(interpreter *it); variable *idoexpr(interpreter *interp, const char *line); @@ -99,6 +114,9 @@ void iinit(interpreter *interp) inew_cfunc(interp, "jmp", ifunc_jmp); inew_cfunc(interp, "func", ifunc_label); inew_cfunc(interp, "end", ifunc_end); + inew_cfunc(interp, "if", ifunc_if); + inew_cfunc(interp, "do", ifunc_do); + inew_cfunc(interp, "while", ifunc_while); } void ipush(interpreter *it, void *v) @@ -266,6 +284,7 @@ loop: offset = 0; // step 1 - convert to tokens + skipblank(line, eol, &offset); while (!eol(line[offset])) { ops[ooffset] = make_var(interp, line + offset, &next); if (ops[ooffset] == 0) { @@ -274,9 +293,7 @@ loop: ooffset++; offset += next; } - - // skip whitespace - for (; line[offset] == ' ' && !eol(line[offset]); offset++); + skipblank(line, eol, &offset); } // step 2 - execute @@ -365,7 +382,7 @@ variable *idoexpr(interpreter *interp, const char *line) // step 1 - break apart line // skip whitespace - for (; line[offset] == ' ' && !eol(line[offset]); offset++); + skipblank(line, eol, &offset); while (!eoe(line[offset])) { if (line[offset] == '(') { uint8_t indent = 0; @@ -404,7 +421,7 @@ variable *idoexpr(interpreter *interp, const char *line) offset += next; // skip whitespace - for (; line[offset] == ' ' && !eoe(line[offset]); offset++); + skipblank(line, eoe, &offset); if (eoe(line[offset])) break; @@ -421,7 +438,7 @@ variable *idoexpr(interpreter *interp, const char *line) ooffset++; // skip whitespace - for (; line[offset] == ' ' && !eol(line[offset]); offset++); + skipblank(line, eol, &offset); } if (ooffset % 2 == 0) @@ -557,6 +574,14 @@ int ifunc_label(interpreter *it) return 0; } +int ifunc_if(interpreter *it) +{ + int v = igetarg_integer(it, 0); + if (v == 0) + it->indent++; + return 0; +} + int ifunc_end(interpreter *it) { if (it->stidx > 0) { @@ -576,6 +601,25 @@ int ifunc_jmp(interpreter *it) return 0; } +int ifunc_do(interpreter *it) +{ + ipush(it, (void *)it->lnidx); + return 0; +} + +int ifunc_while(interpreter *it) +{ + int c = igetarg_integer(it, 0); + ipop(it); + int nidx = (int)ipop(it); + if (c != 0) { + ipush(it, (void *)nidx); + it->lnidx = nidx; + } + ipush(it, 0); + return 0; +} + /** * Builtin operations */ diff --git a/script b/script new file mode 100644 index 0000000..b31a18e --- /dev/null +++ b/script @@ -0,0 +1,5 @@ +set a 0 +do + put a + set a (a+1) +while (a<5) diff --git a/shell.c b/shell.c index 1d22269..751ef8f 100644 --- a/shell.c +++ b/shell.c @@ -41,10 +41,21 @@ int quit(interpreter *it) return 0; } -int main() +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, "put", s_put); inew_cfunc(&interp, "tp", s_type); @@ -54,14 +65,13 @@ int main() char *line = 0; unsigned int size; int result; - while (1) { - printf("%d> ", interp.lnidx); - getline(&line, &size, stdin); + while (getline(&line, &size, fp) != -1) { *strchr(line, '\n') = '\0'; result = idoline(&interp, line); if (result != 0) printf("Error: %d\n", result); } + fclose(fp); return 0; }