This is an old revision of the document!


TP 10 - Génération de code 2

Three Address Code

Le code de trois adresses est un moyen d'écrire des instructions. Chaque instruction consiste en:

  • maximum trois adresses (variables, numero, étiquette, …)
  • opérateur
  • résultat

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);

Objectif

Nous voulons transformer l'AST suivant en une liste de Three Address Code avec une pile.

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.1587583208.txt.gz · Last modified: 2020/04/22 22:20 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