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)