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
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');
 
 
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 is the result of node.left
            // node.right 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
        console.log ('push '+node.value);
    }
    else
    if (node.type === 'id')
    {
 
    }
    else
    if (node.type === 'function_run')
    {
 
    }
    else
    if (node.type === 'function')
    {
 
    }
}
 
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)
    • 2+3*(5+6)
    • s = 2+3*(5+6)
    • e = (s+3)-(s+4)
  2. Ecrivez le code de trois adresses avec une pile pour le programme suivant (1p)
    if (x < 0)
    {
      r = 'unde zero';
    }
    else
    {
      r = 'above zero';
    }
  3. Ecrivez le code de trois adresses avec une pile pour le programme suivant (1p)
    function square (x)
    {
        return x*x;
    }
     
    square (5+6);
  4. Telechargez la structure du TP.Exécutez le parser du laboratoire et écrivez un programme qui écrit le three address code pour les noeds expr (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) <spoiler AST>
    {
        "type": "script",
        "statements": [
            {
                "type": "expr",
                "op": "+",
                "left": {
                    "type": "expr",
                    "op": "+",
                    "left": {
                        "type": "expr",
                        "op": "+",
                        "left": {
                            "type": "number",
                            "value": 2
                        },
                        "right": {
                            "type": "number",
                            "value": 3
                        }
                    },
                    "right": {
                        "type": "number",
                        "value": 5
                    }
                },
                "right": {
                    "type": "expr",
                    "op": "*",
                    "left": {
                        "type": "id",
                        "value": "a"
                    },
                    "right": {
                        "type": "number",
                        "value": 5
                    }
                }
            },
            {
                "type": "assign",
                "to": "a",
                "from": {
                    "type": "function_run",
                    "id": "print",
                    "parameters": [
                        {
                            "type": "expr",
                            "op": "+",
                            "left": {
                                "type": "number",
                                "value": 2
                            },
                            "right": {
                                "type": "number",
                                "value": 3
                            }
                        },
                        {
                            "type": "id",
                            "value": "a"
                        }
                    ]
                }
            }
        ]
    }

    </spoiler>(2p)

  5. Modifiez la grammaire pour que les appels de fonction puissent être à l'intérieur des expressions. (1p)
  6. Ecrire un programme qui écrit le three address code avec une pile pour les noeds assign (1p)
  7. Écrivez un programme qui écrit le three address code avec une pile pour les noeds function_run (2p)
  8. Écrivez un programme qui écrit le three address code avec une pile pour les noeds 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.1556175843.txt.gz · Last modified: 2019/04/25 10:04 by teodor.deaconu
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