aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--parser.c60
-rw-r--r--script5
-rw-r--r--shell.c18
3 files changed, 71 insertions, 12 deletions
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;
}