This is an old revision of the document!
Le code de trois adresses est un moyen d'écrire des instructions. Chaque instruction consiste en:
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'; }
%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];
}
| {
$$ = [];
}
;
"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);
Nous voulons transformer l'AST suivant en une liste de Three Address Code avec une pile.
if (a > 0) { result = 'positive'; } else { result = 'negative'; }
function double (nr) { return nr*2; } double (7/2);
{ "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)
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)