This is an old revision of the document!


TP 9 - Generation du code

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
Newline               \r?\n
Ws                    [ \t]
Number                [0-9]+("."[0-9]+)?
String_value          \"[^\"]*\"
Identifier            [A-Za-z][A-Za-z0-9]*
 
 
%%
 
 
"var"                 { return 'VAR'; }
"of"                  { return 'OF'; }
"int"                 { return 'INT'; }
"float"               { return 'FLOAT'; }
"string"              { return 'STRING'; }
"function"            { return 'FUNCTION'; }
"endfunction"         { return 'END_FUNCTION'; }
"="				      { 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 '*' '/' 
 
%% 
 
start: expressions { 
				$$ = 
				{
				    type:'script',
				    statements: $1
				};
                 return $$; 
            };
 
expressions: statement NEWLINE expressions	{
                                                $3.splice (0, 0, $1);
                                                $$ = $3;
										}
			| statement NEWLINE		{
									$$ = [$1];
								}
			| statement	{
						$$ = [$1];
					};
 
statement:  expr  {
 
                }
            | assign {
 
                    }
            | function_run {
 
            		};
 
 
expr:	'(' expr ')'	{
							$$ = $2;	
						}
	  | expr '+' expr	{ 
				$$ = {
				    type: 'expr',
				    op: '+',
				    left: $1,
				    right: $3
				};
			}
      | expr '-' expr 	{
        				$$ = {
    				    type: 'expr',
    				    op: '-',
    				    left: $1,
    				    right: $3
    				};
      			}
      | expr '*' expr	{ 
    			$$ = {
				    type: 'expr',
				    op: '*',
				    left: $1,
				    right: $3
				};
			}
      | expr '/' expr 	{
    				$$ = {
    				    type: 'expr',
    				    op: '/',
    				    left: $1,
    				    right: $3
    				};
      			}
      | IDENTIFIER
                {
                    $$ = {
        	  		    type: 'id',
        	  		    value: $1
        	  		};
                }
      | NUMBER 	{ 
	  		$$ = {
	  		    type: 'number',
	  		    value: parseFloat ($1)
	  		};
	  	}
	   | STRING_VALUE {
			$$ = {
	  		    type: 'string',
	  		    value: $1.substring (1, $1.length-2)
	  		};
		};
 
assign: IDENTIFIER '=' expr
            {
                $$ = {
                    type: 'assign',
                    to: $1,
                    from: $3
                };
            }
        | IDENTIFIER '=' function_run 
        {
            $$ = {
                    type: 'assign',
                    to: $1,
                    from: $3
                };
        };
 
function_run: IDENTIFIER 'LP' parameters_run 'RP' {
													$$ = {
													    type: 'function_run',
													    id: $1,
													    parameters: $3
													};
												};
 
parameters_run: expr ',' parameters_run
				{
				    $3.splice (0, 0, $1);
					$$ = $3;
				}
			| expr
				{
					$$ = [$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;
 
 
function nextVariable ()
{
    return 'variable'+variable_id++;
}
 
 
function writeThreeAddressCode (node)
{
    if (node.type === 'script')
    {
        for (var statementIndex in node.statements)
        {
            writeThreeAddressCode(node.statements[statementIndex]);
        }
    }
    else
    if (node.type === 'expr')
    {
        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
            // write the three address code here
        }
    }
    else
    if (node.type === 'number')
    {
        // the result for a number is the number itself
        node.result = node.value;
    }
    else
    if (node.type === 'id')
    {
 
    }
    else
    if (node.type === 'function_run')
    {
 
    }
}
 
var ast = parser.parse (str);
console.log (JSON.stringify(ast, null, 4));
 
writeThreeAddressCode(ast);
 

Objectif

Nous voulons transformer l'AST suivant dans une liste de Three Address Code.

Exercises

  1. Dans un fichier ex1.txt écrivez le three address code pour les expressions suivantes (1p)
    • (4+2)/5-3
    • a = (4+2)/5-3
    • e = (a-2)+(a-5)
  2. Dans un fichier ex2.txt écrivez le three address code pour le programme suivant (1p)
    if (a > 0)
    {
      result = 'positive';
    }
    else
    {
      result = 'negative';
    }
  3. Dans un fichier ex3.txt écrivez le three address code pour le programme suivant (1p)
    function double (nr)
    {
        return nr*2;
    }
     
    double (7/2);
  4. Téléchargez 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 les noeuds 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)
  5. Écrivez un programme qui écrit le three address code pour les noeuds assign et vérifiez la corectitude avec le fichier ex5.txt(1p)
  6. Écrivez un programme qui écrit le three address code pour les noeuds fonction et testez avec le fichier ex6.txt(2p)
  7. 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)
  8. 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)

AST

AST

{
    "type": "module",
    "statements": [
        {
            "type": "assign",
            "to": "a",
            "from": {
                "type": "function_call",
                "function": "sum",
                "parameters": [
                    {
                        "type": "number",
                        "value": 1
                    },
                    {
                        "type": "number",
                        "value": 2
                    },
                    {
                        "type": "expression",
                        "operator": "+",
                        "left": {
                            "type": "number",
                            "value": 3
                        },
                        "right": {
                            "type": "expression",
                            "operator": "/",
                            "left": {
                                "type": "number",
                                "value": 4
                            },
                            "right": {
                                "type": "number",
                                "value": 5
                            }
                        }
                    }
                ]
            }
        }
    ]
}

Three Address Code

Three Address Code

[
    {
        "result": {
            "type": "temp",
            "value": "var0",
            "line": 1
        },
        "arg1": {
            "type": "number",
            "value": 4
        },
        "arg2": {
            "type": "number",
            "value": 5
        },
        "op": "/"
    },
    {
        "result": {
            "type": "temp",
            "value": "var1",
            "line": 2
        },
        "arg1": {
            "type": "number",
            "value": 3
        },
        "arg2": {
            "type": "temp",
            "value": "var0",
            "line": 1
        },
        "op": "+"
    },
    {
        "result": null,
        "arg1": {
            "type": "number",
            "value": 1
        },
        "arg2": null,
        "op": "param"
    },
    {
        "result": null,
        "arg1": {
            "type": "number",
            "value": 2
        },
        "arg2": null,
        "op": "param"
    },
    {
        "result": null,
        "arg1": {
            "type": "temp",
            "value": "var1",
            "line": 2
        },
        "arg2": null,
        "op": "param"
    },
    {
        "result": {
            "type": "temp",
            "value": "var2",
            "line": 6
        },
        "arg1": "sum",
        "arg2": 3,
        "op": "call"
    },
    {
        "result": null,
        "arg1": "a",
        "arg2": {
            "type": "temp",
            "value": "var2",
            "line": 6
        },
        "op": "="
    }
]
alf/laboratoare/09.1586787695.txt.gz · Last modified: 2020/04/13 17:21 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