3 +---------------------------------------------------------------------------------+
4 | Copyright (c) 2010 Haanga |
5 +---------------------------------------------------------------------------------+
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met: |
8 | 1. Redistributions of source code must retain the above copyright |
9 | notice, this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
15 | 3. All advertising materials mentioning features or use of this software |
16 | must display the following acknowledgement: |
17 | This product includes software developed by César D. Rodas. |
19 | 4. Neither the name of the César D. Rodas nor the |
20 | names of its contributors may be used to endorse or promote products |
21 | derived from this software without specific prior written permission. |
23 | THIS SOFTWARE IS PROVIDED BY CÉSAR D. RODAS ''AS IS'' AND ANY |
24 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
25 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
26 | DISCLAIMED. IN NO EVENT SHALL CÉSAR D. RODAS BE LIABLE FOR ANY |
27 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
28 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
30 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
31 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE |
33 +---------------------------------------------------------------------------------+
34 | Authors: César Rodas <crodas@php.net> |
35 +---------------------------------------------------------------------------------+
41 * This class takes the generated AST structure (arrays),
42 * and generated the PHP represantion.
46 class Haanga_CodeGenerator
51 // getCode (AST $op_code) {{{
53 * Transform the AST generated by the Haanga_Compiler class
54 * and return the equivalent PHP code.
56 * @param array $op_code
60 final function getCode($op_code)
64 foreach ($op_code as $op) {
65 $method = "php_{$op['op']}";
66 if (!is_callable(array($this, $method))) {
67 throw new Exception("CodeGenerator: Missing method $method");
76 $code .= $this->ident();
78 $code .= $this->$method($op);
86 * Get the string for the current tabulation
90 protected function ident()
93 $code .= str_repeat($this->tab
, $this->ident
);
101 * Return code for "else"
105 protected function php_else()
108 $code = $this->ident()."} else {";
116 * Return code for "comments"
120 function php_comment($op)
122 return "/* {$op['comment']} */";
126 // php_function(array $op) {{{
128 * Return the function declaration of the class, for now
129 * it has fixed params, this should change soon to generate
130 * any sort of functions
134 function php_function($op)
136 $code = "function {$op['name']}(\$vars, \$return=FALSE, \$blocks=array())".$this->ident()."{";
142 // php_if(array $op) {{{
144 * Return the "if" declaration and increase $this->ident
148 protected function php_if($op)
150 $code = "if (".$this->php_generate_expr($op['expr']).") {";
158 * Return a stand-alone statement
162 protected function php_expr($op)
164 return $this->php_generate_expr($op[0]).";";
168 // php_end_block() {{{
170 * Finish the current block (if, for, function, etc),
171 * return the final "}", and decrease $this->ident
175 protected function php_end_block()
178 return $this->ident()."}";
182 // php_end_function() {{{
184 * Return code to end a function
188 protected function php_end_function()
190 return $this->php_end_block();
196 * Return code to end a if
200 protected function php_end_if()
202 return $this->php_end_block();
206 // php_end_foreach() {{{
208 * Return code to end a foreach
212 protected function php_end_foreach()
214 return $this->php_end_block();
218 // php_foreach(array $op) {{{
220 * Return the declaration of a "foreach" statement.
224 protected function php_foreach($op)
226 $op['array'] = $this->php_get_varname($op['array']);
227 $op['value'] = $this->php_get_varname($op['value']);
228 $code = "foreach ({$op['array']} as ";
229 if (!isset($op['key'])) {
230 $code .= " {$op['value']}";
232 $op['key'] = $this->php_get_varname($op['key']);
233 $code .= " {$op['key']} => {$op['value']}";
242 // php_append_var(array $op) {{{
244 * Return code to append something to a variable
248 protected function php_append_var($op)
250 return $this->php_declare($op, '.=');
256 * Return code for a function calling.
260 protected function php_exec($op)
263 $code .= $op['name'].'(';
264 if (isset($op['args'])) {
265 $code .= $this->php_generate_list($op['args']);
272 // php_generate_expr($op) {{{
274 * Return an expression
278 protected function php_generate_expr($expr)
281 if (is_array($expr) && isset($expr['op_expr'])) {
282 if ($expr['op_expr'] == 'expr') {
284 $code .= $this->php_generate_expr($expr[0]);
287 $code .= $this->php_generate_expr($expr[0]);
288 $code .= " {$expr['op_expr']} ";
289 $code .= $this->php_generate_expr($expr[1]);
292 if (is_array($expr)) {
293 $code .= $this->php_generate_stmt(array($expr));
295 if ($expr === FALSE) {
297 } else if ($expr === TRUE) {
307 // php_generate_list(array ($array) {{{
309 * Return a list of expressions for parameters
314 protected function php_generate_list($array)
317 foreach ($array as $value) {
318 $code .= $this->php_generate_stmt(array($value));
321 return substr($code, 0, -2);
325 // php_generate_stmt(Array $op) {{{
327 * Return the representation of a statement
331 protected function php_generate_stmt($op)
335 for ($i=0; $i < count($op); $i++
) {
336 if (!isset($op[$i])) {
339 if (!is_Array($op[$i])) {
340 throw new Haanga_CompilerException("Malformed declaration ".print_r($op, TRUE));
343 $value = current($op[$i]);
347 $code .= $this->php_generate_list($value);
352 if (strlen($code) != 0 && $code[strlen($code) -1] != '.') {
356 $value = array('name' => $value, 'args' => $op[$i]['args']);
357 $code .= $this->php_exec($value, FALSE);
361 $code .= $this->php_generate_stmt(array($value[0]))." => ".$this->php_generate_stmt(array($value[1]));
364 if ($code != "" && $code[strlen($code)-1] == '"') {
365 $code = substr($code, 0, -1);
369 $html = addslashes($value);
370 $html = str_replace(array('$', "\r", "\t", "\n","\\'"), array('\\$', '\r', '\t', '\n',"'"), $html);
374 if (strlen($code) != 0 && $code[strlen($code) -1] != '.') {
377 $code .= $this->php_get_varname($value).'.';
380 if (!is_numeric($value)) {
381 throw new Exception("$value is not a valid number");
386 if (strlen($code) != 0) {
389 $code .= $this->php_generate_expr($op[$i]);
393 if (strlen($code) != 0) {
396 $code .= $this->php_generate_expr($value);
400 if (strlen($code) != 0) {
404 $code .= $this->php_generate_expr($value);
406 $code .= $this->php_generate_stmt(array($op[$i]['true']));
408 $code .= $this->php_generate_stmt(array($op[$i]['false']));
415 throw new Exception("Don't know how to declare {$key} = {$value} (".print_r($op[$i], TRUE));
419 if ($code != "" && $code[strlen($code)-1] == '.') {
420 $code = substr($code, 0, -1);
427 // php_print(array $op) {{{
429 * Return an echo of an stmt
433 protected function php_print($op)
435 return 'echo '.$this->php_generate_stmt($op).';';
439 // php_inc(array $op) {{{
441 * Return increment a variable ($var++)
445 protected function php_inc($op)
447 return $this->php_get_varname($op['name'])."++;";
451 // php_declare(array $op, $assign='=') {{{
453 * Return a variable declaration
457 protected function php_declare($op, $assign=' =')
459 $op['name'] = $this->php_get_varname($op['name']);
460 $code = "{$op['name']} {$assign} ".$this->php_generate_stmt($op).";";
465 // php_get_varname(mixed $var) {{{
473 protected function php_get_varname($var)
475 if (is_array($var)) {
476 if (!is_string($var[0])) {
477 if (count($var) == 1) {
478 return $this->php_get_varname($var[0]);
480 throw new Exception("Invalid variable definition ".print_r($var, TRUE));
483 $var_str = $this->php_get_varname($var[0]);
484 for ($i=1; $i < count($var); $i++
) {
486 if (is_string($var[$i])) {
487 $var_str .= '"'.$var[$i].'"';
488 } else if (is_array($var[$i])) {
489 if (isset($var[$i]['var'])) {
490 $var_str .= $this->php_get_varname($var[$i]['var']);
491 } else if (isset($var[$i]['string'])) {
492 $var_str .= '"'.addslashes($var[$i]['string']).'"';
504 // php_return($op) {{{
510 protected function php_return($op)
512 $code = "return ".$this->php_generate_stmt($op).";";
524 * vim600: sw=4 ts=4 fdm=marker