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)
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);
#include <stdio.h>
-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 {
struct ast *tail;
} an_cons;
int an_int;
+ struct {
+ enum unop op;
+ struct ast *l;
+ } an_unop;
} data;
};
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);
#include "y.tab.h"
+int yylex_debug = 1;
int yylex(void);
void yyerror(struct ast **result, const char *str)
%}
-%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; } ;
;
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
;