Differences

This shows you the differences between two versions of the page.

Link to this comparison view

alf:laboratoare:09 [2020/04/13 23:52]
alexandru.radovici
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 ======
  
-===== 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:
-Le code de trois adresses ​est un moyen d'​écrire des instructions. Chaque instruction consiste en: +
-  * maximum trois adresses (variables, numero, étiquette, ...) +
-  * operateur +
-  * resultat+
  
-===== Expression Parser =====+   * maximum trois adresses (variables, numéro, étiquette, …) 
 +   * opérateur 
 +   * résultat
  
-<code jison alf.l> 
-Ws                    [ \t] 
-Number ​               [0-9]+("​."​[0-9]+)?​ 
-String_value ​         \"​[^\"​]*\"​ 
-Identifier ​           [A-Za-z][A-Za-z0-9]* 
-Newline ​              \r?\n 
  
-%%+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**.
  
  
-"​def" ​                { return '​DEF';​ } +===== Exemple =====
-"​int" ​                { return '​INT';​ } +
-"​float" ​              { return '​FLOAT';​ } +
-"​string" ​             { return '​STRING';​ } +
-"​function" ​           { return '​FUNCTION';​ } +
-"​end" ​                { return '​END';​ } +
-"="​  ​     { return '='; } +
-"​-" ​                  { return '​-';​ } +
-"​+" ​                  { return '​+';​ } +
-"​*" ​                  { return '​*';​ } +
-"/" ​                  { return '/';​ } +
-"​(" ​                  { return '​LP';​ } +
-"​)"​  ​                 { return '​RP';​ } +
-','​  ​     { return ',';​ }+
  
-{Ws}                  { /*skip whitespace*/ } +<​code>​ 
-{Newline} ​            { return '​NEWLINE'​} +/* Expression ​*/ 
-{Number} ​             { return '​NUMBER';​ } +(5-3)*7
-{String_value} ​       { return '​STRING_VALUE';​ } + 
-{Identifier} ​         { return '​IDENTIFIER';​ }+/* Three Address Code */ 
 +push 5 
 +push 3 
 +sub 
 +push 7 
 +mul
 </​code>​ </​code>​
  
-<​code ​jison alf.y+ 
-%left '​+'​ '​-'​ + 
-// * and / have higher priority +===== Expression Parser ===== 
-%left '​*'​ '/' ​+ 
 +<​code ​g4 Alf.g4
 +grammar Alf;
    
-%% +start               : (statement SEMICOLON NEWLINE*)* ​              #​multilineProg 
 +                    | statement SEMICOLON ​                          #​singlelineProg  
 +                    ;
    
-startexpressions {  +statement ​          declaration ​                                  #​declarationRule 
- $$ =  +                    | expression ​                                   #​expressionRule 
- { +                    | list_declaration ​                             #listRule 
-     type:'​script',​ +                    | function_declaration ​                         #​functionRule 
-     statements: $1 +                    | attribution ​                                  #​attributionRule 
- }; +                    | function_call ​                                #​functionCallRule 
-                 return $$;  +                    ;
-            };+
    
