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 +---------------------------------------------------------------------------------+
39 * Simple AST (abstract syntax tree) helper class. This
40 * helps to generate array structure that is then translated by
41 * the Haanga_Generator class.
46 public $stack = array();
47 public $current = array();
48 public $doesPrint = FALSE;
53 * Return a refernce to the last element
61 if (count($this->stack
) == 0) {
64 return $this->stack
[count($this->stack
)-1];
69 static protected function check_type($obj, $type)
71 if (is_string($obj)) {
74 if (is_object($obj)) {
75 $obj = $obj->getArray();
77 return isset($obj[$type]);
80 public static function is_str($arr)
82 return self
::check_type($arr, 'string');
85 public static function is_var($arr)
87 return self
::check_type($arr, 'var');
90 public static function is_exec($arr)
92 return self
::check_type($arr, 'exec');
95 public static function is_expr($arr)
97 return self
::check_type($arr, 'op_expr');
101 function str($string)
103 return array("string" => $string);
106 function num($number)
108 return array("number" => $number);
111 function stack_size()
113 return count($this->stack
);
116 function append_ast(Haanga_AST
$obj)
120 $this->stack
= array_merge($this->stack
, $obj->stack
);
125 function constant($str)
127 return array('constant' => $str);
130 function comment($str)
132 $this->stack
[] = array("op" => "comment", 'comment' => $str);
137 function declare_function($name)
139 $this->stack
[] = array('op' => 'function', 'name' => $name);
144 function do_return($name)
146 $this->getValue($name, $expr);
147 $this->stack
[] = array('op' => 'return', $expr);
152 function do_if($expr)
154 $this->getValue($expr, $vexpr);
155 $this->stack
[] = array('op' => 'if', 'expr' => $vexpr);
162 $this->stack
[] = array('op' => 'else');
169 $this->stack
[] = array('op' => 'end_if');
174 function do_endfunction()
176 $this->stack
[] = array('op' => 'end_function');
184 foreach (func_get_args() as $id => $def) {
188 $this->getValue($def, $value);
192 $this->current
= array('var' => $var);
197 final function __get($property)
199 $property = strtolower($property);
200 if (isset($this->current
[$property])) {
201 return $this->current
[$property];
206 static function fromArrayGetAST($obj)
209 if ($obj InstanceOf $class) {
212 foreach (array('op_expr', 'expr_cond', 'exec', 'var', 'string', 'number', 'constant') as $type) {
213 if (isset($obj[$type])) {
215 $nobj->stack
[] = $obj;
221 static function getValue($obj, &$value, $get_all=FALSE)
225 if ($obj InstanceOf $class) {
226 $value = $obj->getArray($get_all);
227 } else if (is_string($obj)) {
228 $value = self
::str($obj);
229 } else if (is_numeric($obj) or $obj === 0) {
230 $value = self
::num($obj);
231 } else if ($obj === FALSE) {
232 $value = array('expr' => FALSE);
233 } else if ($obj === TRUE) {
234 $value = array('expr' => TRUE);
235 } else if (is_array($obj)) {
236 foreach (array('exec', 'var', 'string', 'number', 'constant') as $type) {
237 if (isset($obj[$type])) {
244 foreach($obj as $key => $value) {
245 if ($key === $first) {
249 $h->element($key, $value);
251 $value = $h->getArray();
252 } else if ($obj === NULL) {
256 throw new Exception("Imposible to get the value of the object");
260 function getArray($get_all=FALSE)
266 return isset($this->stack
[0]) ?
$this->stack
[0] : NULL;
269 function do_foreach($array, $value, $key, Haanga_AST
$body)
271 foreach (array('array', 'value', 'key') as $var) {
272 if ($
$var === NULL) {
276 if (is_string($var1)) {
279 if (is_object($var1)) {
280 $var1 = $var1->getArray();
282 $var1 = $var1['var'];
284 $def = array('op' => 'foreach', 'array' => $array, 'value' => $value);
288 $this->stack
[] = $def;
289 $this->stack
= array_merge($this->stack
, $body->getArray(TRUE));
290 $this->stack
[] = array('op' => 'end_foreach');
295 function do_echo($stmt)
297 $this->getValue($stmt, $value);
298 $this->stack
[] = array('op' => 'print', $value);
304 $params = func_get_args();
305 $exec = call_user_func_array('hexec', $params);
306 $this->stack
[] = array('op' => 'expr', $exec->getArray());
311 function exec($function)
313 $this->current
= array('exec' => $function, 'args' => array());
314 foreach (func_get_args() as $id => $param) {
316 $this->param($param);
322 function expr($operation, $term1, $term2=NULL)
324 $this->getValue($term1, $value1);
325 if ($term2 !== NULL) {
326 $this->getValue($term2, $value2);
330 $this->current
= array('op_expr' => $operation, $value1, $value2);
335 function expr_cond($expr, $if_true, $if_false)
337 $this->getValue($expr, $vExpr);
338 $this->getValue($if_true, $vIfTrue);
339 $this->getValue($if_false, $vIfFalse);
341 $this->current
= array('expr_cond' => $vExpr, 'true' => $vIfTrue, 'false' => $vIfFalse);
349 $this->current
= array('array' => array());
354 function element($key=NULL, $value)
356 $last = & $this->current
;
358 if (!isset($last['array'])) {
359 throw new Exception("Invalid call to element()");
362 $this->getValue($value, $val);
364 $this->getValue($key, $kval);
365 $val = array('key' => array($kval, $val));
367 $last['array'][] = $val;
370 function decl($name, $value)
372 if (is_string($name)) {
375 $this->getValue($name, $name);
376 $array = array('op' => 'declare', 'name' => $name['var']);
377 foreach (func_get_args() as $id => $value) {
379 $this->getValue($value, $stmt);
383 $this->stack
[] = $array;
387 function append($name, $value)
389 if (is_string($name)) {
392 $this->getValue($value, $stmt);
393 $this->getValue($name, $name);
394 $this->stack
[] = array('op' => 'append_var', 'name' => $name['var'], $stmt);
398 function param($param)
400 $last = & $this->current
;
402 if (!isset($last['exec'])) {
403 throw new Exception("Invalid call to param()");
406 $this->getValue($param, $value);
407 $last['args'][] = $value;
414 if (count($this->current
) > 0) {
415 $this->stack
[] = $this->current
;
416 $this->current
= array();
425 return new Haanga_AST
;
428 function hexpr($term1, $op='expr', $term2=NULL, $op2=NULL)
445 /* call recursive to resolve term2 */
446 $args = func_get_args();
447 $term2 = call_user_func_array('hexpr', array_slice($args, 2));
450 return $code->expr($op, $term1, $term2);
453 function hexpr_cond($expr, $if_true, $if_false)
456 $code->expr_cond($expr, $if_true, $if_false);
464 $args = func_get_args();
465 return call_user_func_array(array($code, 'exec'), $args);
468 function hconst($str)
470 return Haanga_AST
::Constant($str);
475 * Create the representation of a variable
481 $args = func_get_args();
482 return hvar_ex($args);
485 function hvar_ex($args)
488 return call_user_func_array(array($code, 'v'), $args);
497 * vim600: sw=4 ts=4 fdm=marker