summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
authorPeter Mikkelsen <peter@pmikkelsen.com>2021-07-16 00:42:49 +0000
committerPeter Mikkelsen <peter@pmikkelsen.com>2021-07-16 00:42:49 +0000
commit1c8789198373a52da9e80dc9b2b1ee2b67af61c4 (patch)
tree980040a8d1828a85428b175eef9f6a4106248309 /parser.c
parent2a77288e28f2725b5621c239d2393d49f61993e8 (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.c197
1 files changed, 70 insertions, 127 deletions
diff --git a/parser.c b/parser.c
index acca0cb..0e7c967 100644
--- a/parser.c
+++ b/parser.c
@@ -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