Prevent wrong types
This commit is contained in:
parent
9fefbe57df
commit
b05575a595
|
@ -18,7 +18,7 @@ void yyerror(char *s)
|
||||||
typedef struct var // a variable
|
typedef struct var // a variable
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
int type;
|
int class;
|
||||||
int value; // 0 = bool, 1 = int
|
int value; // 0 = bool, 1 = int
|
||||||
struct var *next;
|
struct var *next;
|
||||||
} var;
|
} var;
|
||||||
|
@ -32,6 +32,7 @@ typedef struct varlist // variable reference (used for print statement)
|
||||||
typedef struct expr // boolean expression
|
typedef struct expr // boolean expression
|
||||||
{
|
{
|
||||||
int type; // TRUE, FALSE, OR, AND, EQUIV, NOT, 0 (variable), PLUS, TIMES, INT, EQUALS, LT
|
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;
|
var *var;
|
||||||
struct expr *left, *right;
|
struct expr *left, *right;
|
||||||
} expr;
|
} expr;
|
||||||
|
@ -55,11 +56,11 @@ stmt *program_stmts;
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/* Functions for settting up data structures at parse time. */
|
/* 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));
|
var *v = malloc(sizeof(var));
|
||||||
v->name = s;
|
v->name = s;
|
||||||
v->type = type;
|
v->class = class;
|
||||||
v->value = 0; // make variable false initially
|
v->value = 0; // make variable false initially
|
||||||
v->next = NULL;
|
v->next = NULL;
|
||||||
return v;
|
return v;
|
||||||
|
@ -87,7 +88,7 @@ var* make_int(int val)
|
||||||
{
|
{
|
||||||
var *v = malloc(sizeof(var));
|
var *v = malloc(sizeof(var));
|
||||||
v->name = NULL;
|
v->name = NULL;
|
||||||
v->type = 1; // int
|
v->class = 1; // int
|
||||||
v->value = val;
|
v->value = val;
|
||||||
v->next = NULL;
|
v->next = NULL;
|
||||||
return v;
|
return v;
|
||||||
|
@ -102,10 +103,11 @@ varlist* make_varlist (char *s)
|
||||||
return l;
|
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));
|
expr *e = malloc(sizeof(expr));
|
||||||
e->type = type;
|
e->type = type;
|
||||||
|
e->class = class;
|
||||||
e->var = var;
|
e->var = var;
|
||||||
e->left = left;
|
e->left = left;
|
||||||
e->right = right;
|
e->right = right;
|
||||||
|
@ -197,20 +199,20 @@ assign : IDENT ASSIGN expr
|
||||||
varlist : IDENT { $$ = make_varlist($1); }
|
varlist : IDENT { $$ = make_varlist($1); }
|
||||||
| varlist ',' IDENT { ($$ = make_varlist($3))->next = $1; }
|
| varlist ',' IDENT { ($$ = make_varlist($3))->next = $1; }
|
||||||
|
|
||||||
expr : IDENT { $$ = make_expr(0,find_ident($1),NULL,NULL); }
|
expr : IDENT { $$ = make_expr(0, 2, find_ident($1), NULL, NULL); }
|
||||||
| expr XOR expr { $$ = make_expr(XOR,NULL,$1,$3); }
|
| expr XOR expr { $$ = make_expr(XOR, 0, NULL, $1, $3); }
|
||||||
| expr OR expr { $$ = make_expr(OR,NULL,$1,$3); }
|
| expr OR expr { $$ = make_expr(OR, 0, NULL, $1, $3); }
|
||||||
| expr AND expr { $$ = make_expr(AND,NULL,$1,$3); }
|
| expr AND expr { $$ = make_expr(AND, 0, NULL, $1, $3); }
|
||||||
| expr EQUIV expr { $$ = make_expr(EQUIV,NULL,$1,$3); }
|
| expr EQUIV expr { $$ = make_expr(EQUIV, 0, NULL, $1, $3); }
|
||||||
| NOT expr { $$ = make_expr(NOT,NULL,$2,NULL); }
|
| NOT expr { $$ = make_expr(NOT, 0, NULL, $2, NULL); }
|
||||||
| TRUE { $$ = make_expr(TRUE,NULL,NULL,NULL); }
|
| TRUE { $$ = make_expr(TRUE, 0, NULL, NULL, NULL); }
|
||||||
| FALSE { $$ = make_expr(FALSE,NULL,NULL,NULL); }
|
| FALSE { $$ = make_expr(FALSE, 0, NULL, NULL, NULL); }
|
||||||
| '(' expr ')' { $$ = $2; }
|
| '(' expr ')' { $$ = $2; }
|
||||||
| INT { $$ = make_expr(INT, make_int($1), NULL, NULL); }
|
| INT { $$ = make_expr(INT, 1, make_int($1), NULL, NULL); }
|
||||||
| expr TIMES expr { $$ = make_expr(TIMES, NULL, $1, $3); }
|
| expr TIMES expr { $$ = make_expr(TIMES, 1, NULL, $1, $3); }
|
||||||
| expr PLUS expr { $$ = make_expr(PLUS, NULL, $1, $3); }
|
| expr PLUS expr { $$ = make_expr(PLUS, 1, NULL, $1, $3); }
|
||||||
| expr EQUALS expr { $$ = make_expr(EQUALS, NULL, $1, $3); }
|
| expr LT expr { $$ = make_expr(LT, 0, NULL, $1, $3); }
|
||||||
| expr LT expr { $$ = make_expr(LT, 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 TRUE: return 1;
|
||||||
case FALSE: return 0;
|
case FALSE: return 0;
|
||||||
case XOR: return eval(e->left) ^ eval(e->right);
|
case XOR: {
|
||||||
case OR: return eval(e->left) || eval(e->right);
|
if (e->left->class != 0 || e->right->class != 0) {
|
||||||
case AND: return eval(e->left) && eval(e->right);
|
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: {
|
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 right = eval(e->right);
|
||||||
int left = eval(e->left);
|
int left = eval(e->left);
|
||||||
return (right && left) || (!right && !left); // Équivalent avec left == right avec la définition.
|
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 NOT: {
|
||||||
case PLUS:
|
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);
|
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);
|
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));
|
printf("%d, %d\n", eval(e->left), eval(e->right));
|
||||||
return eval(e->left) == eval(e->right) ? 1 : 0;
|
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;
|
return eval(e->left) < eval(e->right) ? 1 : 0;
|
||||||
|
}
|
||||||
case INT:
|
case INT:
|
||||||
case 0:
|
case 0:
|
||||||
return e->var->value;
|
return e->var->value;
|
||||||
|
@ -258,9 +309,9 @@ void print_vars (varlist *l)
|
||||||
|
|
||||||
if (!l) return;
|
if (!l) return;
|
||||||
print_vars(l->next);
|
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');
|
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);
|
printf("%s = %d ", l->var->name, l->var->value);
|
||||||
else
|
else
|
||||||
fprintf(stderr, "The type of the var %s is unknown", l->var->name);
|
fprintf(stderr, "The type of the var %s is unknown", l->var->name);
|
||||||
|
@ -271,6 +322,10 @@ void execute (stmt *s)
|
||||||
switch(s->type)
|
switch(s->type)
|
||||||
{
|
{
|
||||||
case ASSIGN:
|
case ASSIGN:
|
||||||
|
if (s->var->class != s->expr->class) {
|
||||||
|
yyerror("An assignment has the wrong type");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
s->var->value = eval(s->expr);
|
s->var->value = eval(s->expr);
|
||||||
break;
|
break;
|
||||||
case ';':
|
case ';':
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
bool y;
|
bool y;
|
||||||
int x;
|
int x;
|
||||||
x := 42 + 21;
|
x := 6 * (4 + 3);
|
||||||
y := x == (7 * (5 + 4));
|
y := (0 < 1) || 19 + 23 == x;
|
||||||
print x,y,x
|
print x,y,x
|
||||||
|
|
Loading…
Reference in New Issue