#include #include #include #include "apl9.h" Rune primhybridnames[] = L"/\⌿⍀"; Statement * lexline(Rune *line) { int offset = 0; int len = runestrlen(line); 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])){ switch(line[offset]){ 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]); goto end; case L'⍝': goto end; } offset++; }else if(line[offset] == '{'){ Rune buf[MAX_LINE_LENGTH]; Rune *p = buf; offset++; while(line[offset] != '}' && offset < len){ *p = line[offset]; p++; offset++; } if(line[offset] != '}') goto syntax_error; *p = 0; offset++; stmt->toks[stmt->ntoks].tag = FunctionTag; stmt->toks[stmt->ntoks].func.type = FunctypeDfn; stmt->toks[stmt->ntoks].func.dfn = runestrdup(buf); }else if(line[offset] == '('){ int unclosed = 1; Rune buf[MAX_LINE_LENGTH]; Rune *p = buf; offset++; while((line[offset] != ')' || unclosed > 1) && offset < len){ if(line[offset] == '(') unclosed++; else if(line[offset] == ')') unclosed--; *p = line[offset]; p++; offset++; } if(line[offset] != ')') goto syntax_error; *p = 0; offset++; stmt->toks[stmt->ntoks].tag = LParTag; stmt->toks[stmt->ntoks].stmt = *lexline(buf); stmt->ntoks++; stmt->toks[stmt->ntoks].tag = RParTag; }else if(p = runestrchr(primfuncnames, line[offset])){ stmt->toks[stmt->ntoks].tag = FunctionTag; stmt->toks[stmt->ntoks].func.type = FunctypePrim; stmt->toks[stmt->ntoks].func.code = p-primfuncnames; offset++; }else if(p = runestrchr(primmonopnames, line[offset])){ stmt->toks[stmt->ntoks].tag = MonadicOpTag; stmt->toks[stmt->ntoks].operator.type = OperatortypePrim; stmt->toks[stmt->ntoks].operator.dyadic = 0; stmt->toks[stmt->ntoks].operator.code = p-primmonopnames; offset++; }else if(p = runestrchr(primdyadopnames, line[offset])){ stmt->toks[stmt->ntoks].tag = DyadicOpTag; stmt->toks[stmt->ntoks].operator.type = OperatortypePrim; stmt->toks[stmt->ntoks].operator.dyadic = 1; stmt->toks[stmt->ntoks].operator.code = p-primdyadopnames; offset++; }else if(isdigitrune(line[offset])){ char buf[64]; char *p = buf; while(isdigitrune(line[offset])){ p += runetochar(p, &line[offset]); offset++; } *p = 0; stmt->toks[stmt->ntoks].tag = ArrayTag; stmt->toks[stmt->ntoks].array = mkscalarint(atoll(buf)); }else if(runestrchr(L"⍺⍵", line[offset])){ Rune *name = L"?"; name[0] = line[offset]; stmt->toks[stmt->ntoks].tag = NameTag; stmt->toks[stmt->ntoks].symbol = getsym(currentsymtab, name); offset++; }else if(isalpharune(line[offset]) || line[offset] == L'⎕'){ int quadname = L'⎕' == line[offset]; Rune buf[64]; Rune *p = buf; while(isalpharune(line[offset]) || (line[offset] == L'⎕' && p == buf)){ if(quadname) *p = toupperrune(line[offset]); else *p = line[offset]; p++; offset++; } *p = 0; stmt->toks[stmt->ntoks].tag = NameTag; stmt->toks[stmt->ntoks].symbol = getsym(currentsymtab, buf); }else{ syntax_error: print("Can't lex: %S\n", &line[offset]); free(stmt->toks); free(stmt); return 0; } stmt->ntoks++; } end: stmt->toks = realloc(stmt->toks, sizeof(Datum) * stmt->ntoks); return stmt; }