codice:
%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "symtab.h"
#include "ast.h"
static int currType = 0;
static int uname = 0;
char *strUname[21];
int yylex(void);
void yyerror(nodeType **pTree, Scope *pScope, Scope **pScope2, char *s);
char *makeUniqueName(char *strName);
%}
%union {
int iValue; /* interi e booleani */
double dblValue; /* valori in virgola mobile */
char *strValue; /* stringhe */
nodeType *nPtr; /* puntatore al nodo dell'AST */
};
%token <strValue> ID
%token <strValue> STRING_LITERAL
%token <iValue> INTEGER_LITERAL
%token <dblValue> REAL_LITERAL
%token <iValue> BOOLEAN_LITERAL
%token WHILE IF PRINT
%token INT REAL BOOL STRINGA
%nonassoc IFX
%nonassoc ELSE
%left GE LE EQ NE '>' '<'
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%type <nPtr> program stmt expr stmt_list
%parse-param {nodeType **pTree}
%parse-param {Scope *pScope}
%parse-param {Scope **pScope2}
%%
program:
decl_list stmt_list { *pTree = $2; }
;
decl_list:
decl
| decl_list decl
;
decl: /* Vuoto */
| type { sprintf(strUname, "%d", uname++); } var_list ';'
;
type:
INT { currType = T_INTEGER; }
| REAL { currType = T_REAL; }
| BOOL { currType = T_BOOLEAN; }
| STRINGA { currType = T_STRING; }
;
var_list:
ID
{
Valore val;
char *uniqueName;
if ( currType == T_INTEGER )
val.iVal = 0;
else if ( currType == T_REAL )
val.dblVal = 0.0;
else if ( currType == T_BOOLEAN )
val.bVal = 0;
else
{
val.strVal = (char*)malloc(sizeof(char)*strlen($1)+1);
strcpy(val.strVal, yylval.strValue);
}
scopeInsert(pScope, $1, currType, T_VAR, val, 0);
uniqueName = makeUniqueName($1);
scopeInsert(*pScope2, uniqueName, currType, T_VAR, val, 0);
}
| var_list ',' ID
{
Valore val;
char *uniqueName;
if ( currType == T_INTEGER )
val.iVal = 0;
else if ( currType == T_REAL )
val.dblVal = 0.0;
else if ( currType == T_BOOLEAN )
val.bVal = 0;
else
{
val.strVal = (char*)malloc(sizeof(char)*strlen($3)+1);
strcpy(val.strVal, yylval.strValue);
}
scopeInsert(pScope, $3, currType, T_VAR, val, 0);
uniqueName = makeUniqueName($3);
scopeInsert(*pScope2, uniqueName, currType, T_VAR, val, 0);
}
;
stmt_list:
stmt { $$ = $1; }
| stmt_list stmt { $$ = opr(';', 2, $1, $2); }
;
stmt:
';' { $$ = opr(';', 2, NULL, NULL); }
| expr ';' { $$ = $1; }
| PRINT expr ';' { $$ = opr(PRINT, 1, $2); }
| ID '=' expr ';' {
HashTable Dati;
nodeType *nodePtr;
char *uniqueName;
if ( !scopeFind(pScope, $1, &Dati) )
{
yyerror(pTree, pScope, pScope2, "identificatore non dichiarato\n");
Dati.Tipo1 = T_BOOLEAN;
Dati.Tipo2 = T_VAR;
Dati.Value.bVal = 0;
Dati.bInizializzato = 0;
uniqueName = makeUniqueName($1);
return 1;
}
uniqueName = makeUniqueName($1);
nodePtr = id($1, uniqueName, Dati.Tipo1, Dati.Tipo2, Dati.Value, Dati.bInizializzato);
$$ = opr('=', 2, nodePtr, $3);
}
| WHILE '(' expr ')' stmt { $$ = opr(WHILE, 2, $3, $5); }
| IF '(' expr ')' stmt %prec IFX { $$ = opr(IF, 2, $3, $5); }
| IF '(' expr ')' stmt ELSE stmt { $$ = opr(IF, 3, $3, $5, $7); }
| '{' { scopePush(pScope); } decl_list stmt_list '}' { $$ = $4; scopePop(pScope); }
;
expr:
INTEGER_LITERAL {
Valore val;
val.iVal = $1;
$$ = con(T_INTEGER, val);
}
| REAL_LITERAL {
Valore val;
val.dblVal = $1;
$$ = con(T_REAL, val);
}
| BOOLEAN_LITERAL {
Valore val;
val.bVal = $1;
$$ = con(T_BOOLEAN, val);
}
| STRING_LITERAL {
Valore val;
int len = strlen($1);
val.strVal = (char*)malloc(sizeof(char)*len+1);
strcpy(val.strVal, $1);
$$ = con(T_STRING, val);
}
| ID {
HashTable Dati;
char *uniqueName;
if ( !scopeFind(pScope, $1, &Dati) )
{
yyerror(pTree, pScope, pScope2, "identificatore non dichiarato\n");
Dati.Tipo1 = T_BOOLEAN;
Dati.Tipo2 = T_VAR;
Dati.Value.bVal = 0;
Dati.bInizializzato = 0;
uniqueName = makeUniqueName($1);
return 1;
}
uniqueName = makeUniqueName($1);
$$ = id($1, uniqueName, Dati.Tipo1, Dati.Tipo2, Dati.Value, Dati.bInizializzato);
}
| '-' expr %prec UMINUS { $$ = opr(UMINUS, 1, $2); }
| expr '+' expr { $$ = opr('+', 2, $1, $3); }
| expr '-' expr { $$ = opr('-', 2, $1, $3); }
| expr '*' expr { $$ = opr('*', 2, $1, $3); }
| expr '/' expr { $$ = opr('/', 2, $1, $3); }
| expr '<' expr { $$ = opr('<', 2, $1, $3); }
| expr '>' expr { $$ = opr('>', 2, $1, $3); }
| expr GE expr { $$ = opr(GE, 2, $1, $3); }
| expr LE expr { $$ = opr(LE, 2, $1, $3); }
| expr NE expr { $$ = opr(NE, 2, $1, $3); }
| expr EQ expr { $$ = opr(EQ, 2, $1, $3); }
| '(' expr ')' { $$ = $2; }
;
%%
void yyerror(nodeType **pTree, Scope *pScope, Scope **pScope2, char *s)
{
fprintf(stdout, "%s\n", s);
}
char *makeUniqueName(char *strName)
{
char *uniqueName;
int len1, len2;
len1 = strlen(strName);
len2 = strlen(strUname);
uniqueName = (char*)malloc(len1+len2+1);
strcpy(uniqueName, strName);
return strcat(uniqueName, strUname);
}