TP 9 - Génération de code 2

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, …)
  • opérateur
  • résultat

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

/* Expression */
(5-3)*7;

/* Three Address Code */
push 5
push 3
sub
push 7
mul

Expression Parser

Alf.g4
grammar Alf;
 
start               : (statement SEMICOLON NEWLINE*)*               #multilineProg
                    | statement SEMICOLON                           #singlelineProg 
                    ;
 
statement           : declaration                                   #declarationRule
                    | expression                                    #expressionRule
                    | list_declaration                              #listRule
                    | function_declaration                          #functionRule
                    | attribution                                   #attributionRule
                    | function_call                                 #functionCallRule
                    ;
 
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         :   ('"'~["]+'"'|'\''~[']+'\'');
 
;
index.ts
import { ASTNode } from "./index";
import symbol_tree from './index';
import { Expression, ValueNode, AttributionNode, FunctionCallNode } from './index';
 
var variable_id = 0;
 
let results: string[] = [];
function nextVar ()
{
    return 'var' + variable_id++;
}
 
 
function writeThreeAddressCode (node)
{
    if (node.id === 'StatementsNode')
    {
        for (var statement of node.statements)
        {
            writeThreeAddressCode(statement);
        }
    }
    else
    if (node instanceof FunctionCallNode)
    {
 
    }
    else
    if (node instanceof ValueNode)
    {
 
    }
    else
    if (node instanceof VariableNode)
    {
 
    }
    else
    if (node instanceof AttributionNode)
    {
 
    }
    else
    if (node instanceof Expression)
    {
        if (node.left !== undefined && node.right !== undefined)
        {
 
        }
    }
}
 
var ast = parser.parse (str);
console.log (JSON.stringify(ast, null, 4));
 
writeThreeAddressCode(ast);

Exercises

  1. Dans un fichier ex1.txt écrivez le three address code avec une pile pour les expressions suivantes (1p)
    • (5-3)*7+2+4
    • a = (5-3)*7+2+4
    • e = (a+5)/(a-2)
  2. Dans un fichier ex2.txt écrivez le three address code avec une pile pour le programme suivant (1p)
    if (a > 0)
    {
      result = 'positive';
    }
    else
    {
      result = 'negative';
    }
  3. Dans un fichier ex3.txt écrivez le three address code avec une pile pour le programme suivant (1p)
    function double (nr)
    {
        return nr*2;
    }
     
    double (7/2);
  4. Téléchargez 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)
  5. 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)
  6. Ecrivez un programme qui écrit le three address code avec une pile pour le noeud AttributionNode. Testez avec le fichier ex6.txt. (1p)
  7. Écrivez un programme qui écrit le three address code avec une pile pour le noeud FunctionCallNode. Testez avec le fichier ex7.txt. (2p)
  8. Écrivez un programme qui écrit le three address code avec une pile pour le noeud FunctionNode. Testez avec le fichier ex8.txt(2p)
alf/laboratoare/09.txt · Last modified: 2022/05/10 00:19 by diana.ghindaoanu
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