diff options
author | Peter Mikkelsen <peter@pmikkelsen.com> | 2021-07-16 00:42:49 +0000 |
---|---|---|
committer | Peter Mikkelsen <peter@pmikkelsen.com> | 2021-07-16 00:42:49 +0000 |
commit | 1c8789198373a52da9e80dc9b2b1ee2b67af61c4 (patch) | |
tree | 980040a8d1828a85428b175eef9f6a4106248309 /parser.c | |
parent | 2a77288e28f2725b5621c239d2393d49f61993e8 (diff) |
Make operators local to each module, and implement some more correct prettyprint code, used by write_term
Diffstat (limited to 'parser.c')
-rw-r--r-- | parser.c | 197 |
1 files changed, 70 insertions, 127 deletions
@@ -5,10 +5,7 @@ #include "dat.h" #include "fns.h" -#define PrecedenceLevels 1200 - typedef struct Token Token; -typedef struct Operator Operator; typedef struct OpInfo OpInfo; struct Token { @@ -18,14 +15,6 @@ struct Token vlong ival; }; -struct Operator -{ - int type; - int level; - Rune *spelling; - Operator *next; -}; - struct OpInfo { int level; @@ -33,16 +22,6 @@ struct OpInfo }; enum { - Xf = 1<<0, /* 1 */ - Yf = 1<<1, /* 2 */ - Xfx = 1<<2, /* 4 */ - Xfy = 1<<3, /* 8 */ - Yfx = 1<<4, /* 16 */ - Fy = 1<<5, /* 32 */ - Fx = 1<<6, /* 64 */ -}; - -enum { AtomTok = 1<<0, /* 1 */ FunctorTok = 1<<1, /* 2 */ VarTok = 1<<2, /* 4 */ @@ -62,11 +41,8 @@ enum { static Biobuf *parsein; static Token lookahead; -static Operator *operators[PrecedenceLevels]; +static Module *currentmod; -void initoperators(void); -void addoperator(int, int, Rune *); -Operator *getoperator(Rune *); void nexttoken(void); Term *fullterm(int, Rune *, Term *); Term *term(void); @@ -77,6 +53,8 @@ Term *parseoperators(Term *); void match(int); void syntaxerror_parser(char *); Term *prologtext(int); +void handlemoduledirective(Term *); +void handleopdirective(Term *); Term * parse(int fd, Biobuf *bio, int querymode) @@ -91,8 +69,8 @@ parse(int fd, Biobuf *bio, int querymode) }else parsein = bio; - initoperators(); nexttoken(); + currentmod = usermodule; Term *result = prologtext(querymode); if(querymode){ @@ -120,14 +98,18 @@ prologtext(int querymode) if(querymode) return t; - + if(t->tag == CompoundTerm && runestrcmp(t->text, L":-") == 0 && t->arity == 1){ Term *body = t->children; - print("Got directive: %S\n", prettyprint(body, 0, 0, 0)); - if(runestrcmp(body->text, L"module") == 0 && body->arity == 2) + if(runestrcmp(body->text, L"module") == 0 && body->arity == 2){ + handlemoduledirective(body->children); t->next = prologtext(querymode); - else - t = prologtext(querymode); + return t; + } + else if(runestrcmp(body->text, L"op") == 0 && body->arity == 3) + handleopdirective(body->children); + + t = prologtext(querymode); }else if(t->tag == CompoundTerm && runestrcmp(t->text, L":-") == 0 && t->arity == 2){ t->next = prologtext(querymode); }else if(t->tag == AtomTerm || t->tag == CompoundTerm){ @@ -268,7 +250,7 @@ parseoperators(Term *list) OpInfo *infos = gmalloc(sizeof(OpInfo) * length); for(i = 0, t = list; i < length; i++){ - Operator *op = getoperator(t->text); + Operator *op = getoperator(t->text, currentmod); if(op && t->tag == AtomTerm){ infos[i].type = op->type; infos[i].level = op->level; @@ -299,7 +281,7 @@ parseoperators(Term *list) if(index == -1){ print("Can't parse, list of length %d contains no operators: ", length); for(i = 0; i < length; i++) - print("%S(%d) ", prettyprint(terms[i], 0, 0, 0), infos[i].level); + print("%S(%d) ", prettyprint(terms[i], 0, 0, 0, currentmod), infos[i].level); print("\n"); syntaxerror_parser("parseoperators"); } @@ -340,7 +322,7 @@ parseoperators(Term *list) terms[i] = terms[i+1]; } }else{ - print("Parse error when parsing operator %S (prefix=%d, postfix=%d, infix=%d level=%d)\n", prettyprint(terms[index], 0, 0, 0), prefixlevel, postfixlevel, infixlevel, infos[index].level); + print("Parse error when parsing operator %S (prefix=%d, postfix=%d, infix=%d level=%d)\n", prettyprint(terms[index], 0, 0, 0, currentmod), prefixlevel, postfixlevel, infixlevel, infos[index].level); syntaxerror_parser("parseoperators"); } } @@ -350,98 +332,6 @@ parseoperators(Term *list) } void -initoperators(void) -{ - Operator *op; - int i; - for(i = 0; i < PrecedenceLevels; i++){ - while(operators[i]){ - op = operators[i]; - operators[i] = op->next; - free(op); - } - } - - addoperator(1200, Xfx, L":-"); - addoperator(1200, Xfx, L"-->"); - addoperator(1200, Fx, L":-"); - addoperator(1200, Fx, L"?-"); - addoperator(1100, Xfy, L";"); - addoperator(1050, Xfy, L"->"); - addoperator(1000, Xfy, L","); - addoperator(900, Fy, L"\\+"); - addoperator(700, Xfx, L"="); - addoperator(700, Xfx, L"\\="); - addoperator(700, Xfx, L"=="); - addoperator(700, Xfx, L"\\=="); - addoperator(700, Xfx, L"@<"); - addoperator(700, Xfx, L"@=<"); - addoperator(700, Xfx, L"@>"); - addoperator(700, Xfx, L"@>="); - addoperator(700, Xfx, L"is"); - addoperator(700, Xfx, L"=:="); - addoperator(700, Xfx, L"=\\="); - addoperator(700, Xfx, L"<"); - addoperator(700, Xfx, L"=<"); - addoperator(700, Xfx, L">"); - addoperator(700, Xfx, L">="); - addoperator(700, Xfx, L"=.."); - addoperator(600, Xfy, L":"); - addoperator(500, Yfx, L"+"); - addoperator(500, Yfx, L"-"); - addoperator(500, Yfx, L"/\\"); - addoperator(500, Yfx, L"\\/"); - addoperator(400, Yfx, L"*"); - addoperator(400, Yfx, L"/"); - addoperator(400, Yfx, L"//"); - addoperator(400, Yfx, L"rem"); - addoperator(400, Yfx, L"mod"); - addoperator(400, Yfx, L"<<"); - addoperator(400, Yfx, L">>"); - addoperator(200, Xfx, L"**"); - addoperator(200, Xfy, L"^"); - addoperator(200, Fy, L"-"); - addoperator(200, Fy, L"\\"); -} - -void -addoperator(int level, int type, Rune *spelling) -{ - /* the operator table is never garbage collected, so just use normal malloc */ - Operator *op = malloc(sizeof(Operator)); - op->type = type; - op->level = level; - op->spelling = spelling; - op->next = operators[level-1]; - operators[level-1] = op; -} - -Operator * -getoperator(Rune *spelling) -{ - Operator *op = nil; - int level; - - if(spelling == nil) - return nil; - - for(level = 0; level < PrecedenceLevels && op == nil; level++){ - Operator *tmp; - for(tmp = operators[level]; tmp != nil; tmp = tmp->next){ - if(runestrcmp(tmp->spelling, spelling) == 0){ - if(op == nil){ - op = gmalloc(sizeof(Operator)); - memcpy(op, tmp, sizeof(Operator)); - }else - op->type |= tmp->type; - } - } - } - - return op; -} - -void nexttoken(void) { Rune buf[1024]; @@ -596,7 +486,7 @@ Integer: } /* Graphic atom */ - Rune *graphics = L"#$&*+-./:<=>?@^~\\"; + Rune *graphics = L"#$&*+-./:<=>?@^~\\"; /* keep in sync with prettyprint*/ if(runestrchr(graphics, peek)){ while(runestrchr(graphics, peek)){ buf[i++] = peek; @@ -674,3 +564,56 @@ syntaxerror_parser(char *where) print("Syntax error: Unexpected %d (%S) token in %s\n", lookahead.tag, lookahead.text, where); exits("syntax error"); } + +void +handlemoduledirective(Term *args) +{ + Term *modulename = args; + Term *publiclist = modulename->next; + USED(publiclist); + + if(modulename->tag != AtomTerm){ + print("Module name should be an atom in: %S\n", prettyprint(modulename, 0, 0, 0, currentmod)); + return; + } + currentmod = addemptymodule(modulename->text); +} + +void +handleopdirective(Term *args) +{ + Term *levelt = args; + Term *typet = levelt->next; + Term *opt = typet->next; + if(levelt->tag == IntegerTerm + && levelt->ival >= 0 + && levelt->ival <= PrecedenceLevels + && typet->tag == AtomTerm + && opt->tag == AtomTerm){ + int level = levelt->ival; + Rune *spelling = opt->text; + int type = 0; + if(runestrcmp(typet->text, L"xf") == 0) + type = Xf; + else if(runestrcmp(typet->text, L"yf") == 0) + type = Yf; + else if(runestrcmp(typet->text, L"xfx") == 0) + type = Xfx; + else if(runestrcmp(typet->text, L"xfy") == 0) + type = Xfy; + else if(runestrcmp(typet->text, L"yfx") == 0) + type = Yfx; + else if(runestrcmp(typet->text, L"fy") == 0) + type = Fy; + else if(runestrcmp(typet->text, L"fx") == 0) + type = Fx; + if(type != 0){ + addoperator(level, type, spelling, currentmod); + return; + } + } + print("Malformed op directive with level=%S, type=%S, op=%S\n", + prettyprint(levelt, 0, 0, 0, currentmod), + prettyprint(typet, 0, 0, 0, currentmod), + prettyprint(opt, 0, 0, 0, currentmod)); +}
\ No newline at end of file |