This is an old revision of the document!
Le code de trois adresses est un moyen d'écrire des instructions. Chaque instruction consiste en:
/* Jison example file */
/* Tokens part */
%lex
%%
/* RegEx */
// add newline for Windows (\r\n) and Linux/Unix/Mac (\n)
\r?\n return 'NEWLINE';
// \s includes \n space and tab, we need the NEWLINE token, so we put space and tab in white spacve
[ \t] /* skip whitespace */
function return 'FUNCTION';
endfunction return 'END_FUNCTION';
[0-9]+("."[0-9]+)? return 'NUMBER';
\"[^\"]*\" return 'STRING_VALUE';
// add the token for the variable
[A-Za-z][A-Za-z0-9]* return 'IDENTIFIER';
'=' return '=';
"-" return '-';
"+" return '+';
"*" return '*';
"/" return '/';
"(" return '(';
")" return ')';
',' return ',';
/lex
/* Grammar part, for this lab */
// when it is ambiguous, derive the left part
%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 '(' parameters_run ')' {
$$ = {
type: 'function_run',
id: $1,
parameters: $3
};
};
parameters_run: expr ',' parameters_run
{
$3.splice (0, 0, $1);
$$ = $3;
}
| expr
{
$$ = [$1];
}
| {
$$ = [];
};
function: 'function' IDENTIFIER '(' parameters ')' '{' expressions '}' {
$$ = {
type: 'function',
parameters: $4,
statements: $7
};
};
parameters: IDENTIFIER ',' parameters
{
$3.splice (0, 0, $1);
$$ = $3;
}
| IDENTIFIER
{
$$ = [$1];
}
| {
$$ = [];
};
"use strict"; // import fs for reading var fs = require ('fs'); // import the generated Parser var parser = require ('./program.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);
Nous voulons transformer l'AST suivant en une liste de Three Address Code avec une pile.
if (x < 0) { r = 'unde zero'; } else { r = 'above zero'; }
function square (x) { return x*x; } square (5+6);
{ "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)