From 5b238c771bbb8db281010e20d8ab89860a127f8b Mon Sep 17 00:00:00 2001 From: Mart Lubbers Date: Fri, 5 Feb 2021 13:27:01 +0100 Subject: [PATCH] use builtin operator associativity functionality --- ast.c | 34 +++++++++++++++++++++++++++++++--- ast.h | 14 ++++++++++++-- parse.y | 44 ++++++++++++++++++++++++++++++-------------- scan.l | 12 ++++++++++++ 4 files changed, 85 insertions(+), 19 deletions(-) diff --git a/ast.c b/ast.c index b220f5e..4d89925 100644 --- a/ast.c +++ b/ast.c @@ -40,11 +40,34 @@ struct ast *ast_int(int integer) return res; } +struct ast *ast_unop(enum unop op, struct ast *l) +{ + struct ast *res = ast_alloc(); + res->type = an_unop; + res->data.an_unop.op = op; + res->data.an_unop.l = l; + return res; +} static const char *binop_str[] = { + [binor] = "||", + [binand] = "&&", + [eq] = "==", + [neq] = "!=", + [leq] = "<=", + [le] = "<", + [geq] = ">=", + [ge] = ">", + [cons] = ":", [plus] = "+", - [minus] = "+", - [times] = "+", - [divide] = "+", + [minus] = "-", + [times] = "*", + [divide] = "/", + [modulo] = "%", + [power] = "^", +}; +static const char *unop_str[] = { + [inverse] = "!", + [negate] = "-", }; void ast_print(struct ast * ast, FILE *out) @@ -67,6 +90,11 @@ void ast_print(struct ast * ast, FILE *out) case an_int: fprintf(out, "%d", ast->data.an_int); break; + case an_unop: + fprintf(out, "(-"); + ast_print(ast->data.an_unop.l, out); + fprintf(out, ")"); + break; default: fprintf(stderr, "Unsupported AST node\n"); exit(1); diff --git a/ast.h b/ast.h index 758d034..872e25c 100644 --- a/ast.h +++ b/ast.h @@ -3,8 +3,13 @@ #include -enum binop {plus,minus,times,divide}; -enum ast_type {an_binop, an_cons, an_int}; +enum binop { + binor,binand, + eq,neq,leq,le,geq,ge, + cons,plus,minus,times,divide,modulo,power +}; +enum unop {negate,inverse}; +enum ast_type {an_binop, an_cons, an_int, an_unop}; struct ast { enum ast_type type; union { @@ -18,6 +23,10 @@ struct ast { struct ast *tail; } an_cons; int an_int; + struct { + enum unop op; + struct ast *l; + } an_unop; } data; }; @@ -25,6 +34,7 @@ struct ast { struct ast *ast_cons(struct ast *el, struct ast *tail); struct ast *ast_binop(struct ast *l, enum binop op, struct ast *tail); struct ast *ast_int(int integer); +struct ast *ast_unop(enum unop op, struct ast *l); void ast_print(struct ast * ast, FILE *out); void ast_free(struct ast *ast); diff --git a/parse.y b/parse.y index 60d4e0d..6600e5b 100644 --- a/parse.y +++ b/parse.y @@ -8,6 +8,7 @@ #include "y.tab.h" +int yylex_debug = 1; int yylex(void); void yyerror(struct ast **result, const char *str) @@ -22,9 +23,19 @@ int yywrap() %} -%token INTEGER PLUS MINUS TIMES DIVIDE BOPEN BCLOSE SEMICOLON +%define parse.error verbose +%token INTEGER PLUS MINUS TIMES DIVIDE BOPEN BCLOSE SEMICOLON POWER CONS MODULO BINOR BINAND INVERSE + %parse-param { struct ast **result } +%right BINOR +%right BINAND +%nonassoc EQ NEQ LEQ LE GEQ GE +%right CONS +%left PLUS MINUS +%left TIMES DIVIDE MODULO +%right POWER + %% start : exprs { *result = $1; } ; @@ -35,18 +46,23 @@ exprs ; expr - : expr PLUS fact { $$ = ast_binop($1, plus, $3); } - | expr MINUS fact { $$ = ast_binop($1, minus, $3); } - | fact - ; - -fact - : fact TIMES basic { $$ = ast_binop($1, times, $3); } - | fact DIVIDE basic { $$ = ast_binop($1, divide, $3); } - | basic - ; - -basic - : INTEGER + : expr BINOR expr { $$ = ast_binop($1, binor, $3); } + | expr BINAND expr { $$ = ast_binop($1, binand, $3); } + | expr EQ expr { $$ = ast_binop($1, eq, $3); } + | expr NEQ expr { $$ = ast_binop($1, neq, $3); } + | expr LEQ expr { $$ = ast_binop($1, leq, $3); } + | expr LE expr { $$ = ast_binop($1, le, $3); } + | expr GEQ expr { $$ = ast_binop($1, geq, $3); } + | expr GE expr { $$ = ast_binop($1, ge, $3); } + | expr CONS expr { $$ = ast_binop($1, cons, $3); } + | expr PLUS expr { $$ = ast_binop($1, plus, $3); } + | expr MINUS expr { $$ = ast_binop($1, minus, $3); } + | expr TIMES expr { $$ = ast_binop($1, times, $3); } + | expr DIVIDE expr { $$ = ast_binop($1, divide, $3); } + | expr MODULO expr { $$ = ast_binop($1, modulo, $3); } + | expr POWER expr { $$ = ast_binop($1, power, $3); } + | MINUS expr { $$ = ast_unop(negate, $2); } + | INVERSE expr { $$ = ast_unop(inverse, $2); } | BOPEN expr BCLOSE { $$ = $2; } + | INTEGER ; diff --git a/scan.l b/scan.l index bb34a5b..f92af61 100644 --- a/scan.l +++ b/scan.l @@ -13,10 +13,22 @@ extern YYSTYPE yylval; %% [0-9]+ { yylval = ast_int(atoi(yytext)); return INTEGER; } +! return INVERSE; +\|\| return BINOR; +&& return BINAND; +== return EQ; +!= return NEQ; +\<= return GEQ; +\< return GE; +>= return LEQ; +> return LE; +: return CONS; \+ return PLUS; - return MINUS; \* return TIMES; \/ return DIVIDE; +% return MODULO; +\^ return POWER; \( return BOPEN; \) return BCLOSE; \; return SEMICOLON; -- 2.20.1