This shows you the differences between two versions of the page.
alf:laboratoare:09 [2021/04/15 10:38] diana.ghindaoanu [Exercises] |
alf:laboratoare:09 [2022/05/10 00:19] (current) diana.ghindaoanu [Exercises] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== TP 9 - Generation de code ====== | + | ====== TP 9 - Génération de code 2 ====== |
- | ===== Three Address Code ===== | + | Dans le domaine informatique, le code de trois adresses (three address code) représente un code intermédiaire utilisé pour les compilateurs en tant que moyen d'écrire des instructions. Chaque instruction consiste en: |
- | Dans le domaine informatique, le code de trois adresses (**three address code**) représente un code intermédiaire utilisé pour les compilateurs en tant que moyen d'écrire des instructions. Chaque instruction consiste en: | + | * maximum trois adresses (variables, numéro, étiquette, …) |
- | * maximum trois adresses (variables, numero, étiquette, ...) | + | * opérateur |
- | * operateur | + | * résultat |
- | * resultat | + | |
- | Comme il s'agit d'un code intermédiaire, les opérands ne représentent pas d'adresses de mémoire ou de registres, mais plutôt des adresse //symboliques// qui seront traduites plus tard. | + | Contrairement au TP précédent où la transformation a été implémentée a l'aide des //variables temporaires//, l'objectif de ce travail est de représenter le ''Three Address Code'' en simulant une **pile**. |
- | === Exemple === | + | ===== Exemple ===== |
<code> | <code> | ||
/* Expression */ | /* Expression */ | ||
- | e = (a-2)+(a-5) | + | (5-3)*7; |
/* Three Address Code */ | /* Three Address Code */ | ||
- | t1 = a - 2 | + | push 5 |
- | t2 = a - 5 | + | push 3 |
- | t3 = t1 + t2 | + | sub |
- | e = t3 | + | push 7 |
+ | mul | ||
</code> | </code> | ||
+ | |||
+ | |||
===== Expression Parser ===== | ===== Expression Parser ===== | ||
Line 28: | Line 31: | ||
<code g4 Alf.g4> | <code g4 Alf.g4> | ||
grammar Alf; | grammar Alf; | ||
+ | |||
start : (statement SEMICOLON NEWLINE*)* #multilineProg | start : (statement SEMICOLON NEWLINE*)* #multilineProg | ||
| statement SEMICOLON #singlelineProg | | statement SEMICOLON #singlelineProg | ||
; | ; | ||
+ | |||
statement : declaration #declarationRule | statement : declaration #declarationRule | ||
| expression #expressionRule | | expression #expressionRule | ||
Line 40: | Line 43: | ||
| function_call #functionCallRule | | function_call #functionCallRule | ||
; | ; | ||
+ | |||
declaration : type VARIABLE EQ expression #variableDeclaration | declaration : type VARIABLE EQ expression #variableDeclaration | ||
| type VARIABLE EQ function_call #variableFunctionCall | | type VARIABLE EQ function_call #variableFunctionCall | ||
; | ; | ||
+ | |||
type : INT #typeInt | type : INT #typeInt | ||
| FLOAT #typeFloat | | FLOAT #typeFloat | ||
| STRING #typeString | | STRING #typeString | ||
; | ; | ||
+ | |||
value : INT_NUMBER #valueInt | value : INT_NUMBER #valueInt | ||
| FLOAT_NUMBER #valueFloat | | FLOAT_NUMBER #valueFloat | ||
Line 55: | Line 58: | ||
| VARIABLE #valueVariable | | VARIABLE #valueVariable | ||
; | ; | ||
+ | |||
expression : left=expression op=MUL right=expression #expressionMultiply | expression : left=expression op=MUL right=expression #expressionMultiply | ||
| left=expression op=DIV right=expression #expressionDivision | | left=expression op=DIV right=expression #expressionDivision | ||
Line 64: | Line 67: | ||
| value #expressionValue | | value #expressionValue | ||
; | ; | ||
+ | |||
attribution : VARIABLE EQ expression #variableAttribution | attribution : VARIABLE EQ expression #variableAttribution | ||
; | ; | ||
+ | |||
list_declaration : LIST VARIABLE EQ LSP values RSP #listDeclaration | list_declaration : LIST VARIABLE EQ LSP values RSP #listDeclaration | ||
; | ; | ||
+ | |||
values : (value COMMA)* #listValues | values : (value COMMA)* #listValues | ||
; | ; | ||
+ | |||
function_declaration: FUNCTION VARIABLE LP (parameter COMMA*)* RP LB (statement SEMICOLON)* return_function RB #functionContent | function_declaration: FUNCTION VARIABLE LP (parameter COMMA*)* RP LB (statement SEMICOLON)* return_function RB #functionContent | ||
; | ; | ||
+ | |||
parameter : declaration #functionParameter | parameter : declaration #functionParameter | ||
; | ; | ||
+ | |||
return_function : RETURN statement SEMICOLON #returnStatement | return_function : RETURN statement SEMICOLON #returnStatement | ||
| RETURN SEMICOLON #emptyReturn | | RETURN SEMICOLON #emptyReturn | ||
; | ; | ||
+ | |||
function_call : VARIABLE LP (value COMMA*)* RP #functionCall | function_call : VARIABLE LP (value COMMA*)* RP #functionCall | ||
; | ; | ||
- | + | ||
+ | |||
WS : (' ') -> skip; | WS : (' ') -> skip; | ||
NEWLINE : ([\r\n]+) -> skip; | NEWLINE : ([\r\n]+) -> skip; | ||
Line 114: | Line 117: | ||
FLOAT_NUMBER : ([0-9]+'.'[0-9]+); | FLOAT_NUMBER : ([0-9]+'.'[0-9]+); | ||
STRING_TEXT : ('"'~["]+'"'|'\''~[']+'\''); | STRING_TEXT : ('"'~["]+'"'|'\''~[']+'\''); | ||
+ | |||
; | ; | ||
</code> | </code> | ||
- | <code javascript index.js> | + | <code javascript index.ts> |
import { ASTNode } from "./index"; | import { ASTNode } from "./index"; | ||
import symbol_tree from './index'; | import symbol_tree from './index'; | ||
import { Expression, ValueNode, AttributionNode, FunctionCallNode } from './index'; | import { Expression, ValueNode, AttributionNode, FunctionCallNode } from './index'; | ||
+ | |||
var variable_id = 0; | var variable_id = 0; | ||
+ | |||
let results: string[] = []; | let results: string[] = []; | ||
function nextVar () | function nextVar () | ||
Line 144: | Line 147: | ||
if (node instanceof FunctionCallNode) | if (node instanceof FunctionCallNode) | ||
{ | { | ||
- | /**TODO: | + | |
- | * generate the three address code for each parameter of the node.parameters array | + | |
- | * write on the screen the three address code for each parameter | + | |
- | * node.result will be nextVar() | + | |
- | * write on the screen the three address code for function call | + | |
- | */ | + | |
} | } | ||
else | else | ||
if (node instanceof ValueNode) | if (node instanceof ValueNode) | ||
{ | { | ||
- | // the result for a number is the number itself | + | |
- | node.result = node.value; | + | |
} | } | ||
else | else | ||
- | if (node.id instanceof AttributionNode) | + | if (node instanceof VariableNode) |
{ | { | ||
- | /** TODO: | + | |
- | * generate the three address code for node.from | + | } |
- | * write on the screen the three address code for assign */ | + | else |
+ | if (node instanceof AttributionNode) | ||
+ | { | ||
+ | |||
} | } | ||
else | else | ||
Line 169: | Line 169: | ||
if (node.left !== undefined && node.right !== undefined) | if (node.left !== undefined && node.right !== undefined) | ||
{ | { | ||
- | writeThreeAddressCode (node.left); | ||
- | writeThreeAddressCode (node.right); | ||
- | |||
- | // node.left.result is the result of node.left | ||
- | // node.right.result is the result of node.right | ||
| | ||
- | /** TODO: | ||
- | * node.result will be nextVar() | ||
- | * write on the screen the three address code based on result, left result, right result and operator*/ | ||
} | } | ||
} | } | ||
Line 184: | Line 176: | ||
var ast = parser.parse (str); | var ast = parser.parse (str); | ||
console.log (JSON.stringify(ast, null, 4)); | console.log (JSON.stringify(ast, null, 4)); | ||
+ | |||
writeThreeAddressCode(ast); | writeThreeAddressCode(ast); | ||
- | |||
- | |||
</code> | </code> | ||
Line 193: | Line 183: | ||
===== Exercises ===== | ===== Exercises ===== | ||
- | - Dans un fichier **ex1.txt** écrivez le //three address code// pour les expressions suivantes (**1p**) | + | |
- | * 3-5/(4+8) | + | - Dans un fichier **ex1.txt** écrivez le //three address code// avec une **pile** pour les expressions suivantes (**1p**) |
- | * a = 2*7/(2-3) | + | * (5-3)*7+2+4 |
- | * e = (b+5)/(7-a) | + | * a = (5-3)*7+2+4 |
- | - Dans un fichier **ex2.txt** écrivez le //three address code// pour le programme suivant (**1p**) <code javascript> | + | * e = (a+5)/(a-2) |
- | if (a == 0) | + | - Dans un fichier **ex2.txt** écrivez le //three address code// avec une **pile** pour le programme suivant (**1p**) <code javascript> |
+ | if (a > 0) | ||
{ | { | ||
- | result = 'null'; | + | result = 'positive'; |
} | } | ||
else | else | ||
{ | { | ||
- | result = 'not null'; | + | result = 'negative'; |
} | } | ||
</code> | </code> | ||
- | - Dans un fichier **ex3.txt** écrivez le //three address code// pour le programme suivant (**1p**) <code javascript> | + | - Dans un fichier **ex3.txt** écrivez le //three address code// avec une **pile** pour le programme suivant (**1p**) <code javascript> |
- | function power (base, exp) | + | function double (nr) |
{ | { | ||
- | return base ^ exp; | + | return nr*2; |
} | } | ||
- | + | ||
- | power (4/2, 5); | + | double (7/2); |
</code> | </code> | ||
- | - Téléchargez [[https://github.com/UPB-FILS/alf/tree/master/TP/TP9 | la structure]] du tp. Pour les exercices suivants vous devez modifier seulement le contenu du fichier et **three_address_code.ts**. Exécutez le parser du laboratoire et écrivez un programme qui génere le three address code pour le noeud //expression// et vérifiez avec le fichier //ex4.txt// (**Indice**: Pour nommer les variables temporaires, vous pouvez prendre un compteur global que vous incrémentez chaque fois que vous avez besoin d'une autre variable). (**2p**) | + | - Téléchargez [[https://github.com/UPB-FILS-ALF/TP/tree/main/TP9|la structure]] du TP. Exécutez le parser du laboratoire et écrivez un programme qui écrit le three address code pour les noeuds //Expression// avec une pile (**2p**) |
- | - Écrivez un programme qui écrit le three address code pour le noeud //assign// et vérifiez la corectitude avec le fichier //ex5.txt//(**1p**) | + | - Modifiez la grammaire et le //Visitor// pour que les appels de fonction puissent être à l'intérieur des expressions. (Exemple: ''2 + 3 / _double(a)''). Testez la validité de la grammaire avec le fichier **ex5.txt**. (**1p**) |
- | - Écrivez un programme qui écrit le three address code pour le noeud //function_call// et testez avec le fichier //ex6.txt//(**2p**) | + | - Ecrivez un programme qui écrit le three address code avec une pile pour le noeud //AttributionNode//. Testez avec le fichier **ex6.txt**. (**1p**) |
- | - Au lieu d'écrire sur l'écran, ajoutez le three address code dans un tableau. A la fin, affichez le tableau sur l'écran. (**1p**) | + | - Écrivez un programme qui écrit le three address code avec une pile pour le noeud //FunctionCallNode//. Testez avec le fichier **ex7.txt**. (**2p**) |
- | - Pour résoudre cet exercice, on vous recommande de créer un nouveau fichier index_bonus.js, pour pouvoir modifier la structure sans supprimer les exercices précedents. Ajoutez le type à chaque argument dans le tableau. Les types sont: nombre, identifier, string, temp (une valeur temporaire). Pour chaque valeur temporaire, ajoutez la ligne où elle est assignée dans le three address code. Modifiez la structure du fichier index.js de facon que, si vous testez avec le fichier **ex6.txt**, vous obteniez le resultat suivant.(**2p**) | + | - Écrivez un programme qui écrit le three address code avec une pile pour le noeud //FunctionNode//. Testez avec le fichier **ex8.txt**(**2p**) |
- | <spoiler AST><code javascript> | + | |
- | { | + | |
- | "type": "module", | + | |
- | "statements": [ | + | |
- | { | + | |
- | "type": "assign", | + | |
- | "to": "a", | + | |
- | "from": { | + | |
- | "type": "function_call", | + | |
- | "function": "sum", | + | |
- | "parameters": [ | + | |
- | { | + | |
- | "type": "number", | + | |
- | "value": 1 | + | |
- | }, | + | |
- | { | + | |
- | "type": "number", | + | |
- | "value": 2 | + | |
- | }, | + | |
- | { | + | |
- | "type": "expression", | + | |
- | "operator": "+", | + | |
- | "left": { | + | |
- | "type": "number", | + | |
- | "value": 3 | + | |
- | }, | + | |
- | "right": { | + | |
- | "type": "expression", | + | |
- | "operator": "/", | + | |
- | "left": { | + | |
- | "type": "number", | + | |
- | "value": 4 | + | |
- | }, | + | |
- | "right": { | + | |
- | "type": "number", | + | |
- | "value": 5 | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | ] | + | |
- | } | + | |
- | } | + | |
- | ] | + | |
- | } | + | |
- | </code> | + | |
- | </spoiler> | + | |
- | <spoiler Three Address Code><code javascript> | + | |
- | [ | + | |
- | { | + | |
- | "result": { | + | |
- | "type": "temp", | + | |
- | "value": "var0", | + | |
- | "line": 1 | + | |
- | }, | + | |
- | "arg1": { | + | |
- | "type": "number", | + | |
- | "value": 4 | + | |
- | }, | + | |
- | "arg2": { | + | |
- | "type": "number", | + | |
- | "value": 5 | + | |
- | }, | + | |
- | "op": "/" | + | |
- | }, | + | |
- | { | + | |
- | "result": { | + | |
- | "type": "temp", | + | |
- | "value": "var1", | + | |
- | "line": 2 | + | |
- | }, | + | |
- | "arg1": { | + | |
- | "type": "number", | + | |
- | "value": 3 | + | |
- | }, | + | |
- | "arg2": { | + | |
- | "type": "temp", | + | |
- | "value": "var0", | + | |
- | "line": 1 | + | |
- | }, | + | |
- | "op": "+" | + | |
- | }, | + | |
- | { | + | |
- | "result": null, | + | |
- | "arg1": { | + | |
- | "type": "number", | + | |
- | "value": 1 | + | |
- | }, | + | |
- | "arg2": null, | + | |
- | "op": "param" | + | |
- | }, | + | |
- | { | + | |
- | "result": null, | + | |
- | "arg1": { | + | |
- | "type": "number", | + | |
- | "value": 2 | + | |
- | }, | + | |
- | "arg2": null, | + | |
- | "op": "param" | + | |
- | }, | + | |
- | { | + | |
- | "result": null, | + | |
- | "arg1": { | + | |
- | "type": "temp", | + | |
- | "value": "var1", | + | |
- | "line": 2 | + | |
- | }, | + | |
- | "arg2": null, | + | |
- | "op": "param" | + | |
- | }, | + | |
- | { | + | |
- | "result": { | + | |
- | "type": "temp", | + | |
- | "value": "var2", | + | |
- | "line": 6 | + | |
- | }, | + | |
- | "arg1": "sum", | + | |
- | "arg2": 3, | + | |
- | "op": "call" | + | |
- | }, | + | |
- | { | + | |
- | "result": null, | + | |
- | "arg1": "a", | + | |
- | "arg2": { | + | |
- | "type": "temp", | + | |
- | "value": "var2", | + | |
- | "line": 6 | + | |
- | }, | + | |
- | "op": "=" | + | |
- | } | + | |
- | ] | + | |
- | </code> | + | |
- | </spoiler> | + | |
- | + | ||
- | <hidden> | + | |
- | ===== Solutions ===== | + | |
- | + | ||
- | [[https://github.com/upb-fils/alf/tree/master/TP/TP9|Solutions]] | + | |
- | </hidden> | + | |
- | + | ||