La table de symboles représente un structure de données créée et traitée par le compilateur afin de stocker des informations sur l'apparition de certains éléments tels que le nom des variables, le nom des fonctions, les objets, les classes, les interfaces et d'autres similaires. Essentiellement, la table de symbole est utilisée pour acccomplir la fonction d'analyse du compilateur.
Selon le langage utilisé, le tableau de symbole peut servir aux suivants objectifs:
Pour stocker les variables dans la table de symboles, on va utiliser un dictionnaire:
// Dans VariableSymbolTable.java public class VariableSymbolTable { String type; Object value; } // Dans SymbolTable.java HashMap<String, VariableSymbolTable> symbolTable = new HashMap<>(); public void addVariableToSymbolTable(String variable, String type) { symbolTable.put( variable, new VariableSymbolTable(type, null) ); }
Du TP passé on a appris comment créer et structurer l'AST. Le but est de retourner les 2 structures de données dans un meme objet:
// Dans SymbolTree.java public class SymbolTree { ASTNode ast; SymbolTable symbolTable; } // Dans Main.java SymbolTree symbolTree = new SymbolTree(visitor.visit(tree), symbolTable); writeToFile("files\\output.json", toJSON(symbolTree));
Pour générer le parse tree et la table de symboles on va utiliser la grammaire suivante:
grammar Alf; start : (statement SEMICOLON NEWLINE*)* #multilineProg | statement SEMICOLON #singlelineProg ; statement : declaration #declarationRule | expression #expressionRule | list_declaration #listRule | function_declaration #functionRule | attribution #attributionRule ; declaration : type VARIABLE EQ expression #variableDeclaration | type VARIABLE EQ function_call #variableFunctionCall ; type : INT #typeInt | FLOAT #typeFloat | STRING #typeString ; value : INT_NUMBER #valueInt | FLOAT_NUMBER #valueFloat | STRING_TEXT #valueString | VARIABLE #valueVariable ; expression : left=expression op=MUL right=expression #expressionMultiply | left=expression op=DIV right=expression #expressionDivision | left=expression op=REM right=expression #expressionRem | left=expression op=ADD right=expression #expressionAddition | left=expression op=SUB right=expression #expressionSubtraction | LP expression RP #expressionParanthesis | value #expressionValue ; attribution : VARIABLE EQ expression #variableAttribution ; list_declaration : LIST VARIABLE EQ LSP values RSP #listDeclaration ; values : (value COMMA)* #listValues ; function_declaration: FUNCTION VARIABLE LP (parameter COMMA*)* RP LB (statement SEMICOLON)* return_function RB #functionContent ; parameter : declaration #functionParameter ; return_function : RETURN statement SEMICOLON #returnStatement | RETURN SEMICOLON #emptyReturn ; function_call : VARIABLE LP (value COMMA*)* RP #functionCall ; WS : (' ') -> skip; NEWLINE : ([\r\n]+) -> skip; FUNCTION : 'function'; VARIABLE : ('_'[a-zA-Z0-9]+); ADD : '+'; SUB : '-'; MUL : '*'; DIV : '/'; REM : '%'; INT : 'int'; FLOAT : 'float'; STRING : 'string'; LIST : 'list'; LP : '('; RP : ')'; EQ : '='; SEMICOLON : ';'; LSP : '['; RSP : ']'; COMMA : ','; LB : '{'; RB : '}'; RETURN : 'return'; INT_NUMBER : ([0-9]+); FLOAT_NUMBER : ([0-9]+'.'[0-9]+); STRING_TEXT : ('"'~["]+'"'|'\''~[']+'\'');
Pour pouvoir visiter tous les noeuds et générer les 2 structures de données, on va utiliser comme support les méthodes qui seront créées aujourd'hui au laboratoire. Vous pouvez observer la grammaire et aussi les implementations des classes, de visiteur et de SymbolTable dans le repository Github donné pour le TP d'aujourd'hui.
ex1.txt
(2.5p).ex2.txt
(2p)ex3.txt
. A la fin, modifiez le contenu du fichier ex3.txt
pour tester votre programme pour l'expression 123 - “alf”;. (3p). ex4.txt
. Suivez les lignes avec TODO 4. (2.5p). ex5.txt
. Suivez les lignes marquées par TODO 5. (2p)