This is an old revision of the document!


TP 10 - Generation du 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, …)
  • operateur
  • resultat

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. Ecrivez 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. Ecrivez le code de trois adresses avec une pile pour le programme suivant (1p)
    if (a > 0)
    {
      result = 'positive';
    }
    else
    {
      result = 'negative';
    }
  3. Ecrivez le code de trois adresses avec une pile pour le programme suivant (1p)
    function double (nr)
    {
        return nr*2;
    }
     
    double (7/2);
  4. Telechargez 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 <spoiler AST>
    {
        "type": "module",
        "statements": [
            {
                "type": "expression",
                "op": "+",
                "left": {
                    "type": "expression",
                    "op": "+",
                    "left": {
                        "type": "expression",
                        "op": "+",
                        "left": {
                            "type": "number",
                            "value": 2
                        },
                        "right": {
                            "type": "number",
                            "value": 3
                        }
                    },
                    "right": {
                        "type": "number",
                        "value": 5
                    }
                },
                "right": {
                    "type": "expression",
                    "op": "*",
                    "left": {
                        "type": "identifier",
                        "value": "a"
                    },
                    "right": {
                        "type": "number",
                        "value": 5
                    }
                }
            },
            {
                "type": "assign",
                "to": "a",
                "from": {
                    "type": "function_call",
                    "id": "print",
                    "parameters": [
                        {
                            "type": "expression",
                            "op": "+",
                            "left": {
                                "type": "number",
                                "value": 2
                            },
                            "right": {
                                "type": "number",
                                "value": 3
                            }
                        },
                        {
                            "type": "identifier",
                            "value": "a"
                        }
                    ]
                }
            }
        ]
    }

    </spoiler>(2p)

  5. Modifiez la grammaire pour que les appels de fonction puissent être à l'intérieur des expressions. (1p)
  6. Ecrivez un programme qui écrit le three address code avec une pile pour le noeud assign (1p)
  7. Écrivez un programme qui écrit le three address code avec une pile pour les noeds function_call (2p)
  8. Écrivez un programme qui écrit le three address code avec une pile pour les noeuds function. Un paramètre est lu dans la fonction en utilisant l'instruction 'index' suivie de la position du paramètre. (1p)

Solutions

alf/laboratoare/10.1587386510.txt.gz · Last modified: 2020/04/20 15:41 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