Progetto di Benedetto Scala e Leopoldo Todisco per il corso di Compilatori.
Per eseguire il progetto occorre usare Java 17 e maven 3.8
In questa sezione vi sono tutti i token e i corrispettivi lessemi.
Le regole di inferenza si possono trovare nel file pdf inviato con il link della repository.
Token | Lessema |
---|---|
VAR | var |
ID | [A-Za-z_][A-Za-z0-9_]* |
INTEGER | integer |
REAL | real |
STRING | string |
LPAR | ( |
RPAR | ) |
FUNC | func |
ENDFUNC | endfunc |
TYPERETURN | -> |
READ | <-- |
WRITERETURN | -->! |
WRITE | --> |
DOLLARSIGN | $ |
OUT | out |
PROC | proc |
ENDPROC | endproc |
IF | if |
THEN | then |
ELSE | else |
ELSEIF | elseif |
DO | do |
ENDWHILE | endwhile |
ENDIF | endif |
PLUS | + |
MINUS | - |
DIV | / |
TIMES | * |
NEQ | <> |
EQ | = |
ASSIGN | ^= |
LT | < |
GT | > |
LE | <= |
GE | >= |
REF | @ |
NOT | ! |
OR | || |
AND | && |
SEMI | ; |
COLON | : |
COMMA | , |
ENDVAR | \ |
TRUE | true |
FALSE | false |
precedence left OR;
precedence left AND;
precedence right NOT;
precedence nonassoc EQ, NE, LT, LE, GT, GE;
precedence left PLUS, MINUS;
precedence left TIMES, DIV;
Program ::= IterWithoutProcedure Procedure Iter;
IterWithoutProcedure ::= VarDecl IterWithoutProcedure
| Function IterWithoutProcedure
| /* empty */ ;
Iter ::= VarDecl Iter
| Function Iter
| Procedure Iter
| /* empty */ ;
VarDecl ::= VAR Decls;
Decls ::= Ids COLON Type SEMI Decls
| Ids:ids ASSIGN Consts:consts SEMI Decls:decls
| Ids:ids COLON Type:tipo SEMI ENDVAR
| Ids:ids ASSIGN Consts:consts SEMI ENDVAR
Ids ::= ID:id COMMA Ids:ids
| ID:id;
Consts ::= Const:costante COMMA Consts:listaCostanti
| Const:costante;
Const ::= REAL_CONST:lessema
| INTEGER_CONST
| STRING_CONST
| TRUE
| FALSE ;
Type ::= REAL
| INTEGER
| STRING
| BOOLEAN ;
Function ::= FUNCTION ID LPAR FuncParams RPAR TYPERETURN Types
FuncParams ::= ID COLON Type OtherFuncParams
| /* empty */;
OtherFuncParams ::= COMMA ID COLON Type OtherFuncParams:paramsList
| /* empty */;
Types ::= Type COMMA Types
| Type;
Procedure ::= PROCEDURE ID LPAR ProcParams RPAR COLON Body ENDPROCEDURE
ProcParams::= ProcParamId COLON Type OtherProcParams
| /* empty */ ;
OtherProcParams ::= COMMA ProcParamId COLON Type OtherProcParams
| /* empty */;
ProcParamId ::= ID
| OUT ID;
Body ::= VarDecl Body
| Stat Body
| /* empty */;
Stat ::= Ids ASSIGN Exprs SEMI
| ProcCall SEMI
| RETURN Exprs SEMI
| WRITE IOArgs SEMI
| WRITERETURN IOArgs SEMI
| READ IOArgs SEMI
| IfStat SEMI
| WhileStat SEMI;
FunCall ::= ID LPAR Exprs RPAR
| ID LPAR RPAR;
ProcCall ::= ID LPAR ProcExprs RPAR
| ID LPAR RPAR;
IfStat ::= IF Expr THEN Body Elifs Else ENDIF;
Elifs ::= Elif Elifs
| /* empty */;
Elif ::= ELIF Expr THEN Body
Else ::= ELSE Body
| /* empty */;
WhileStat ::= WHILE Expr DO Body ENDWHILE;
IOArgs ::= IOArgsExpr IOArgs
| DOLLARSIGN LPAR Expr RPAR IOArgs
| /* empty */;
IOArgsExpr ::= ID
| STRING_CONST
| IOArgsExpr PLUS IOArgsExpr;
ProcExprs::= Expr COMMA ProcExprs
| REF ID COMMA ProcExprs
| Expr
| REF ID;
Exprs ::= Expr COMMA Exprs
| Expr;
Expr ::= FunCall
| REAL_CONST
| INTEGER_CONST
| STRING_CONST
| ID
| TRUE
| FALSE
| Expr PLUS Expr
| Expr MINUS Expr
| Expr TIMES Expr
| Expr DIV Expr
| Expr AND Expr
| Expr OR Expr
| Expr GT Expr
| Expr GE Expr
| Expr LT Expr
| Expr LE Expr
| Expr EQ Expr
| Expr NE Expr
| LPAR Expr RPAR
| MINUS Expr
| NOT Expr;
Nel Lexer sono state aggiunte delle parole riservate che servono nella traduzione in C:
- daRestituire
- r [0-9
Inoltre nel nostro compilatore è stato anche eseguito un controllo relativo ai return quando si ha un if-else. Come si può vedere nell'esempio di seguito, sebbene non ci sia un return statement alla fine, il codice viene compilato poichè sia il body dell'if che il body dell'else hanno un return statement.
`func funzione(a:integer)->integer :
if a>8 then
return 8;
else
return 10;
endif;
endfunc`
Inoltre, nella repository è presente una branch chiamata "OrderOfVariable" nella quale è presente una prima versione del compilatore (incompleta) in cui si poteva usare una variabile se e solo se questa era stata dichiarata nelle linee precedenti di codice. Ciò è stato fatto grazie alla classe DefaultMutableTreeNode che è stata anche usata per produrre l'albero sintattico. Nel metodo visit dello ScopeCheckingVisitor si iterava su tutti i figli di un body e si visitava l'albero al contrario, in questo modo se, in uno statement, si usava una variabile che non era presente nella tabella dei simboli si lanciava un'eccezione. Nella repository è anche presente una branch chiamata "CodeGeneratorVisitor" nella quale è presente una versione del compilatore (anche questa incompleta) che consentiva di usare funzioni con multipli tipi di ritorno anche nei parametri di altre funzioni.