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 '*' '/' %% 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') { /**TODO: * generate the three address code for each parameter of the node.parameters array * write on the screen the three address code for each parameter * node.result will be nextVar() * write on the screen the three address code for function call */ } else if (node.type === 'number') { // the result for a number is the number itself node.result = node.value; } else if (node.type === 'assign') { /** TODO: * generate the three address code for node.from * write on the screen the three address code for assign */ } else if (node.type === 'identifier') { /*TODO: the result is the value of the identifier */ } else if (node.type === 'expression') { 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 /** TODO: * node.result will be nextVar() * write on the screen the three address code based on result, left result, right result and operator*/ } } } var ast = parser.parse (str); console.log (JSON.stringify(ast, null, 4)); writeThreeAddressCode(ast);
Nous voulons transformer l'AST suivant dans une liste de Three Address Code.
if (a > 0) { result = 'positive'; } else { result = 'negative'; }
function double (nr) { return nr*2; } double (7/2);