-expressionsstatement NEWLINE expressions { +declaration ​        type VARIABLE EQ expression ​                  #​variableDeclaration 
-                                                ​$3.splice (0, 0, $1); +                    type VARIABLE EQ function_call ​               #​variableFunctionCall 
-                                                $$ = $3; +                    ;
-+
- statement NEWLINE { +
- $$ = [$1]; +
-+
- | statement { +
- $$ = [$1]; +
- };+
    
-statement ​expr ​ {+type                ​INT                                           #​typeInt 
 +                    | FLOAT                                         #​typeFloat 
 +                    | STRING ​                                       #​typeString 
 +                    ;
    
-                } +value               : INT_NUMBER ​                                   #valueInt 
-            assign {+                    FLOAT_NUMBER ​                                 #​valueFloat 
 +                    | STRING_TEXT ​                                  #​valueString 
 +                    | VARIABLE ​                                     #​valueVariable 
 +                    ;
    
-                    } +expression ​         : left=expression op=MUL right=expression ​      #​expressionMultiply 
-            function_run {+                    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
 +                    ;
    
-expr: '(' expr ')' { +values ​             ​: (value COMMA)*                                #​listValues 
- $$ = $2;  +                    ;
-+
-   | expr '​+'​ expr {  +
- $$ = { +
-     type: '​expression',​ +
-     op: '​+',​ +
-     left: $1, +
-     right: $3 +
- }; +
-+
-      | expr '​-'​ expr { +
-        $$ = { +
-        type: '​expression',​ +
-        op: '​-',​ +
-        left: $1, +
-        right: $3 +
-    }; +
-      } +
-      | expr '*' expr {  +
-    $$ = { +
-     type: '​expression',​ +
-     op: '​*',​ +
-     left: $1, +
-     right: $3 +
- }; +
-+
-      | expr '/'​ expr { +
-    $$ = { +
-        type: '​expression',​ +
-        op: '/',​ +
-        left: $1, +
-        right: $3 +
-    }; +
-      } +
-      | IDENTIFIER +
-                { +
-                    ​$$ = { +
-              type: '​identifier',​ +
-              value: $1 +
-          }; +
-                } +
-      | NUMBER {  +
-   $$ = { +
-       type: '​nr',​ +
-       value: parseFloat ($1) +
-   }; +
-   } +
-    | STRING_VALUE { +
- $$ = { +
-       type: '​str',​ +
-       value: $1.substring (1, $1.length-2) +
-   }; +
- };+
    
-assignIDENTIFIER '​='​ expr +function_declarationFUNCTION VARIABLE LP (parameter COMMA*)* RP LB (statement SEMICOLON)* return_function RB    #​functionContent 
-            { +                    ;
-                $$ = { +
-                    ​type: '​set',​ +
-                    to: $1, +
-                    from: $3 +
-                }; +
-            } +
-        | IDENTIFIER '​='​ function_run  +
-        { +
-            $$ = { +
-                    type: '​set',​ +
-                    to: $1, +
-                    from: $3 +
-                }; +
-        };+
    
-function_runIDENTIFIER '​LP'​ parameters_run '​RP'​ { +parameter ​          declaration ​                                  #​functionParameter 
- $$ = { +                    ;
-  ​   type: '​fn_run',​ +
-  ​   id: $1, +
-  ​   parameters: $3 +
- };​ +
- };+
    
-parameters_runexpr ','​ parameters_run +return_function ​    RETURN statement SEMICOLON ​                   #​returnStatement 
- +                    RETURN SEMICOLON ​                             #​emptyReturn 
-     $3.splice (0, 0, $1); +                    ;
- $$ = $3; +
-+
- expr +
-+
- $$ = [$1]; +
-+
- | { +
- $$ = []; +
- }; +
- +
-</​code>​ +
- +
-<code javascript index.js>​ +
-"use strict"​;+
    
-// import fs for reading  +function_call ​      : VARIABLE LP (value COMMA*)* RP                #​functionCall 
-var fs = require ​('​fs'​);+                    ​;
    
-// import the generated Parser 
-var parser = require ('​./​alf.js'​).parser;​ 
    
-var str = fs.readFileSync ​(process.argv[2], 'UTF-8');+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 ​        : ​  ​('"'​~["​]+'"'​|'​\''​~['​]+'​\''​);​ 
 +  
 +
 +</​code>​ 
 + 
 +<code javascript index.ts>​ 
 +import { ASTNode } from "​./​index";​ 
 +import symbol_tree from '​./​index';​ 
 +import { Expression, ValueNode, AttributionNode,​ FunctionCallNode } from '​./​index'​;
    
 var variable_id = 0; var variable_id = 0;
- 
    
-// get a new temporary variable+let results: string[] = [];
 function nextVar () function nextVar ()
 { {
-    return 's' + variable_id++;​+    return 'var' + variable_id++;​
 } }
    
Line 197: Line 137:
 function writeThreeAddressCode (node) function writeThreeAddressCode (node)
 { {
-    if (node.type === 'script')+    if (node.id === 'StatementsNode')
     {     {
         for (var statement of node.statements)         for (var statement of node.statements)
Line 205: Line 145:
     }     }
     else     else
-    if (node.type === '​fn_run'​)+    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.type === '​nr'​)+    if (node instanceof ValueNode)
     {     {
-        ​// the result for a number is the number itself +        ​
-        node.result = node.value;+
     }     }
     else     else
-    if (node.type === '​set'​)+    if (node instanceof VariableNode)
     {     {
-        ​/** TODO:  +        ​
-         * generate the three address code for node.from +
-         * write on the screen the three address code for assign */+
     }     }
     else     else
-    if (node.type === '​identifier'​)+    if (node instanceof AttributionNode)
     {     {
-        ​/*TODO: the result is the value of the identifier */+        ​
     }     }
     else     else
-    if (node.type === '​expression'​)+    if (node instanceof Expression)
     {     {
         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 252: 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>​
  
-===== Objectif ===== 
  
-Nous voulons transformer l'AST suivant dans une liste de Three Address Code.+===== Exercises =====
  
-===== Exercises ===== 
  
-  - Dans un fichier **ex1.txt** écrivez le //three address code// pour les expressions suivantes (**1p**) +  - Dans un fichier **ex1.txt** écrivez le //three address code// ​avec une **pile** ​pour les expressions suivantes (**1p**) 
-    * 5-3/(4+2) +    * (5-3)*7+2+4 
-    * a = 5-3/(4+2) +    * a = (5-3)*7+2+4 
-    * e = (a-5)*(a-3+    * e = (a+5)/(a-2
-  - Dans un fichier **ex2.txt** écrivez le //three address code// pour le programme suivant (**1p**) <code javascript>​ +  - Dans un fichier **ex2.txt** écrivez le //three address code// ​avec une **pile** ​pour le programme suivant (**1p**) <code javascript>​ 
-if (a > 0 && a < 10000)+if (a > 0)
 { {
-  result = 'pozitive';+  result = 'positive';
 } }
 else else
Line 278: Line 198:
 } }
 </​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 (nr, e)+function ​double ​(nr)
 { {
-    ​let n = 1; +    return nr*2;
-    for (let i=0; i<e; i++) n = n * nr; +
-    ​return nr;+
 } }
- +  
-power (72);+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 **index.js**. 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'​ecran. (**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":​ "​set",​ +
-            "​to":​ "​a",​ +
-            "​from":​ { +
-                "​type":​ "​fn_run",​ +
-                "​function":​ "​sum",​ +
-                "​parameters":​ [ +
-                    { +
-                        "​type":​ "​nr",​ +
-                        "​value":​ 1 +
-                    }, +
-                    { +
-                        "​type":​ "​nr",​ +
-                        "​value":​ 2 +
-                    }, +
-                    { +
-                        "​type":​ "​expression",​ +
-                        "​operator":​ "​+",​ +
-                        "​left":​ { +
-                            "​type":​ "​nr",​ +
-                            "​value":​ 3 +
-                        }, +
-                        "​right":​ { +
-                            "​type":​ "​expression",​ +
-                            "​operator":​ "/",​ +
-                            "​left":​ { +
-                                "​type":​ "​nr",​ +
-                                "​value":​ 4 +
-                            }, +
-                            "​right":​ { +
-                                "​type":​ "​nr",​ +
-                                "​value":​ 5 +
-                            } +
-                        } +
-                    } +
-                ] +
-            } +
-        } +
-    ] +
-+
-</​code>​ +
-</​spoiler>​ +
-<spoiler Three Address Code><​code javascript>​ +
-+
-    { +
-        "​res":​ { +
-            "​type":​ "​temp",​ +
-            "​value":​ "​var0",​ +
-            "​line":​ 1 +
-        }, +
-        "​arg1":​ { +
-            "​type":​ "​nr",​ +
-            "​value":​ 4 +
-        }, +
-        "​arg2":​ { +
-            "​type":​ "​nr",​ +
-            "​value":​ 5 +
-        }, +
-        "​op":​ "/"​ +
-    }, +
-    { +
-        "​res":​ { +
-            "​type":​ "​temp",​ +
-            "​value":​ "​var1",​ +
-            "​line":​ 2 +
-        }, +
-        "​arg1":​ { +
-            "​type":​ "​nr",​ +
-            "​value":​ 3 +
-        }, +
-        "​arg2":​ { +
-            "​type":​ "​temp",​ +
-            "​value":​ "​var0",​ +
-            "​line":​ 1 +
-        }, +
-        "​op":​ "​+"​ +
-    }, +
-    { +
-        "​res":​ null, +
-        "​arg1":​ { +
-            "​type":​ "​nr",​ +
-            "​value":​ 1 +
-        }, +
-        "​arg2":​ null, +
-        "​op":​ "​param"​ +
-    }, +
-    { +
-        "​res":​ null, +
-        "​arg1":​ { +
-            "​type":​ "​nr",​ +
-            "​value":​ 2 +
-        }, +
-        "​arg2":​ null, +
-        "​op":​ "​param"​ +
-    }, +
-    { +
-        "​res":​ null, +
-        "​arg1":​ { +
-            "​type":​ "​temp",​ +
-            "​value":​ "​var1",​ +
-            "​line":​ 2 +
-        }, +
-        "​arg2":​ null, +
-        "​op":​ "​param"​ +
-    }, +
-    { +
-        "​res":​ { +
-            "​type":​ "​temp",​ +
-            "​value":​ "​var2",​ +
-            "​line":​ 6 +
-        }, +
-        "​arg1":​ "​sum",​ +
-        "​arg2":​ 3, +
-        "​op":​ "​call"​ +
-    }, +
-    { +
-        "​res":​ 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>​ +
- +
  
  
  
alf/laboratoare/09.1586811136.txt.gz · Last modified: 2020/04/13 23:52 by alexandru.radovici
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0