This is an old revision of the document!


TP 10 - 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.

Expression Parser

alf.l
Ws                    [ \t]
Number                [0-9]+("."[0-9]+)?
String_value          \"[^\"]*\"
Identifier            [A-Za-z][A-Za-z0-9]*
Newline               \r?\n
 
%%
 
 
"def"                 { return 'DEF'; }
"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*/ }
{Newline}             { return 'NEWLINE'; }
{Number}              { return 'NUMBER'; }
{String_value}        { return 'STRING_VALUE'; }
{Identifier}          { return 'IDENTIFIER'; }
alf.y
%left '+' '-'
// * and / have higher priority
%left '*' '/' 
 
%% 
 
%left '+' '-'
// * and / have higher priority
%left '*' '/' 
 
%% 
 
start: statements 							{ 
												$$ =  {
													type:'module',
													statements: $1
												};
												return $$; 
											};
 
statements
: statement NEWLINE statements				{
                                                $3.splice (0, 0, $1);
                                                $$ = $3;
											}
| statement NEWLINE							{
												$$ = [$1];
											}
| statement									{
												$$ = [$1];
											}
			;
 
statement
: expression  								{}
| assign 									{}
| function_call 							{}
;
 
 
expression
: LP expression RP							{ $$ = $2; }
| expression '+' expression					{ 
												$$ = {
													type: 'expression',
													operator: '+',
													left: $1,
													right: $3
												};
											}
| expression '-' expression 				{
													$$ = {
													type: 'expression',
													operator: '-',
													left: $1,
													right: $3
												};
											}
| expression '*' expression					{ 
												$$ = {
													type: 'expression',
													operator: '*',
													left: $1,
													right: $3
												};
											}
| expression '/' expression 				{
												$$ = {
													type: 'expression',
													operator: '/',
													left: $1,
													right: $3
												};
											}
| IDENTIFIER 								{
												$$ = {
													type: 'identifier',
													value: $1
												};
											}
| NUMBER 									{ 
												$$ = {
													type: 'number',
													value: parseFloat ($1)
												};
											}
| STRING_VALUE 								{
												$$ = {
													type: 'string',
													value: $1.substring (1, $1.length-2)
												};
											}
;
 
 
assign
: IDENTIFIER '=' expression						{
													$$ = {
														type: 'assign',
														to: $1,
														from: $3
													};
												}
| IDENTIFIER '=' function_call					{
													$$ = {
															type: 'assign',
															to: $1,
															from: $3
														};
												}
;
 
function_call
: IDENTIFIER LP parameters_run RP  			{
													$$ = {
														type: 'function_call',
														function: $1,
														parameters: $3
													};
												};
 
parameters_run
: expression ',' parameters_run					{
													$3.splice (0, 0, $1);
													$$ = $3;
												}
| expression									{
													$$ = [$1];
												}
|												{
													$$ = [];
												}
;
index.js
"use strict";
 
// import fs for reading 
var fs = require ('fs');
 
// import the generated Parser
var parser = require ('./alf.js').parser;
 
var str = fs.readFileSync (process.argv[2], 'UTF-8');
 
var variable_id = 0;
 
 
// get a new temporary variable
function nextVar ()
{
    return 'var' + variable_id++;
}
 
 
function writeThreeAddressCode (node)
{
    if (node.type === 'module')
    {
        for (var statement of node.statements)
        {
            writeThreeAddressCode(statement);
        }
    }
    else
    if (node.type === 'function_call')
    {
 
    }
    else
    if (node.type === 'number')
    {
 
    }
    else
    if (node.type === 'assign')
    {
 
    }
    else
    if (node.type === 'identifier')
    {
 
    }
    else
    if (node.type === '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 texte ex1.txt, écrivez le code de trois adresses 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 texte ex2.txt, écrivez le code de trois adresses avec une pile pour le programme suivant (1p)
    if (a > 0)
    {
      result = 'positive';
    }
    else
    {
      result = 'negative';
    }
  3. Dans un fichier texte ex3.txt, écrivez le code de trois adresses 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 (le fichier alf.y) 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 et vérifiez que le programme ne retourne aucune erreur. (1p)
  6. Ecrivez un programme qui écrit le three address code avec une pile pour le noeud assign. Testez avec le fichier ex6.txt. (1p)
  7. Écrivez un programme qui écrit le three address code avec une pile pour les noeds function_call. Testez avec le fichier ex7.txt. (2p)
  8. Écrivez un programme qui écrit le three address code avec une pile pour les noeuds function. Tout d'abord, il faut modifier la grammaire afin qu'elle accepte la déclaration des fonctions
        function function_name(param1, param2, ...)
        {
           statement1
           statement2
           ...
        }
        

Suivez les lignes marquées par TODO8 afin de générer le Three Address Code pour les fonctions. (2p)

Solutions

alf/laboratoare/10.1618475499.txt.gz · Last modified: 2021/04/15 11:31 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