diff options
author | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2022-01-12 18:46:55 +0000 |
---|---|---|
committer | Peter Mikkelsen <petermikkelsen10@gmail.com> | 2022-01-12 18:46:55 +0000 |
commit | d596e90554816e62d39fbaf68713810ed1eaf764 (patch) | |
tree | cf06e3beab322bd261248761a90cf93d4d520bd7 | |
parent | 85aa2ad424c68343ef09e5f6df243ad6499e47d5 (diff) |
Add statements separated by ⋄
-rw-r--r-- | apl9.h | 13 | ||||
-rw-r--r-- | eval.c | 67 | ||||
-rw-r--r-- | lexer.c | 61 | ||||
-rw-r--r-- | main.c | 15 |
4 files changed, 88 insertions, 68 deletions
@@ -29,7 +29,7 @@ typedef enum /* Data types */ typedef struct Array Array; -typedef struct Expr Expr; +typedef struct Statement Statement; typedef struct Function Function; typedef struct Datum Datum; typedef struct Symbol Symbol; @@ -49,17 +49,18 @@ struct Array }; }; -struct Expr +struct Statement { int ntoks; Datum *toks; + Statement *next; }; struct Function { union { int code; - Expr *dfn; + Statement *dfn; }; Array *left; }; @@ -69,7 +70,7 @@ struct Datum datumTag tag; union { Array *array; - Expr expr; + Statement stmt; Function func; Symbol *symbol; }; @@ -98,7 +99,7 @@ Rune *ppdatums(Datum *, int); Rune *pparray(Array *); /* lexer.c */ -Datum *lexline(Rune *, int *, Symtab *); +Statement *lexline(Rune *, Symtab *); /* array.c */ Array *mkarray(int, int, int); @@ -108,7 +109,7 @@ int simplearray(Array *); int simplescalar(Array *); /* eval.c */ -Datum *eval(Datum *, int *); +Datum *eval(Statement *); /* symbol.c */ Symbol *getsym(Symtab *, Rune *); @@ -59,47 +59,46 @@ evalfn evalfns[15][15] = { }; Datum * -eval(Datum *tokens, int *ntoks) +eval(Statement *stmt) { errormsg = nil; /* start by looking up first variable if needed */ - if(*ntoks > 0 && tokens[(*ntoks)-1].tag == NameTag){ - Datum *value = lookup(tokens[(*ntoks)-1]); + if(stmt->ntoks > 0 && stmt->toks[stmt->ntoks-1].tag == NameTag){ + Datum *value = lookup(stmt->toks[stmt->ntoks-1]); if(value == nil) - *ntoks = 0; + return nil; else - tokens[(*ntoks)-1] = *value; + stmt->toks[stmt->ntoks-1] = *value; } - while(*ntoks > 1){ + while(stmt->ntoks > 1){ int maxlevel = 0; int offset; evalfn fn = nil; - traceprint("CURRENT: %S\n", ppdatums(tokens, *ntoks)); - for(offset = (*ntoks)-1; offset >= 0; offset--){ + traceprint("CURRENT: %S\n", ppdatums(stmt->toks, stmt->ntoks)); + for(offset = stmt->ntoks-1; offset >= 0; offset--){ int level; retry: if(offset == 0) level = 0; else{ - Datum left = tokens[offset-1]; - Datum right = tokens[offset]; + Datum left = stmt->toks[offset-1]; + Datum right = stmt->toks[offset]; level = bindingstrengths[left.tag][right.tag]; } - if(level == 0 && tokens[offset-1].tag == NameTag){ - Datum *value = lookup(tokens[offset-1]); - if(value == nil){ - *ntoks = 0; - return tokens; - }else{ - tokens[offset-1] = *value; + if(level == 0 && stmt->toks[offset-1].tag == NameTag){ + Datum *value = lookup(stmt->toks[offset-1]); + if(value == nil) + return nil; + else{ + stmt->toks[offset-1] = *value; goto retry; } }else if(level < maxlevel){ - Datum left = tokens[offset]; - Datum right = tokens[offset+1]; + Datum left = stmt->toks[offset]; + Datum right = stmt->toks[offset+1]; fn = evalfns[left.tag][right.tag]; traceprint("Reducing %S and %S (fn=%p, level=%d, max=%d)\n", ppdatum(left), ppdatum(right), fn, level, maxlevel); break; @@ -108,15 +107,21 @@ retry: } if(maxlevel == 0){ errormsg = L"No reduce rule. Syntax error."; - *ntoks = 0; + return nil; }else{ - tokens[offset] = fn(tokens[offset],tokens[offset+1]); - for(int i = offset+1; i < (*ntoks)-1; i++) - tokens[i] = tokens[i+1]; - (*ntoks)--; + stmt->toks[offset] = fn(stmt->toks[offset],stmt->toks[offset+1]); + for(int i = offset+1; i < stmt->ntoks-1; i++) + stmt->toks[i] = stmt->toks[i+1]; + stmt->ntoks--; } } - return tokens; + if(stmt->ntoks == 1){ + if(stmt->next) + return eval(stmt->next); + else + return stmt->toks; + }else + return nil; } Datum * @@ -173,10 +178,10 @@ Datum lpar(Datum left, Datum right) { /* build up a parthenthesised expression */ - left.expr.ntoks++; - left.expr.toks = realloc(left.expr.toks, sizeof(Datum) * left.expr.ntoks); - left.expr.toks[left.expr.ntoks-1] = right; - traceprint("LPAR: %S\n", ppdatums(left.expr.toks, left.expr.ntoks)); + left.stmt.ntoks++; + left.stmt.toks = realloc(left.stmt.toks, sizeof(Datum) * left.stmt.ntoks); + left.stmt.toks[left.stmt.ntoks-1] = right; + traceprint("LPAR: %S\n", ppdatums(left.stmt.toks, left.stmt.ntoks)); return left; } @@ -185,8 +190,8 @@ rpar(Datum left, Datum right) { /* evaluate a parenthesis expression and return the result */ USED(right); - traceprint("RPAR: %S\n", ppdatums(left.expr.toks, left.expr.ntoks)); - Datum *result = eval(left.expr.toks, &left.expr.ntoks); + traceprint("RPAR: %S\n", ppdatums(left.stmt.toks, left.stmt.ntoks)); + Datum *result = eval(&left.stmt); result[0].array->stranded = 0; return result[0]; /* TODO handle error if ntoks != 1 */ } @@ -8,40 +8,46 @@ Rune primmonopnames[] = L"¨⍨⌸⌶&"; Rune primdyadopnames[] = L"⍣.∘⍤⍥@⍠⌺"; Rune primhybridnames[] = L"/\⌿⍀"; -Datum * -lexline(Rune *line, int *ntoks, Symtab *symtab) +Statement * +lexline(Rune *line, Symtab *symtab) { int offset = 0; int len = runestrlen(line); - Datum *tokens = mallocz(sizeof(Datum) * MAX_LINE_TOKENS, 1); - *ntoks = 0; + Statement *stmt = malloc(sizeof(Statement)); + stmt->ntoks = 0; + stmt->toks = mallocz(sizeof(Datum) * MAX_LINE_TOKENS, 1); + stmt->next = nil; + while(offset < len){ Rune *p; if(isspacerune(line[offset])){ offset++; continue; - }else if(runestrchr(L"(){}[]←", line[offset])){ + }else if(runestrchr(L"(){}[]←⋄", line[offset])){ switch(line[offset]){ - case '(': tokens[*ntoks].tag = LParTag; break; - case ')': tokens[*ntoks].tag = RParTag; break; - case '{': tokens[*ntoks].tag = LCurlTag; break; - case '}': tokens[*ntoks].tag = RCurlTag; break; - case '[': tokens[*ntoks].tag = LBracketTag; break; - case ']': tokens[*ntoks].tag = RBracketTag; break; - case L'←': tokens[*ntoks].tag = ArrowTag; break; + case '(': stmt->toks[stmt->ntoks].tag = LParTag; break; + case ')': stmt->toks[stmt->ntoks].tag = RParTag; break; + case '{': stmt->toks[stmt->ntoks].tag = LCurlTag; break; + case '}': stmt->toks[stmt->ntoks].tag = RCurlTag; break; + case '[': stmt->toks[stmt->ntoks].tag = LBracketTag; break; + case ']': stmt->toks[stmt->ntoks].tag = RBracketTag; break; + case L'←': stmt->toks[stmt->ntoks].tag = ArrowTag; break; + case L'⋄': + stmt->next = lexline(&line[offset+1], symtab); + goto end; } offset++; }else if(p = runestrchr(primfuncnames, line[offset])){ - tokens[*ntoks].tag = FunctionTag; - tokens[*ntoks].func.code = p-primfuncnames; + stmt->toks[stmt->ntoks].tag = FunctionTag; + stmt->toks[stmt->ntoks].func.code = p-primfuncnames; offset++; }else if(p = runestrchr(primmonopnames, line[offset])){ - tokens[*ntoks].tag = MonadicOpTag; - tokens[*ntoks].func.code = p-primmonopnames; + stmt->toks[stmt->ntoks].tag = MonadicOpTag; + stmt->toks[stmt->ntoks].func.code = p-primmonopnames; offset++; }else if(p = runestrchr(primdyadopnames, line[offset])){ - tokens[*ntoks].tag = DyadicOpTag; - tokens[*ntoks].func.code = p-primdyadopnames; + stmt->toks[stmt->ntoks].tag = DyadicOpTag; + stmt->toks[stmt->ntoks].func.code = p-primdyadopnames; offset++; }else if(isdigitrune(line[offset])){ char buf[64]; @@ -51,8 +57,8 @@ lexline(Rune *line, int *ntoks, Symtab *symtab) offset++; } *p = 0; - tokens[*ntoks].tag = ArrayTag; - tokens[*ntoks].array = mkscalarint(atoll(buf)); + stmt->toks[stmt->ntoks].tag = ArrayTag; + stmt->toks[stmt->ntoks].array = mkscalarint(atoll(buf)); }else if(isalpharune(line[offset]) || line[offset] == L'⎕'){ int quadname = L'⎕' == line[offset]; Rune buf[64]; @@ -66,14 +72,17 @@ lexline(Rune *line, int *ntoks, Symtab *symtab) offset++; } *p = 0; - tokens[*ntoks].tag = NameTag; - tokens[*ntoks].symbol = getsym(symtab, buf); + stmt->toks[stmt->ntoks].tag = NameTag; + stmt->toks[stmt->ntoks].symbol = getsym(symtab, buf); }else{ print("Can't lex: %S\n", &line[offset]); - *ntoks = 0; - break; + free(stmt->toks); + free(stmt); + return 0; } - (*ntoks)++; + stmt->ntoks++; } - return tokens; +end: + stmt->toks = realloc(stmt->toks, sizeof(Datum) * stmt->ntoks); + return stmt; }
\ No newline at end of file @@ -58,13 +58,18 @@ prompt(Rune *pr) Datum * evalline(Rune *line) { - int ntoks; - Datum *tokens = lexline(line, &ntoks, globalsymtab); - Datum *result = eval(tokens, &ntoks); - if(ntoks == 1) + Statement *stmts = lexline(line, globalsymtab); + Datum *result = eval(stmts); + if(result) return result; else{ - free(tokens); + Statement *s = stmts; + while(s != nil){ + Statement *tmp = s; + s = s->next; + free(tmp->toks); + free(tmp); + } return nil; } }
\ No newline at end of file |