Support int types

This commit is contained in:
Yohann D'ANELLO 2020-05-17 00:06:02 +02:00
parent 9bae263414
commit 80abf67355
3 changed files with 73 additions and 14 deletions

View File

@ -18,7 +18,8 @@ void yyerror(char *s)
typedef struct var // a variable
{
char *name;
int value;
int type;
int value; // 0 = bool, 1 = int
struct var *next;
} var;
@ -30,14 +31,14 @@ typedef struct varlist // variable reference (used for print statement)
typedef struct expr // boolean expression
{
int type; // TRUE, FALSE, OR, AND, EQUIV, NOT, 0 (variable)
int type; // TRUE, FALSE, OR, AND, EQUIV, NOT, 0 (variable), PLUS, TIMES, INT
var *var;
struct expr *left, *right;
} expr;
typedef struct stmt // command
{
int type; // ASSIGN, ';', WHILE, PRINT
int type; // ASSIGN, ';', WHILE, IF, PRINT
var *var;
expr *expr;
struct stmt *left, *right;
@ -48,15 +49,17 @@ typedef struct stmt // command
/* All data pertaining to the programme are accessible from these two vars. */
var *program_vars;
var *program_ints;
stmt *program_stmts;
/****************************************************************************/
/* Functions for settting up data structures at parse time. */
var* make_ident (char *s)
var* make_ident (char *s, int type) // type = 0 for a boolean var, type = 1 for an int var
{
var *v = malloc(sizeof(var));
v->name = s;
v->type = type;
v->value = 0; // make variable false initially
v->next = NULL;
return v;
@ -65,8 +68,27 @@ var* make_ident (char *s)
var* find_ident (char *s)
{
var *v = program_vars;
while (v && strcmp(v->name,s)) v = v->next;
if (!v) { yyerror("undeclared variable"); exit(1); }
while (v && strcmp(v->name,s))
v = v->next;
if (!v) {
v = program_ints;
while (v && strcmp(v->name, s))
v = v->next;
}
if (!v) {
yyerror("undeclared variable");
exit(1);
}
return v;
}
var* make_int(int val)
{
var *v = malloc(sizeof(var));
v->name = NULL;
v->type = 1; // int
v->value = val;
v->next = NULL;
return v;
}
@ -115,15 +137,18 @@ stmt* make_stmt (int type, var *var, expr *expr,
varlist *l;
expr *e;
stmt *s;
int val;
}
%type <v> declist
%type <v> bool_declist
%type <v> int_declist
%type <l> varlist
%type <e> expr
%type <s> stmt assign
%token BOOL WHILE DO OD IF THEN ELSE FI ASSIGN PRINT OR AND XOR NOT TRUE FALSE
%token BOOL TYPE_INT WHILE DO OD IF THEN ELSE FI ASSIGN PRINT OR AND XOR NOT TRUE FALSE
%token <i> IDENT
%token <val> INT
%left ';'
@ -131,15 +156,25 @@ stmt* make_stmt (int type, var *var, expr *expr,
%left AND
%right NOT
%left EQUIV
%left PLUS
%left TIMES
%%
prog : bools stmt { program_stmts = $2; }
prog : bools ints stmt { program_stmts = $3; }
| bools stmt { program_stmts = $2; }
| ints stmt { program_stmts = $2; }
| stmt { program_stmts = $1; }
bools : BOOL declist ';' { program_vars = $2; }
bools : BOOL bool_declist ';' { program_vars = $2; }
declist : IDENT { $$ = make_ident($1); }
| declist ',' IDENT { ($$ = make_ident($3))->next = $1; }
bool_declist : IDENT { $$ = make_ident($1, 0); }
| bool_declist ',' IDENT { ($$ = make_ident($3, 0))->next = $1; }
ints : TYPE_INT int_declist ';' { program_ints = $2; }
int_declist : IDENT { $$ = make_ident($1, 1); }
| int_declist ',' IDENT { ($$ = make_ident($3, 1))->next = $1; }
stmt : assign
| stmt ';' stmt
@ -168,6 +203,10 @@ expr : IDENT { $$ = make_expr(0,find_ident($1),NULL,NULL); }
| TRUE { $$ = make_expr(TRUE,NULL,NULL,NULL); }
| FALSE { $$ = make_expr(FALSE,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); }
%%
@ -192,7 +231,13 @@ int eval (expr *e)
// Toutefois, on privilégie cette forme car faux = 0 et vrai = tout entier non nul.
}
case NOT: return !eval(e->left);
case 0: return e->var->value;
case PLUS:
return eval(e->left) + eval(e->right);
case TIMES:
return eval(e->left) * eval(e->right);
case INT:
case 0:
return e->var->value;
}
}
@ -203,7 +248,12 @@ void print_vars (varlist *l)
if (!l) return;
print_vars(l->next);
printf("%s = %c ", l->var->name, l->var->value? 'T' : 'F');
if (l->var->type == 0)
printf("%s = %c ", l->var->name, l->var->value ? 'T' : 'F');
else if (l->var->type == 1)
printf("%s = %d ", l->var->name, l->var->value);
else
fprintf(stderr, "The type of the var %s is unknown", l->var->name);
}
void execute (stmt *s)

View File

@ -5,6 +5,7 @@ DIG [0-9]
%%
"bool" { return BOOL; }
"int" { return TYPE_INT; }
"while" { return WHILE; }
"do" { return DO; }
"od" { return OD; }
@ -15,6 +16,7 @@ DIG [0-9]
"print" { return PRINT; }
"true" { return TRUE; }
"false" { return FALSE; }
{DIG}+ { yylval.val = atoi(yytext); return INT; }
":=" { return ASSIGN; }
"^" { return XOR; }
@ -22,6 +24,8 @@ DIG [0-9]
"&&" { return AND; }
"!" { return NOT; }
"<=>" { return EQUIV; }
"+" { return PLUS; }
"*" { return TIMES; }
[a-z_][a-z0-9_]* { yylval.i = strdup(yytext); return IDENT; }

5
syntaxique/test2.my Normal file
View File

@ -0,0 +1,5 @@
bool y;
int x;
x := 42 + 21;
y := true;
print x,y,x