diff --git a/syntaxique/lang.y b/syntaxique/lang.y index a3eb550..b7ff205 100644 --- a/syntaxique/lang.y +++ b/syntaxique/lang.y @@ -18,7 +18,7 @@ void yyerror(char *s) typedef struct var // a variable { char *name; - int type; + int class; int value; // 0 = bool, 1 = int struct var *next; } var; @@ -32,6 +32,7 @@ typedef struct varlist // variable reference (used for print statement) typedef struct expr // boolean expression { int type; // TRUE, FALSE, OR, AND, EQUIV, NOT, 0 (variable), PLUS, TIMES, INT, EQUALS, LT + int class; // 0 = bool, 1 = int, 2 = both var *var; struct expr *left, *right; } expr; @@ -55,11 +56,11 @@ stmt *program_stmts; /****************************************************************************/ /* Functions for settting up data structures at parse time. */ -var* make_ident (char *s, int type) // type = 0 for a boolean var, type = 1 for an int var +var* make_ident (char *s, int class) // type = 0 for a boolean var, type = 1 for an int var { var *v = malloc(sizeof(var)); v->name = s; - v->type = type; + v->class = class; v->value = 0; // make variable false initially v->next = NULL; return v; @@ -87,7 +88,7 @@ var* make_int(int val) { var *v = malloc(sizeof(var)); v->name = NULL; - v->type = 1; // int + v->class = 1; // int v->value = val; v->next = NULL; return v; @@ -102,10 +103,11 @@ varlist* make_varlist (char *s) return l; } -expr* make_expr (int type, var *var, expr *left, expr *right) +expr* make_expr (int type, int class, var *var, expr *left, expr *right) { expr *e = malloc(sizeof(expr)); e->type = type; + e->class = class; e->var = var; e->left = left; e->right = right; @@ -197,20 +199,20 @@ assign : IDENT ASSIGN expr varlist : IDENT { $$ = make_varlist($1); } | varlist ',' IDENT { ($$ = make_varlist($3))->next = $1; } -expr : IDENT { $$ = make_expr(0,find_ident($1),NULL,NULL); } - | expr XOR expr { $$ = make_expr(XOR,NULL,$1,$3); } - | expr OR expr { $$ = make_expr(OR,NULL,$1,$3); } - | expr AND expr { $$ = make_expr(AND,NULL,$1,$3); } - | expr EQUIV expr { $$ = make_expr(EQUIV,NULL,$1,$3); } - | NOT expr { $$ = make_expr(NOT,NULL,$2,NULL); } - | TRUE { $$ = make_expr(TRUE,NULL,NULL,NULL); } - | FALSE { $$ = make_expr(FALSE,NULL,NULL,NULL); } +expr : IDENT { $$ = make_expr(0, 2, find_ident($1), NULL, NULL); } + | expr XOR expr { $$ = make_expr(XOR, 0, NULL, $1, $3); } + | expr OR expr { $$ = make_expr(OR, 0, NULL, $1, $3); } + | expr AND expr { $$ = make_expr(AND, 0, NULL, $1, $3); } + | expr EQUIV expr { $$ = make_expr(EQUIV, 0, NULL, $1, $3); } + | NOT expr { $$ = make_expr(NOT, 0, NULL, $2, NULL); } + | TRUE { $$ = make_expr(TRUE, 0, NULL, NULL, NULL); } + | FALSE { $$ = make_expr(FALSE, 0, NULL, NULL, NULL); } | '(' expr ')' { $$ = $2; } - | INT { $$ = make_expr(INT, make_int($1), NULL, NULL); } - | expr TIMES expr { $$ = make_expr(TIMES, NULL, $1, $3); } - | expr PLUS expr { $$ = make_expr(PLUS, NULL, $1, $3); } - | expr EQUALS expr { $$ = make_expr(EQUALS, NULL, $1, $3); } - | expr LT expr { $$ = make_expr(LT, NULL, $1, $3); } + | INT { $$ = make_expr(INT, 1, make_int($1), NULL, NULL); } + | expr TIMES expr { $$ = make_expr(TIMES, 1, NULL, $1, $3); } + | expr PLUS expr { $$ = make_expr(PLUS, 1, NULL, $1, $3); } + | expr LT expr { $$ = make_expr(LT, 0, NULL, $1, $3); } + | expr EQUALS expr { $$ = make_expr(EQUALS, 0, NULL, $1, $3); } %% @@ -226,25 +228,74 @@ int eval (expr *e) { case TRUE: return 1; case FALSE: return 0; - case XOR: return eval(e->left) ^ eval(e->right); - case OR: return eval(e->left) || eval(e->right); - case AND: return eval(e->left) && eval(e->right); + case XOR: { + if (e->left->class != 0 || e->right->class != 0) { + yyerror("An expression has wrong types"); + exit(-1); + } + return eval(e->left) ^ eval(e->right); + } + case OR: { + if (e->left->class != 0 || e->right != NULL && e->right->class != 0) { + yyerror("An expression has wrong types"); + exit(-1); + } + return eval(e->left) || eval(e->right); + } + case AND: { + if (e->left->class != 0 || e->right->class != 0) { + yyerror("An expression has wrong types"); + exit(-1); + } + return eval(e->left) && eval(e->right); + } case EQUIV: { + if (e->left->class != 0 || e->right->class != 0) { + yyerror("An expression has wrong types"); + exit(-1); + } int right = eval(e->right); int left = eval(e->left); return (right && left) || (!right && !left); // Équivalent avec left == right avec la définition. - // Toutefois, on privilégie cette forme car faux = 0 et vrai = tout entier non nul. + // Toutefois, on privilégie cette forme car faux = 0 et vrai = tout entier non nul } - case NOT: return !eval(e->left); - case PLUS: + case NOT: { + if (e->left->class != 0) { + yyerror("An expression has wrong types"); + exit(-1); + } + return !eval(e->left); + } + case PLUS: { + if (e->left->class != 1 || e->right->class != 1) { + yyerror("An expression has wrong types"); + exit(-1); + } return eval(e->left) + eval(e->right); - case TIMES: + } + case TIMES: { + if (e->left->class != 1 || e->right->class != 1) { + yyerror("An expression has wrong types"); + exit(-1); + } return eval(e->left) * eval(e->right); - case EQUALS: + } + case EQUALS: { + if (e->left->class != 1 || e->right->class != 1) { + yyerror("An expression has wrong types"); + exit(-1); + } + printf("%d, %d\n", eval(e->left), eval(e->right)); return eval(e->left) == eval(e->right) ? 1 : 0; - case LT: + } + case LT: { + if (e->left->class != 1 || e->right->class != 1) { + yyerror("An expression has wrong types"); + exit(-1); + } return eval(e->left) < eval(e->right) ? 1 : 0; + } case INT: case 0: return e->var->value; @@ -258,9 +309,9 @@ void print_vars (varlist *l) if (!l) return; print_vars(l->next); - if (l->var->type == 0) + if (l->var->class == 0) printf("%s = %c ", l->var->name, l->var->value ? 'T' : 'F'); - else if (l->var->type == 1) + else if (l->var->class == 1) printf("%s = %d ", l->var->name, l->var->value); else fprintf(stderr, "The type of the var %s is unknown", l->var->name); @@ -271,6 +322,10 @@ void execute (stmt *s) switch(s->type) { case ASSIGN: + if (s->var->class != s->expr->class) { + yyerror("An assignment has the wrong type"); + exit(-1); + } s->var->value = eval(s->expr); break; case ';': diff --git a/syntaxique/test2.my b/syntaxique/test2.my index 6a2460c..d22beb4 100644 --- a/syntaxique/test2.my +++ b/syntaxique/test2.my @@ -1,5 +1,5 @@ bool y; int x; -x := 42 + 21; -y := x == (7 * (5 + 4)); +x := 6 * (4 + 3); +y := (0 < 1) || 19 + 23 == x; print x,y,x