1 %name PHP_Parser
2 %declare_class {class PHP_Parser}
3 
4 %syntax_error {
5 /* ?><?php */
6     echo "Syntax Error on line " . $this->lex->line . ": token '" .
7         $this->lex->value . "' while parsing rule:";
8     foreach ($this->yystack as $entry) {
9         echo $this->tokenName($entry->major) . ' ';
10     }
11     foreach ($this->yy_get_expected_tokens($yymajor) as $token) {
12         $expect[] = self::$yyTokenName[$token];
13     }
14     throw new Exception('Unexpected ' . $this->tokenName($yymajor) . '(' . $TOKEN
15         . '), expected one of: ' . implode(',', $expect));
16 }
17 %include_class {
18     static public $transTable = array();
19 
__construct()20     function __construct()
21     {
22         if (!count(self::$transTable)) {
23             $start = 240; // start nice and low to be sure
24             while (token_name($start) == 'UNKNOWN') {
25                 $start++;
26             }
27             $hash = array_flip(self::$yyTokenName);
28             $map =
29                 array(
30                     ord(',') => self::COMMA,
31                     ord('=') => self::EQUALS,
32                     ord('?') => self::QUESTION,
33                     ord(':') => self::COLON,
34                     ord('|') => self::BAR,
35                     ord('^') => self::CARAT,
36                     ord('&') => self::AMPERSAND,
37                     ord('<') => self::LESSTHAN,
38                     ord('>') => self::GREATERTHAN,
39                     ord('+') => self::PLUS,
40                     ord('-') => self::MINUS,
41                     ord('.') => self::DOT,
42                     ord('*') => self::TIMES,
43                     ord('/') => self::DIVIDE,
44                     ord('%') => self::PERCENT,
45                     ord('!') => self::EXCLAM,
46                     ord('~') => self::TILDE,
47                     ord('@') => self::AT,
48                     ord('[') => self::LBRACKET,
49                     ord('(') => self::LPAREN,
50                     ord(')') => self::RPAREN,
51                     ord(';') => self::SEMI,
52                     ord('{') => self::LCURLY,
53                     ord('}') => self::RCURLY,
54                     ord('`') => self::BACKQUOTE,
55                     ord('$') => self::DOLLAR,
56                     ord(']') => self::RBRACKET,
57                     ord('"') => self::DOUBLEQUOTE,
58                     ord("'") => self::SINGLEQUOTE,
59                 );
60             for ($i = $start; $i < self::YYERRORSYMBOL + $start; $i++) {
61                 $lt = token_name($i);
62                 $lt = ($lt == 'T_DOUBLE_COLON') ?  'T_PAAMAYIM_NEKUDOTAYIM' : $lt;
63 //                echo "$lt has hash? ".$hash[$lt]."\n";
64                 if (!isset($hash[$lt])) {
65                     continue;
66                 }
67 
68                 //echo "compare $lt with {$tokens[$i]}\n";
69                 $map[$i] = $hash[$lt];
70             }
71             //print_r($map);
72             // set the map to false if nothing in there.
73             self::$transTable = $map;
74         }
75     }
76 
77     public $data;
78 }
79 
80 %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE.
81 %left COMMA.
82 %left T_LOGICAL_OR.
83 %left T_LOGICAL_XOR.
84 %left T_LOGICAL_AND.
85 %right T_PRINT.
86 %left EQUALS T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL.
87 %left QUESTION COLON.
88 %left T_BOOLEAN_OR.
89 %left T_BOOLEAN_AND.
90 %left BAR.
91 %left CARAT.
92 %left AMPERSAND.
93 %nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL.
94 %nonassoc LESSTHAN T_IS_SMALLER_OR_EQUAL GREATERTHAN T_IS_GREATER_OR_EQUAL.
95 %left T_SL T_SR.
96 %left PLUS MINUS DOT.
97 %left TIMES DIVIDE PERCENT.
98 %right EXCLAM.
99 %nonassoc T_INSTANCEOF.
100 %right TILDE T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST AT.
101 %right LBRACKET.
102 %nonassoc T_NEW T_CLONE.
103 %left T_ELSEIF.
104 %left T_ELSE.
105 %left T_ENDIF.
106 %right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC.
107 
108 %extra_argument {$lex}
109 
110 %parse_accept {
111     var_dump($this->data);
112 }
113 
top_statement_list(B)114 start ::= top_statement_list(B). {$this->data = B->metadata;}
115 
top_statement_list(A)116 top_statement_list(A) ::= top_statement_list(B) top_statement(C). {
117     A = B;
118     A[] = C;
119 }
top_statement_list(A)120 top_statement_list(A) ::= . {A = new PHP_ParseryyToken('');}
121 
top_statement(A)122 top_statement(A) ::= statement(B). {A = B;}
top_statement(A)123 top_statement(A) ::= function_declaration_statement(B). {A = B;}
top_statement(A)124 top_statement(A) ::= class_declaration_statement(B). {A = B;}
125 top_statement ::= T_HALT_COMPILER LPAREN RPAREN SEMI. { $this->lex->haltParsing(); }
126 
statement(A)127 statement(A) ::= unticked_statement(B). {A = B;}
128 
unticked_statement(A)129 unticked_statement(A) ::= LCURLY inner_statement_list(B) RCURLY. {A = B;}
unticked_statement(A)130 unticked_statement(A) ::= T_IF LPAREN expr(E) RPAREN statement(I) elseif_list(EL) else_single(ELL). {
131     A = new PHP_ParseryyToken('');
132     A[] = E;
133     A[] = I;
134     A[] = EL;
135     A[] = ELL;
136 }
unticked_statement(A)137 unticked_statement(A) ::= T_IF LPAREN expr(E) RPAREN COLON inner_statement_list(I) new_elseif_list(EL) new_else_single(ELL) T_ENDIF SEMI. {
138     A = new PHP_ParseryyToken('if (' . E->string . '):' . I->string . EL->string . ELL->string . 'endif;');
139     A[] = E;
140     A[] = I;
141     A[] = EL;
142     A[] = ELL;
143 }
unticked_statement(A)144 unticked_statement(A) ::= T_WHILE LPAREN expr(B) RPAREN while_statement(C). {
145     A = new PHP_ParseryyToken('');
146     A[] = B;
147     A[] = C;
148 }
unticked_statement(A)149 unticked_statement(A) ::= T_DO statement(B) T_WHILE LPAREN expr(C) RPAREN SEMI. {
150     A = new PHP_ParseryyToken('');
151     A[] = B;
152     A[] = C;
153 }
unticked_statement(A)154 unticked_statement(A) ::= T_FOR
155 			LPAREN
156 				for_expr(B)
157 			COLON
158 				for_expr(C)
159 			SEMI
160 				for_expr(D)
161 			RPAREN
162 			for_statement(E). {
163     A = new PHP_ParseryyToken('');
164     A[] = B;
165     A[] = C;
166     A[] = D;
167     A[] = E;
168 }
unticked_statement(A)169 unticked_statement(A) ::= T_SWITCH LPAREN expr(B) RPAREN switch_case_list(C). {
170     A = new PHP_ParseryyToken('');
171     A[] = B;
172     A[] = C;
173 }
174 unticked_statement ::= T_BREAK SEMI.
unticked_statement(A)175 unticked_statement(A) ::= T_BREAK expr(B) SEMI. {
176     A = new PHP_ParseryyToken('');
177     A[] = B;
178 }
179 unticked_statement ::= T_CONTINUE SEMI.
unticked_statement(A)180 unticked_statement(A) ::= T_CONTINUE expr(B) SEMI. {
181     A = new PHP_ParseryyToken('', B);
182 }
183 unticked_statement ::= T_RETURN SEMI.
unticked_statement(A)184 unticked_statement(A) ::= T_RETURN expr_without_variable(B) SEMI. {
185     A = new PHP_ParseryyToken('return ' . B->string . ';', B);
186 }
unticked_statement(A)187 unticked_statement(A) ::= T_RETURN variable(B) SEMI. {
188     A = new PHP_ParseryyToken('return ' . B->string . ';', B);
189 }
unticked_statement(A)190 unticked_statement(A) ::= T_GLOBAL global_var_list(B) SEMI. {A = B;}
unticked_statement(A)191 unticked_statement(A) ::= T_STATIC static_var_list(B) SEMI. {A = B;}
unticked_statement(A)192 unticked_statement(A) ::= T_ECHO echo_expr_list(B) SEMI. {
193     A = new PHP_ParseryyToken('', B);
194 }
195 unticked_statement ::= T_INLINE_HTML.
unticked_statement(A)196 unticked_statement(A) ::= expr(B) SEMI. {A = B;}
unticked_statement(A)197 unticked_statement(A) ::= T_USE use_filename(B) SEMI. {
198     A = new PHP_ParseryyToken('', array('uses' => B));
199     // not that "uses" would actually work in real life
200 }
unticked_statement(A)201 unticked_statement(A) ::= T_UNSET LPAREN unset_variables(B) LPAREN SEMI. {
202     A = new PHP_ParseryyToken('', B);
203 }
unticked_statement(A)204 unticked_statement(A) ::= T_FOREACH LPAREN variable(B) T_AS
205 		foreach_variable foreach_optional_arg RPAREN
206 		foreach_statement(C). {
207     A = new PHP_ParseryyToken('', B);
208     A[] = C;
209 }
unticked_statement(A)210 unticked_statement(A) ::= T_FOREACH LPAREN expr_without_variable(B) T_AS
211 		w_variable foreach_optional_arg RPAREN
212 		foreach_statement(C). {
213     A = new PHP_ParseryyToken('', B);
214     A[] = C;
215 }
unticked_statement(A)216 unticked_statement(A) ::= T_DECLARE LPAREN declare_list(B) RPAREN declare_statement(C). {
217     A = new PHP_ParseryyToken('', B);
218     A[] = C;
219 }
220 unticked_statement ::= SEMI.
unticked_statement(A)221 unticked_statement(A) ::= T_TRY LCURLY inner_statement_list(B) RCURLY
222 		T_CATCH LPAREN
223 		fully_qualified_class_name(C)
224 		T_VARIABLE RPAREN
225 		LCURLY inner_statement_list(D) RCURLY
226 		additional_catches(E). {
227     A = new PHP_ParseryyToken('',
228         array(
229             'catches' => C,
230         ));
231     A[] = B;
232     A[] = D;
233     A[] = E;
234 }
unticked_statement(A)235 unticked_statement(A) ::= T_THROW expr(B) SEMI. {
236     if (B->metadata && isset(B->metadata[0]) && isset(B->metadata[0]['uses']) &&
237           B->metadata[0]['uses'] === 'class') {
238         A = new PHP_ParseryyToken('throw ' . B->string, array('throws' => B->metadata[0]['name']));
239     } else {
240         A = new PHP_ParseryyToken('throw ' . B->string);
241         A[] = B;
242     }
243 }
244 
additional_catches(A)245 additional_catches(A) ::= non_empty_additional_catches(B). {A = B;}
246 additional_catches ::= .
247 
non_empty_additional_catches(A)248 non_empty_additional_catches(A) ::= additional_catch(B). {A = B;}
non_empty_additional_catches(A)249 non_empty_additional_catches(A) ::= non_empty_additional_catches(B) additional_catch(C). {
250     A = B;
251     A[] = C;
252 }
253 
additional_catch(A)254 additional_catch(A) ::= T_CATCH LPAREN fully_qualified_class_name(B) T_VARIABLE RPAREN LCURLY inner_statement_list(C) RCURLY. {
255     A = new PHP_ParseryyToken('', C);
256     A[] = array('catches' => B);
257 }
258 
inner_statement_list(A)259 inner_statement_list(A) ::= inner_statement_list(B) inner_statement(C). {
260     A = B;
261     A[] = C;
262 }
inner_statement_list(A)263 inner_statement_list(A) ::= . {A = new PHP_ParseryyToken('');}
264 
inner_statement(A)265 inner_statement(A) ::= statement(B). {
266     A = new PHP_ParseryyToken(B);
267 }
inner_statement(A)268 inner_statement(A) ::= function_declaration_statement(B). {
269     A = new PHP_ParseryyToken(B);
270 }
inner_statement(A)271 inner_statement(A) ::= class_declaration_statement(B). {
272     A = new PHP_ParseryyToken(B);
273 }
274 inner_statement ::= T_HALT_COMPILER LPAREN RPAREN SEMI. { $this->lex->haltParsing(); }
275 
function_declaration_statement(A)276 function_declaration_statement(A) ::= unticked_function_declaration_statement(B). {
277     A = new PHP_ParseryyToken(B);
278 }
279 
class_declaration_statement(A)280 class_declaration_statement(A) ::= unticked_class_declaration_statement(B). {
281     A = new PHP_ParseryyToken(B);
282 }
283 
unticked_function_declaration_statement(A)284 unticked_function_declaration_statement(A) ::=
285 		T_FUNCTION is_reference(ref) T_STRING(funcname) LPAREN parameter_list(params) RPAREN
286 		LCURLY inner_statement_list(funcinfo) RCURLY. {
287 	A = new PHP_ParseryyToken('function ' . (ref ? '&' : '') .
288 	   funcname . '(' . params->string . ')');
289     A[] = array(
290         'type' => 'function',
291         'returnsref' => ref,
292         'name' => funcname,
293         'parameters' => params->metadata,
294         'info' => funcinfo->metadata,
295     );
296 }
297 
unticked_class_declaration_statement(A)298 unticked_class_declaration_statement(A) ::=
299 		class_entry_type(classtype) T_STRING(C) extends_from(ext)
300 			implements_list(impl)
301 			LCURLY
302 				class_statement_list(cinfo)
303 			RCURLY. {
304 	A = new PHP_ParseryyToken('', array(
305 	   'type' => classtype['type'],
306 	   'modifiers' => classtype['modifiers'],
307 	   'name' => C,
308 	   'extends' => ext,
309 	   'implements' => impl,
310 	   'info' => cinfo->metadata,
311 	));
312 }
313 unticked_class_declaration_statement ::=
314 		interface_entry T_STRING
315 			interface_extends_list
316 			LCURLY
317 				class_statement_list
318 			RCURLY.
319 
class_entry_type(A)320 class_entry_type(A) ::= T_CLASS. { A = new PHP_ParseryyToken('', array('type' => 'class', 'modifiers' => array())); }
class_entry_type(A)321 class_entry_type(A) ::= T_ABSTRACT T_CLASS. {
322     A = new PHP_ParseryyToken('', array('type' => 'class', 'modifiers' => array('abstract')));
323 }
class_entry_type(A)324 class_entry_type(A) ::= T_FINAL T_CLASS. {
325     A = new PHP_ParseryyToken('', array('type' => 'class', 'modifiers' => array('final')));
326 }
327 
extends_from(A)328 extends_from(A) ::= T_EXTENDS fully_qualified_class_name(B). {A = new PHP_ParseryyToken(B, array(B));}
extends_from(A)329 extends_from(A) ::= . {A = new PHP_ParseryyToken('');}
330 
331 interface_entry ::= T_INTERFACE.
332 
333 interface_extends_list ::= T_EXTENDS interface_list.
334 interface_extends_list ::= .
335 
implements_list(A)336 implements_list(A) ::= . {A = new PHP_ParseryyToken('');}
implements_list(A)337 implements_list(A) ::= T_IMPLEMENTS interface_list(B). {A = B;}
338 
interface_list(A)339 interface_list(A) ::= fully_qualified_class_name(B). {A = new PHP_ParseryyToken('', array(B));}
interface_list(A)340 interface_list(A) ::= interface_list(list) COMMA fully_qualified_class_name(B). {
341     A = list;
342     A[] = B;
343 }
344 
expr(A)345 expr(A) ::= r_variable(B). {A = B;}
expr(A)346 expr(A) ::= expr_without_variable(B). {A = B;}
347 
expr_without_variable(A)348 expr_without_variable(A) ::= T_LIST LPAREN assignment_list(B) RPAREN EQUALS expr(C). {
349     A = new PHP_ParseryyToken('list(' . B->string . ') = ' . C->string, B);
350     A[] = C;
351 }
expr_without_variable(A)352 expr_without_variable(A) ::= variable(VAR) EQUALS expr(E). {
353     if ($this->lex->globalSearch(VAR->string)) {
354         A = new PHP_ParseryyToken(VAR->string . ' = ' . E->string,
355             array(
356                 'type' => 'global',
357                 'name' => VAR->string,
358                 'default' => E->string,
359             ));
360         A[] = VAR;
361         A[] = E;
362     } else {
363         A = new PHP_ParseryyToken(VAR->string . ' = ' . E->string, VAR);
364         A[] = E;
365     }
366 }
expr_without_variable(A)367 expr_without_variable(A) ::= variable(VAR) EQUALS AMPERSAND variable(E).{
368     if ($this->lex->globalSearch(VAR->string)) {
369         A = new PHP_ParseryyToken(VAR->string . ' = ' . E->string,
370             array(
371                 'type' => 'global',
372                 'name' => VAR->string,
373                 'default' => '&' . E->string,
374             ));
375         A[] = VAR;
376         A[] = E;
377     } else {
378         A = new PHP_ParseryyToken(VAR->string . ' = &' . E->string, VAR);
379         A[] = E;
380     }
381 }
382 
expr_without_variable(A)383 expr_without_variable(A) ::= variable(VAR) EQUALS AMPERSAND T_NEW class_name_reference(CL) ctor_arguments(ARGS). {
384     $c = is_string(CL) ? CL : CL->string;
385     if ($this->lex->globalSearch(VAR->string)) {
386         A = new PHP_ParseryyToken(VAR->string . ' = &new ' . $c . ARGS->string,
387             array(
388                 'type' => 'global',
389                 'name' => VAR->string,
390                 'default' => '&new ' . CL->string . ARGS->string,
391             ));
392         A[] = VAR;
393     } else {
394         A = new PHP_ParseryyToken(VAR->string . ' = &new ' . $c . ARGS->string, VAR);
395     }
396     if (is_string(CL)) {
397         A[] = array('usedclass' => CL);
398     }
399     A[] = ARGS;
400 }
expr_without_variable(A)401 expr_without_variable(A) ::= T_NEW class_name_reference(B) ctor_arguments(C). {
402     $b = is_string(B) ? B : B->string;
403     A = new PHP_ParseryyToken('new ' . $b . C->string, B);
404     A[] = C;
405     if (is_string(B)) {
406         A[] = array('uses' => 'class', 'name' => B);
407     }
408 }
expr_without_variable(A)409 expr_without_variable(A) ::= T_CLONE expr(B). {
410     A = new PHP_ParseryyToken('clone ' . B->string, B);
411 }
expr_without_variable(A)412 expr_without_variable(A) ::= variable(B) T_PLUS_EQUAL expr(C). {
413     A = new PHP_ParseryyToken(B->string . ' += ' . C->string, B);
414     A[] = C;
415 }
expr_without_variable(A)416 expr_without_variable(A) ::= variable(B) T_MINUS_EQUAL expr(C). {
417     A = new PHP_ParseryyToken(B->string . ' -= ' . C->string, B);
418     A[] = C;
419 }
420 
expr_without_variable(A)421 expr_without_variable(A) ::= variable(B) T_MUL_EQUAL expr(C). {
422     A = new PHP_ParseryyToken(B->string . ' *= ' . C->string, B);
423     A[] = C;
424 }
425 
expr_without_variable(A)426 expr_without_variable(A) ::= variable(B) T_DIV_EQUAL expr(C). {
427     A = new PHP_ParseryyToken(B->string . ' /= ' . C->string, B);
428     A[] = C;
429 }
430 
expr_without_variable(A)431 expr_without_variable(A) ::= variable(B) T_CONCAT_EQUAL expr(C). {
432     A = new PHP_ParseryyToken(B->string . ' .= ' . C->string, B);
433     A[] = C;
434 }
435 
expr_without_variable(A)436 expr_without_variable(A) ::= variable(B) T_MOD_EQUAL expr(C). {
437     A = new PHP_ParseryyToken(B->string . ' %= ' . C->string, B);
438     A[] = C;
439 }
440 
expr_without_variable(A)441 expr_without_variable(A) ::= variable(B) T_AND_EQUAL expr(C). {
442     A = new PHP_ParseryyToken(B->string . ' &= ' . C->string, B);
443     A[] = C;
444 }
445 
expr_without_variable(A)446 expr_without_variable(A) ::= variable(B) T_OR_EQUAL expr(C). {
447     A = new PHP_ParseryyToken(B->string . ' |= ' . C->string, B);
448     A[] = C;
449 }
450 
expr_without_variable(A)451 expr_without_variable(A) ::= variable(B) T_XOR_EQUAL expr(C). {
452     A = new PHP_ParseryyToken(B->string . ' ^= ' . C->string, B);
453     A[] = C;
454 }
455 
expr_without_variable(A)456 expr_without_variable(A) ::= variable(B) T_SL_EQUAL expr(C). {
457     A = new PHP_ParseryyToken(B->string . ' <<= ' . C->string, B);
458     A[] = C;
459 }
460 
expr_without_variable(A)461 expr_without_variable(A) ::= variable(B) T_SR_EQUAL expr(C). {
462     A = new PHP_ParseryyToken(B->string . ' >>= ' . C->string, B);
463     A[] = C;
464 }
465 
expr_without_variable(A)466 expr_without_variable(A) ::= rw_variable(B) T_INC. {
467     A = new PHP_ParseryyToken(B->string . '++', B);
468 }
expr_without_variable(A)469 expr_without_variable(A) ::= T_INC rw_variable(B). {
470     A = new PHP_ParseryyToken('++' . B->string, B);
471 }
expr_without_variable(A)472 expr_without_variable(A) ::= rw_variable(B) T_DEC. {
473     A = new PHP_ParseryyToken(B->string . '--', B);
474 }
expr_without_variable(A)475 expr_without_variable(A) ::= T_DEC rw_variable(B). {
476     A = new PHP_ParseryyToken('--' . B->string, B);
477 }
expr_without_variable(A)478 expr_without_variable(A) ::= expr(B) T_BOOLEAN_OR expr(C). {
479     A = new PHP_ParseryyToken(B->string . ' || ' . C->string, B);
480     A[] = C;
481 }
expr_without_variable(A)482 expr_without_variable(A) ::= expr(B) T_BOOLEAN_AND expr(C). {
483     A = new PHP_ParseryyToken(B->string . ' && ' . C->string, B);
484     A[] = C;
485 }
expr_without_variable(A)486 expr_without_variable(A) ::= expr(B) T_LOGICAL_OR expr(C). {
487     A = new PHP_ParseryyToken(B->string . ' OR ' . C->string, B);
488     A[] = C;
489 }
expr_without_variable(A)490 expr_without_variable(A) ::= expr(B) T_LOGICAL_AND expr(C). {
491     A = new PHP_ParseryyToken(B->string . ' AND ' . C->string, B);
492     A[] = C;
493 }
expr_without_variable(A)494 expr_without_variable(A) ::= expr(B) T_LOGICAL_XOR expr(C). {
495     A = new PHP_ParseryyToken(B->string . ' XOR ' . C->string, B);
496     A[] = C;
497 }
expr_without_variable(A)498 expr_without_variable(A) ::= expr(B) BAR expr(C). {
499     A = new PHP_ParseryyToken(B->string . ' | ' . C->string, B);
500     A[] = C;
501 }
expr_without_variable(A)502 expr_without_variable(A) ::= expr(B) AMPERSAND expr(C). {
503     A = new PHP_ParseryyToken(B->string . ' & ' . C->string, B);
504     A[] = C;
505 }
expr_without_variable(A)506 expr_without_variable(A) ::= expr(B) CARAT expr(C). {
507     A = new PHP_ParseryyToken(B->string . ' ^ ' . C->string, B);
508     A[] = C;
509 }
expr_without_variable(A)510 expr_without_variable(A) ::= expr(B) DOT expr(C). {
511     A = new PHP_ParseryyToken(B->string . ' . ' . C->string, B);
512     A[] = C;
513 }
expr_without_variable(A)514 expr_without_variable(A) ::= expr(B) PLUS expr(C). {
515     A = new PHP_ParseryyToken(B->string . ' + ' . C->string, B);
516     A[] = C;
517 }
expr_without_variable(A)518 expr_without_variable(A) ::= expr(B) MINUS expr(C). {
519     A = new PHP_ParseryyToken(B->string . ' - ' . C->string, B);
520     A[] = C;
521 }
expr_without_variable(A)522 expr_without_variable(A) ::= expr(B) TIMES expr(C). {
523     A = new PHP_ParseryyToken(B->string . ' * ' . C->string, B);
524     A[] = C;
525 }
expr_without_variable(A)526 expr_without_variable(A) ::= expr(B) DIVIDE expr(C). {
527     A = new PHP_ParseryyToken(B->string . ' / ' . C->string, B);
528     A[] = C;
529 }
expr_without_variable(A)530 expr_without_variable(A) ::= expr(B) PERCENT expr(C). {
531     A = new PHP_ParseryyToken(B->string . ' % ' . C->string, B);
532     A[] = C;
533 }
expr_without_variable(A)534 expr_without_variable(A) ::= expr(B) T_SL expr(C). {
535     A = new PHP_ParseryyToken(B->string . ' << ' . C->string, B);
536     A[] = C;
537 }
expr_without_variable(A)538 expr_without_variable(A) ::= expr(B) T_SR expr(C). {
539     A = new PHP_ParseryyToken(B->string . ' >> ' . C->string, B);
540     A[] = C;
541 }
expr_without_variable(A)542 expr_without_variable(A) ::= PLUS expr(B). {
543     A = new PHP_ParseryyToken('+' . B->string, B);
544 }
expr_without_variable(A)545 expr_without_variable(A) ::= MINUS expr(B). {
546     A = new PHP_ParseryyToken('-' . B->string, B);
547 }
expr_without_variable(A)548 expr_without_variable(A) ::= EXCLAM expr(B). {
549     A = new PHP_ParseryyToken('!' . B->string, B);
550 }
expr_without_variable(A)551 expr_without_variable(A) ::= TILDE expr(B). {
552     A = new PHP_ParseryyToken('~' . B->string, B);
553 }
expr_without_variable(A)554 expr_without_variable(A) ::= expr(B) T_IS_IDENTICAL expr(C). {
555     A = new PHP_ParseryyToken(B->string . ' === ' . C->string, B);
556     A[] = C;
557 }
expr_without_variable(A)558 expr_without_variable(A) ::= expr(B) T_IS_NOT_IDENTICAL expr(C). {
559     A = new PHP_ParseryyToken(B->string . ' !== ' . C->string, B);
560     A[] = C;
561 }
expr_without_variable(A)562 expr_without_variable(A) ::= expr(B) T_IS_EQUAL expr(C). {
563     A = new PHP_ParseryyToken(B->string . ' == ' . C->string, B);
564     A[] = C;
565 }
expr_without_variable(A)566 expr_without_variable(A) ::= expr(B) T_IS_NOT_EQUAL expr(C). {
567     A = new PHP_ParseryyToken(B->string . ' != ' . C->string, B);
568     A[] = C;
569 }
expr_without_variable(A)570 expr_without_variable(A) ::= expr(B) LESSTHAN expr(C). {
571     A = new PHP_ParseryyToken(B->string . ' < ' . C->string, B);
572     A[] = C;
573 }
expr_without_variable(A)574 expr_without_variable(A) ::= expr(B) T_IS_SMALLER_OR_EQUAL expr(C). {
575     A = new PHP_ParseryyToken(B->string . ' <= ' . C->string, B);
576     A[] = C;
577 }
expr_without_variable(A)578 expr_without_variable(A) ::= expr(B) GREATERTHAN expr(C). {
579     A = new PHP_ParseryyToken(B->string . ' > ' . C->string, B);
580     A[] = C;
581 }
expr_without_variable(A)582 expr_without_variable(A) ::= expr(B) T_IS_GREATER_OR_EQUAL expr(C). {
583     A = new PHP_ParseryyToken(B->string . ' >= ' . C->string, B);
584     A[] = C;
585 }
expr_without_variable(A)586 expr_without_variable(A) ::= expr(B) T_INSTANCEOF class_name_reference(CL). {
587     $c = is_string(CL) ? CL : CL->string;
588     A = new PHP_ParseryyToken(B->string . ' instanceof ' . $c, B);
589     if (!is_string(CL)) {
590         A[] = CL;
591     }
592 }
expr_without_variable(A)593 expr_without_variable(A) ::= LPAREN expr(B) RPAREN. {
594     A = new PHP_ParseryyToken('(' . B->string . ')', B);
595 }
expr_without_variable(A)596 expr_without_variable(A) ::= expr(B) QUESTION
597 		expr(C) COLON
598 		expr(D). {
599     A = new PHP_ParseryyToken(B->string . ' ? ' . C->string . ' : ' . D->string, B);
600     A[] = C;
601     A[] = D;
602 }
expr_without_variable(A)603 expr_without_variable(A) ::= internal_functions_in_yacc(B). {A = B;}
expr_without_variable(A)604 expr_without_variable(A) ::= T_INT_CAST expr(B). {
605     A = new PHP_ParseryyToken('(int) ' . B->string, B);
606 }
expr_without_variable(A)607 expr_without_variable(A) ::= T_DOUBLE_CAST expr(B). {
608     A = new PHP_ParseryyToken('(double) ' . B->string, B);
609 }
expr_without_variable(A)610 expr_without_variable(A) ::= T_STRING_CAST expr(B). {
611     A = new PHP_ParseryyToken('(string) ' . B->string, B);
612 }
expr_without_variable(A)613 expr_without_variable(A) ::= T_ARRAY_CAST expr(B). {
614     A = new PHP_ParseryyToken('(array) ' . B->string, B);
615 }
expr_without_variable(A)616 expr_without_variable(A) ::= T_OBJECT_CAST expr(B). {
617     A = new PHP_ParseryyToken('(object) ' . B->string, B);
618 }
expr_without_variable(A)619 expr_without_variable(A) ::= T_BOOL_CAST expr(B). {
620     A = new PHP_ParseryyToken('(bool) ' . B->string, B);
621 }
expr_without_variable(A)622 expr_without_variable(A) ::= T_UNSET_CAST expr(B). {
623     A = new PHP_ParseryyToken('(unset) ' . B->string, B);
624 }
expr_without_variable(A)625 expr_without_variable(A) ::= T_EXIT exit_expr(B). {
626     A = new PHP_ParseryyToken('exit ' . B->string, B);
627 }
expr_without_variable(A)628 expr_without_variable(A) ::= AT expr(B). {
629     A = new PHP_ParseryyToken('@' . B->string, B);
630 }
expr_without_variable(A)631 expr_without_variable(A) ::= scalar(B). {
632     A = new PHP_ParseryyToken(B->string, B);
633 }
expr_without_variable(A)634 expr_without_variable(A) ::= expr_without_variable_t_array LPAREN array_pair_list(B) RPAREN. {
635     A = new PHP_ParseryyToken('array(' . B->string . ')', B);
636 }
expr_without_variable(A)637 expr_without_variable(A) ::= BACKQUOTE encaps_list(B) BACKQUOTE. {
638     A = new PHP_ParseryyToken('`' . B->string . '`');
639 }
expr_without_variable(A)640 expr_without_variable(A) ::= T_PRINT expr(B). {
641     A = new PHP_ParseryyToken('print ' . B->string, B);
642 }
643 
644 expr_without_variable_t_array ::= T_ARRAY. {$this->lex->trackWhitespace();}
645 
exit_expr(A)646 exit_expr(A) ::= LPAREN RPAREN. {A = new PHP_ParseryyToken('()');}
exit_expr(A)647 exit_expr(A) ::= LPAREN expr(B) RPAREN. {A = new PHP_ParseryyToken('(' . B->string . ')', B);}
exit_expr(A)648 exit_expr(A) ::= . {A = new PHP_ParseryyToken('');}
649 
650 common_scalar(A) ::=
651 		T_LNUMBER
652 	   |T_DNUMBER
653 	   |T_CONSTANT_ENCAPSED_STRING
654 	   |T_LINE
655 	   |T_FILE
656 	   |T_CLASS_C
657 	   |T_METHOD_C
658 	   |T_FUNC_C(B). {A = B;}
659 
660 /* compile-time evaluated scalars */
static_scalar(A)661 static_scalar(A) ::= common_scalar(B). {A = B;}
static_scalar(A)662 static_scalar(A) ::= T_STRING(B). {A = B;}
static_scalar(A)663 static_scalar(A) ::= static_scalar_t_array(B) LPAREN(C) static_array_pair_list(D) RPAREN(E). {
664     A = B . C . D . E;
665     // have to do all because of nested arrays
666     $this->lex->stopTrackingWhitespace(); // we only need whitespace for
667                                           // array default values
668 }
static_scalar(A)669 static_scalar(A) ::= static_class_constant(B). {A = B;}
670 
static_scalar_t_array(A)671 static_scalar_t_array(A) ::= T_ARRAY(B). {
672     $this->lex->trackWhitespace();
673     A = B;
674 }
675 
static_array_pair_list(A)676 static_array_pair_list(A) ::= non_empty_static_array_pair_list(B). {A = B;}
static_array_pair_list(A)677 static_array_pair_list(A) ::= non_empty_static_array_pair_list(B) COMMA(C). {
678     A = B . C;
679 }
static_array_pair_list(A)680 static_array_pair_list(A) ::= . {A = '';}
681 
non_empty_static_array_pair_list(A)682 non_empty_static_array_pair_list(A) ::= non_empty_static_array_pair_list(B) COMMA(C) static_scalar(D) T_DOUBLE_ARROW(E) static_scalar(F). {
683     A = B . C . D . E . F;
684 }
non_empty_static_array_pair_list(A)685 non_empty_static_array_pair_list(A) ::= non_empty_static_array_pair_list(B) COMMA(C) static_scalar(D). {
686     A = B . C . D;
687 }
non_empty_static_array_pair_list(A)688 non_empty_static_array_pair_list(A) ::= static_scalar(B) T_DOUBLE_ARROW(C) static_scalar(D). {
689     A = B . C . D;
690 }
non_empty_static_array_pair_list(A)691 non_empty_static_array_pair_list(A) ::= static_scalar(B). {A = B;}
692 
static_class_constant(A)693 static_class_constant(A) ::= T_STRING(B) T_PAAMAYIM_NEKUDOTAYIM T_STRING(C). {
694     A = B . '::' . C;
695 }
696 
697 foreach_optional_arg ::= T_DOUBLE_ARROW foreach_variable.
698 foreach_optional_arg ::= .
699 
700 foreach_variable ::= w_variable.
701 foreach_variable ::= AMPERSAND w_variable.
702 
for_statement(A)703 for_statement(A) ::= statement(B). {A = B;}
for_statement(A)704 for_statement(A) ::= COLON inner_statement_list(B) T_ENDFOR SEMI. {A = B;}
705 
foreach_statement(A)706 foreach_statement(A) ::= statement(B). {A = B;}
foreach_statement(A)707 foreach_statement(A) ::= COLON inner_statement_list(B) T_ENDFOREACH SEMI. {A = B;}
708 
709 
declare_statement(A)710 declare_statement(A) ::= statement(B). {A = B;}
declare_statement(A)711 declare_statement(A) ::= COLON inner_statement_list(B) T_ENDDECLARE SEMI. {A = B;}
712 
declare_list(A)713 declare_list(A) ::= T_STRING(B) EQUALS static_scalar(C). {
714     A = new PHP_ParseryyToken(B . ' = ' . C, array('declare' => B, 'default' => C));
715 }
declare_list(A)716 declare_list(A) ::= declare_list(DEC) COMMA T_STRING(B) EQUALS static_scalar(C). {
717     A = new PHP_ParseryyToken(DEC->string . ', ' . B . ' = ' . C, DEC);
718     A[] = array('declare' => B, 'default' => C);
719 }
720 
switch_case_list(A)721 switch_case_list(A) ::= LCURLY case_list(B) RCURLY. {A = B;}
switch_case_list(A)722 switch_case_list(A) ::= LCURLY SEMI case_list(B) RCURLY. {A = B;}
switch_case_list(A)723 switch_case_list(A) ::= COLON case_list(B) T_ENDSWITCH SEMI. {A = B;}
switch_case_list(A)724 switch_case_list(A) ::= COLON SEMI case_list(B) T_ENDSWITCH SEMI. {A = B;}
725 
case_list(A)726 case_list(A) ::= case_list(LIST) T_CASE expr(B) case_separator. {
727     A = LIST;
728     A[] = B;
729 }
case_list(A)730 case_list(A) ::= case_list(LIST) T_DEFAULT case_separator inner_statement_list(B). {
731     A = LIST;
732     A[] = B;
733 }
case_list(A)734 case_list(A) ::= . {A = new PHP_ParseryyToken('');}
735 
736 case_separator ::= COLON|SEMI.
737 
738 while_statement(A) ::= statement(B). {A = B;}
while_statement(A)739 while_statement(A) ::= COLON inner_statement_list(B) T_ENDWHILE SEMI. {A = B;}
740 
elseif_list(A)741 elseif_list(A) ::= elseif_list(B) T_ELSEIF LPAREN expr(C) RPAREN statement(D). {
742     A = B;
743     A[] = C;
744     A[] = D;
745 }
elseif_list(A)746 elseif_list(A) ::= . {A = new PHP_ParseryyToken('');}
747 
new_elseif_list(A)748 new_elseif_list(A) ::= new_elseif_list(B) T_ELSEIF LPAREN expr(C) RPAREN COLON inner_statement_list(D) . {
749     A = B;
750     A[] = C;
751     A[] = D;
752 }
new_elseif_list(A)753 new_elseif_list(A) ::= . {A = new PHP_ParseryyToken('');}
754 
else_single(A)755 else_single(A) ::= T_ELSE statement(B). {A = B;}
else_single(A)756 else_single(A) ::= . {A = new PHP_ParseryyToken('');}
757 
new_else_single(A)758 new_else_single(A) ::= T_ELSE COLON inner_statement_list(B). {A = B;}
new_else_single(A)759 new_else_single(A) ::= . {A = new PHP_ParseryyToken('');}
760 
parameter_list(A)761 parameter_list(A) ::= non_empty_parameter_list(B). {A = B;}
parameter_list(A)762 parameter_list(A) ::= . {A = new PHP_ParseryyToken('');}
763 
non_empty_parameter_list(A)764 non_empty_parameter_list(A) ::= optional_class_type(T) T_VARIABLE(V). {
765     A = new PHP_ParseryyToken(T . V, array(
766             array(
767                 'typehint' => T,
768                 'param' => V,
769                 'isreference' => false,
770                 'default' => null,
771             )
772         ));
773 }
non_empty_parameter_list(A)774 non_empty_parameter_list(A) ::= optional_class_type(T) AMPERSAND T_VARIABLE(V). {
775     A = new PHP_ParseryyToken(T . '&' . V, array(
776             array(
777                 'typehint' => T,
778                 'param' => V,
779                 'isreference' => true,
780                 'default' => null,
781             )
782         ));
783 }
non_empty_parameter_list(A)784 non_empty_parameter_list(A) ::= optional_class_type(T) AMPERSAND T_VARIABLE(V) EQUALS static_scalar(D). {
785     A = new PHP_ParseryyToken(T . '&' . V . ' = ' . D, array(
786             array(
787                 'typehint' => T,
788                 'param' => V,
789                 'isreference' => true,
790                 'default' => D,
791             )
792         ));
793 }
non_empty_parameter_list(A)794 non_empty_parameter_list(A) ::= optional_class_type(T) T_VARIABLE(V) EQUALS static_scalar(D). {
795     A = new PHP_ParseryyToken(T . V . ' = ' . D, array(
796             array(
797                 'typehint' => T,
798                 'param' => V,
799                 'isreference' => false,
800                 'default' => D,
801             )
802         ));
803 }
non_empty_parameter_list(A)804 non_empty_parameter_list(A) ::= non_empty_parameter_list(list) COMMA optional_class_type(T) T_VARIABLE(V). {
805     A = new PHP_ParseryyToken(list->string . ', ' . T . V, list);
806     A[] =
807         array(
808             'typehint' => T,
809             'param' => V,
810             'isreference' => false,
811             'default' => null,
812         );
813 }
non_empty_parameter_list(A)814 non_empty_parameter_list(A) ::= non_empty_parameter_list(list) COMMA optional_class_type(T) AMPERSAND T_VARIABLE(V). {
815     A = new PHP_ParseryyToken(list->string . ', ' . T . '&' . V, list);
816     A[] =
817         array(
818             'typehint' => T,
819             'param' => V,
820             'isreference' => true,
821             'default' => null,
822         );
823 }
non_empty_parameter_list(A)824 non_empty_parameter_list(A) ::= non_empty_parameter_list(list) COMMA optional_class_type(T) AMPERSAND T_VARIABLE(V) EQUALS static_scalar(D). {
825     A = new PHP_ParseryyToken(list->string . ', ' . T . V . ' = ' . D, list);
826     A[] =
827         array(
828             'typehint' => T,
829             'param' => V,
830             'isreference' => true,
831             'default' => D,
832         );
833 }
non_empty_parameter_list(A)834 non_empty_parameter_list(A) ::= non_empty_parameter_list(list) COMMA optional_class_type(T) T_VARIABLE(V) EQUALS static_scalar(D). {
835     A = new PHP_ParseryyToken(list->string . ', ' . T . V . ' = ' . D, list);
836     A[] =
837         array(
838             'typehint' => T,
839             'param' => V,
840             'isreference' => false,
841             'default' => D,
842         );
843 }
844 
845 
846 optional_class_type(A) ::= T_STRING|T_ARRAY(B). {A = B;}
optional_class_type(A)847 optional_class_type(A) ::= . {A = '';}
848 
function_call_parameter_list(A)849 function_call_parameter_list(A) ::= non_empty_function_call_parameter_list(B). {A = B;}
function_call_parameter_list(A)850 function_call_parameter_list(A) ::= . {A = new PHP_ParseryyToken('');}
851 
non_empty_function_call_parameter_list(A)852 non_empty_function_call_parameter_list(A) ::= expr_without_variable(B). {A = new PHP_ParseryyToken(B);}
non_empty_function_call_parameter_list(A)853 non_empty_function_call_parameter_list(A) ::= variable(B). {A = PHP_ParseryyToken(B);}
non_empty_function_call_parameter_list(A)854 non_empty_function_call_parameter_list(A) ::= AMPERSAND w_variable(B). {
855     if (B instanceof PHP_ParseryyToken) {
856         $b = B->string;
857     } else {
858         $b = (string) B;
859     }
860     A = new PHP_ParseryyToken('&' . $b, B);}
non_empty_function_call_parameter_list(A)861 non_empty_function_call_parameter_list(A) ::= non_empty_function_call_parameter_list(LIST) COMMA expr_without_variable(B). {
862     if (B instanceof PHP_ParseryyToken) {
863         $b = B->string;
864     } else {
865         $b = (string) B;
866     }
867     A = new PHP_ParseryyToken(LIST->string . ', ' . $b, LIST);
868     A[] = B;
869 }
non_empty_function_call_parameter_list(A)870 non_empty_function_call_parameter_list(A) ::= non_empty_function_call_parameter_list(LIST) COMMA variable(B). {
871     if (B instanceof PHP_ParseryyToken) {
872         $b = B->string;
873     } else {
874         $b = (string) B;
875     }
876     A = new PHP_ParseryyToken(LIST->string . ', ' . $b, LIST);
877     A[] = B;
878 }
non_empty_function_call_parameter_list(A)879 non_empty_function_call_parameter_list(A) ::= non_empty_function_call_parameter_list(LIST) COMMA AMPERSAND w_variable(B). {
880     if (B instanceof PHP_ParseryyToken) {
881         $b = B->string;
882     } else {
883         $b = (string) B;
884     }
885     A = new PHP_ParseryyToken(LIST->string . ', &' . $b, LIST);
886     A[] = B;
887 }
888 
global_var_list(A)889 global_var_list(A) ::= global_var_list(B) COMMA global_var(C). {
890     A = B;
891     A[] = C;
892 }
global_var_list(A)893 global_var_list(A) ::= global_var(B). {A = B;}
894 
global_var(A)895 global_var(A) ::= T_VARIABLE(B). {A = new PHP_ParseryyToken(B, array('global' => B));}
global_var(A)896 global_var(A) ::= DOLLAR r_variable(B). {A = new PHP_ParseryyToken('$' . B);}
global_var(A)897 global_var(A) ::= DOLLAR LCURLY expr(B) RCURLY.{
898     A = new PHP_ParseryyToken('${' . B->string . '}', B);
899 }
900 
901 
static_var_list(A)902 static_var_list(A) ::= static_var_list(B) COMMA T_VARIABLE(C). {
903     A = B;
904     A[] = array('static' => C, 'default' => null);
905 }
static_var_list(A)906 static_var_list(A) ::= static_var_list(B) COMMA T_VARIABLE(C) EQUALS static_scalar(D). {
907     A = B;
908     A[] = array('static' => C, 'default' => D);
909 }
static_var_list(A)910 static_var_list(A) ::= T_VARIABLE(B). {
911     A = new PHP_ParseryyToken('', array('static' => B, 'default' => null));
912 }
static_var_list(A)913 static_var_list(A) ::= T_VARIABLE(B) EQUALS static_scalar(C). {
914     A = new PHP_ParseryyToken('', array('static' => B, 'default' => C));
915 }
916 
class_statement_list(A)917 class_statement_list(A) ::= class_statement_list(list) class_statement(B). {
918     A = list;
919     A[] = B;
920 }
class_statement_list(A)921 class_statement_list(A) ::= . {A = array();}
922 
class_statement(A)923 class_statement(A) ::= variable_modifiers(mod) class_variable_declaration(B) SEMI. {
924     $a = array();
925     foreach (B as $item) {
926         $a[] = array(
927             'type' => 'var',
928             'name' => $item['name'],
929             'default' => $item['default'],
930             'modifiers' => mod,
931         );
932     }
933     A = new PHP_ParseryyToken('', $a);
934 }
class_statement(A)935 class_statement(A) ::= class_constant_declaration(B) SEMI. {
936     $a = array();
937     foreach (B as $item) {
938         $a[] = array(
939             'type' => 'const',
940             'name' => $item['name'],
941             'value' => $item['value'],
942         );
943     }
944     A = new PHP_ParseryyToken('', $a);
945 }
class_statement(A)946 class_statement(A) ::= method_modifiers(mod) T_FUNCTION is_reference T_STRING(B) LPAREN parameter_list(params) RPAREN method_body. {
947     A = new PHP_ParseryyToken('', array(
948             array(
949                 'type' => 'method',
950                 'name' => B,
951                 'parameters' => params->metadata,
952                 'modifiers' => mod,
953             )
954         ));
955 }
956 
957 
method_body(A)958 method_body(A) ::= SEMI. /* abstract method */ {A = new PHP_ParseryyToken('');}
method_body(A)959 method_body(A) ::= LCURLY inner_statement_list(B) RCURLY. {
960     A = B;
961 }
962 
variable_modifiers(A)963 variable_modifiers(A) ::= non_empty_member_modifiers(B). {A = B;}
variable_modifiers(A)964 variable_modifiers(A) ::= T_VAR. {A = array('public');}
965 
method_modifiers(A)966 method_modifiers(A) ::= non_empty_member_modifiers(B). {A = B;}
method_modifiers(A)967 method_modifiers(A) ::= . {A = array('public');}
968 
non_empty_member_modifiers(A)969 non_empty_member_modifiers(A) ::= member_modifier(B). {A = array(B);}
non_empty_member_modifiers(A)970 non_empty_member_modifiers(A) ::= non_empty_member_modifiers(mod) member_modifier(B). {
971     A = mod;
972     A[] = B;
973 }
974 
975 member_modifier(A) ::= T_PUBLIC|T_PROTECTED|T_PRIVATE|T_STATIC|T_ABSTRACT|T_FINAL(B). {A = strtolower(B);}
976 
class_variable_declaration(A)977 class_variable_declaration(A) ::= class_variable_declaration(list) COMMA T_VARIABLE(var). {
978     A = list;
979     A[] = array(
980         'name' => var,
981         'default' => null,
982     );
983 }
class_variable_declaration(A)984 class_variable_declaration(A) ::= class_variable_declaration(list) COMMA T_VARIABLE(var) EQUALS static_scalar(val). {
985     A = list;
986     A[] = array(
987         'name' => var,
988         'default' => val,
989     );
990 }
class_variable_declaration(A)991 class_variable_declaration(A) ::= T_VARIABLE(B). {
992     A = array(
993             array(
994                 'name' => B,
995                 'default' => null,
996             )
997         );
998 }
class_variable_declaration(A)999 class_variable_declaration(A) ::= T_VARIABLE(var) EQUALS static_scalar(val). {
1000     A = array(
1001             array(
1002                 'name' => var,
1003                 'default' => val,
1004             )
1005         );
1006 }
1007 
class_constant_declaration(A)1008 class_constant_declaration(A) ::= class_constant_declaration(list) COMMA T_STRING(n) EQUALS static_scalar(v). {
1009     A = list;
1010     A[] = array('name' => n, 'value' => v);
1011 }
class_constant_declaration(A)1012 class_constant_declaration(A) ::= T_CONST T_STRING(n) EQUALS static_scalar(v). {
1013     A = array(
1014         array('name' => n, 'value' => v)
1015     );
1016 }
1017 
echo_expr_list(A)1018 echo_expr_list(A) ::= echo_expr_list(B) COMMA expr(C). {A = B;A[] = C;}
echo_expr_list(A)1019 echo_expr_list(A) ::= expr(B). {A = B;}
1020 
unset_variables(A)1021 unset_variables(A) ::= unset_variable(B). {A = B;}
unset_variables(A)1022 unset_variables(A) ::= unset_variables(B) COMMA unset_variable(C). {
1023     A = B;
1024     A[] = C;
1025 }
1026 
unset_variable(A)1027 unset_variable(A) ::= variable(B). {A = B;}
1028 
use_filename(A)1029 use_filename(A) ::= T_CONSTANT_ENCAPSED_STRING(B). {A = B;}
use_filename(A)1030 use_filename(A) ::= LCURLY T_CONSTANT_ENCAPSED_STRING(B) RCURLY. {
1031     A = '{' . B . '}';
1032 }
1033 
r_variable(A)1034 r_variable(A) ::= variable(B). {A = B;}
1035 
w_variable(A)1036 w_variable(A) ::= variable(B). {A = B;}
1037 
rw_variable(A)1038 rw_variable(A) ::= variable(B). {A = B;}
1039 
variable(A)1040 variable(A) ::= base_variable_with_function_calls(BASE) T_OBJECT_OPERATOR object_property(PROP) method_or_not(IS_METHOD) variable_properties(VARP). {
1041     A = new PHP_ParseryyToken((string) BASE . '->' . (string) PROP .
1042         (string) IS_METHOD . (string) VARP, array());
1043     A[] = BASE;
1044     if (is_array(PROP)) {
1045         A[] = PROP;
1046     } else {
1047         if (IS_METHOD->string) {
1048             A[] = array(
1049                 'uses' => 'method',
1050                 'name' => PROP,
1051             );
1052         } else {
1053             A[] = array(
1054                 'uses' => 'var',
1055                 'name' => PROP,
1056             );
1057         }
1058     }
1059     A[] = VARP;
1060 }
variable(A)1061 variable(A) ::= base_variable_with_function_calls(B). {A = B;}
1062 
variable_properties(A)1063 variable_properties(A) ::= variable_properties(B) variable_property(C).
1064 variable_properties(A) ::= . {A = new PHP_ParseryyToken('');}
1065 
variable_property(A)1066 variable_property(A) ::= T_OBJECT_OPERATOR object_property(B) method_or_not(C). {
1067     A = new PHP_ParseryyToken('->' . B->string . C->string, B);
1068     A[] = C;
1069 }
1070 
method_or_not(A)1071 method_or_not(A) ::= LPAREN function_call_parameter_list(B) RPAREN. {
1072     A = new PHP_ParseryyToken('(' . B . ')', B);
1073 }
method_or_not(A)1074 method_or_not(A) ::= . {A = new PHP_ParseryyToken('');}
1075 
variable_without_objects(A)1076 variable_without_objects(A) ::= reference_variable(B). {A = B;}
variable_without_objects(A)1077 variable_without_objects(A) ::= simple_indirect_reference(I) reference_variable(B). {
1078     A = new PHP_ParseryyToken(I . B->string, B);
1079 }
1080 
static_member(A)1081 static_member(A) ::= fully_qualified_class_name(CLASS) T_PAAMAYIM_NEKUDOTAYIM variable_without_objects(VAR). {
1082     A = new PHP_ParseryyToken(CLASS . '::' . (string) VAR, array(
1083         array(
1084             'usedclass' => CLASS,
1085         )
1086     ));
1087     A[] = VAR;
1088 }
1089 
base_variable_with_function_calls(A)1090 base_variable_with_function_calls(A) ::= base_variable(B). {A = new PHP_ParseryyToken(B);}
base_variable_with_function_calls(A)1091 base_variable_with_function_calls(A) ::= function_call(B). {A = B;}
1092 
base_variable(A)1093 base_variable(A) ::= reference_variable(B). {A = B;}
base_variable(A)1094 base_variable(A) ::= simple_indirect_reference(I) reference_variable(B). {
1095     A = new PHP_ParseryyToken(I . B->string, B);
1096 }
base_variable(A)1097 base_variable(A) ::= static_member(B). {A = B;}
1098 
reference_variable(A)1099 reference_variable(A) ::= reference_variable(REF) LBRACKET dim_offset(DIM) RBRACKET. {
1100     A = new PHP_ParseryyToken((string) REF . '[' . (string) DIM . ']', array());
1101     A[] = REF;
1102     A[] = DIM;
1103 }
reference_variable(A)1104 reference_variable(A) ::= reference_variable(REF) LCURLY expr(DIM) RCURLY. {
1105     A = new PHP_ParseryyToken((string) REF . '{' . (string) DIM . '}', array());
1106     A[] = REF;
1107     A[] = DIM;
1108 }
reference_variable(A)1109 reference_variable(A) ::= compound_variable(B). {A = new PHP_ParseryyToken(B);}
1110 
compound_variable(A)1111 compound_variable(A) ::= T_VARIABLE(B). {A = B;}
compound_variable(A)1112 compound_variable(A) ::= DOLLAR LCURLY expr(B) RCURLY. {A = new PHP_ParseryyToken('${' . (string) B . '}', B);}
1113 
dim_offset(A)1114 dim_offset(A) ::= expr(B). {A = new PHP_ParseryyToken(B);}
dim_offset(A)1115 dim_offset(A) ::= . {A = new PHP_ParseryyToken('');}
1116 
object_property(A)1117 object_property(A) ::= object_dim_list(B). {A = B;}
object_property(A)1118 object_property(A) ::= variable_without_objects(B). {A = B;}
1119 
object_dim_list(A)1120 object_dim_list(A) ::= object_dim_list(LIST) LBRACKET dim_offset(B) RBRACKET. {
1121     A = new PHP_ParseryyToken(LIST->string . '[' . B->string . ']', LIST);
1122     A[] = B;
1123 }
object_dim_list(A)1124 object_dim_list(A) ::= object_dim_list(LIST) LCURLY expr(B) RCURLY. {
1125     A = new PHP_ParseryyToken(LIST->string . '{' . B->string . '}', LIST);
1126     A[] = B;
1127 }
object_dim_list(A)1128 object_dim_list(A) ::= variable_name(B). {A = new PHP_ParseryyToken(B);}
1129 
variable_name(A)1130 variable_name(A) ::= T_STRING(B). {A = B;}
variable_name(A)1131 variable_name(A) ::= LCURLY expr(B) RCURLY. {A = new PHP_ParseryyToken('{' . B->string . '}', B);}
1132 
simple_indirect_reference(A)1133 simple_indirect_reference(A) ::= DOLLAR. {A = '$';}
simple_indirect_reference(A)1134 simple_indirect_reference(A) ::= simple_indirect_reference(B) DOLLAR. {A = B . '$';}
1135 
assignment_list(A)1136 assignment_list(A) ::= assignment_list(B) COMMA assignment_list_element(C). {
1137     A = new PHP_ParseryyToken(B->string . ', ' . C->string, B);
1138     A[] = C;
1139 }
assignment_list(A)1140 assignment_list(A) ::= assignment_list_element(B). {A = B;}
1141 
assignment_list_element(A)1142 assignment_list_element(A) ::= variable(B). {A = B;}
assignment_list_element(A)1143 assignment_list_element(A) ::= T_LIST LPAREN assignment_list(B) RPAREN. {
1144     A = new PHP_ParseryyToken('list(' . B->string . ')', B);
1145 }
assignment_list_element(A)1146 assignment_list_element(A) ::= . {A = new PHP_ParseryyToken('');}
1147 
array_pair_list(A)1148 array_pair_list(A) ::= non_empty_array_pair_list(B) possible_comma(C). {
1149     A = new PHP_ParseryyToken(B->string . C, B);
1150 }
array_pair_list(A)1151 array_pair_list(A) ::= . {A = new PHP_ParseryyToken('');}
1152 
non_empty_array_pair_list(A)1153 non_empty_array_pair_list(A) ::= expr(B) T_DOUBLE_ARROW AMPERSAND w_variable(C). {
1154     A = new PHP_ParseryyToken(B->string . ' => &' . C->string, B);
1155     A[] = C;
1156 }
non_empty_array_pair_list(A)1157 non_empty_array_pair_list(A) ::= expr(B). {A = B;}
non_empty_array_pair_list(A)1158 non_empty_array_pair_list(A) ::= AMPERSAND w_variable(B). {
1159     A = new PHP_ParseryyToken('&' . B->string, B);
1160 }
non_empty_array_pair_list(A)1161 non_empty_array_pair_list(A) ::= non_empty_array_pair_list(B) COMMA expr(C) T_DOUBLE_ARROW expr(D). {
1162     A = new PHP_ParseryyToken(B->string . ', ' . C->string . ' => ' . D->string, B);
1163     A[] = C;
1164     A[] = D;
1165 }
non_empty_array_pair_list(A)1166 non_empty_array_pair_list(A) ::= non_empty_array_pair_list(B) COMMA expr(C). {
1167     A = new PHP_ParseryyToken(B->string . ', ' . C->string, B);
1168     A[] = C;
1169 }
non_empty_array_pair_list(A)1170 non_empty_array_pair_list(A) ::= expr(B) T_DOUBLE_ARROW expr(C). {
1171     A = new PHP_ParseryyToken(B->string . ' => ' . C->string, B);
1172     A[] = C;
1173 }
non_empty_array_pair_list(A)1174 non_empty_array_pair_list(A) ::= non_empty_array_pair_list(B) COMMA expr(C) T_DOUBLE_ARROW AMPERSAND w_variable(D). {
1175     A = new PHP_ParseryyToken(B->string . ', ' . C->string . ' => &' . D->string, B);
1176     A[] = C;
1177     A[] = D;
1178 }
non_empty_array_pair_list(A)1179 non_empty_array_pair_list(A) ::= non_empty_array_pair_list(B) COMMA AMPERSAND w_variable(C). {
1180     A = new PHP_ParseryyToken(B->string . ', &' . C->string, B);
1181     A[] = C;
1182 }
1183 
1184 
encaps_list(A)1185 encaps_list(A) ::= encaps_list(B) encaps_var(C). {
1186     A = new PHP_ParseryyToken(B->string . C, B);
1187     A[] = C;
1188 }
encaps_list(A)1189 encaps_list(A) ::= encaps_list(B) T_STRING(C). {
1190     A = new PHP_ParseryyToken(B->string . C, B);
1191 }
encaps_list(A)1192 encaps_list(A) ::= encaps_list(B) T_NUM_STRING(C). {
1193     A = new PHP_ParseryyToken(B->string . C, B);
1194 }
encaps_list(A)1195 encaps_list(A) ::= encaps_list(B) T_ENCAPSED_AND_WHITESPACE(C). {
1196     A = new PHP_ParseryyToken(B->string . C, B);
1197 }
encaps_list(A)1198 encaps_list(A) ::= encaps_list(B) T_CHARACTER(C). {
1199     A = new PHP_ParseryyToken(B->string . C, B);
1200 }
encaps_list(A)1201 encaps_list(A) ::= encaps_list(B) T_BAD_CHARACTER(C). {
1202     A = new PHP_ParseryyToken(B->string . C, B);
1203 }
encaps_list(A)1204 encaps_list(A) ::= encaps_list(B) LBRACKET. {
1205     A = new PHP_ParseryyToken(B->string . '[', B);
1206 }
encaps_list(A)1207 encaps_list(A) ::= encaps_list(B) RBRACKET. {
1208     A = new PHP_ParseryyToken(B->string . ']', B);
1209 }
encaps_list(A)1210 encaps_list(A) ::= encaps_list(B) LCURLY. {
1211     A = new PHP_ParseryyToken(B->string . '{', B);
1212 }
encaps_list(A)1213 encaps_list(A) ::= encaps_list(B) RCURLY. {
1214     A = new PHP_ParseryyToken(B->string . '}', B);
1215 }
encaps_list(A)1216 encaps_list(A) ::= encaps_list(B) T_OBJECT_OPERATOR. {
1217     A = new PHP_ParseryyToken(B->string . '->', B);
1218 }
encaps_list(A)1219 encaps_list(A) ::= . {A = new PHP_ParseryyToken('');}
1220 
encaps_var(A)1221 encaps_var(A) ::= T_VARIABLE(B). {A = new PHP_ParseryyToken(B);}
1222 encaps_var(A) ::= T_VARIABLE(B) LBRACKET T_STRING|T_NUM_STRING|T_VARIABLE(C) RBRACKET. {
1223     A = new PHP_ParseryyToken(B . '[' . C . ']');
1224 }
encaps_var(A)1225 encaps_var(A) ::= T_VARIABLE(B) T_OBJECT_OPERATOR T_STRING(C). {
1226     A = new PHP_ParseryyToken(B . '->' . C);
1227 }
encaps_var(A)1228 encaps_var(A) ::= T_DOLLAR_OPEN_CURLY_BRACES expr(B) RCURLY. {
1229     A = new PHP_ParseryyToken('${' . B->string . '}', B);
1230 }
encaps_var(A)1231 encaps_var(A) ::= T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME(B) LBRACKET expr(C) RBRACKET RCURLY. {
1232     A = new PHP_ParseryyToken('${' . B . '[' . C->string . ']}', C);
1233 }
encaps_var(A)1234 encaps_var(A) ::= T_CURLY_OPEN variable(B) RCURLY. {
1235     A = new PHP_ParseryyToken('{' . B->string, '}', B);
1236 }
1237 
internal_functions_in_yacc(A)1238 internal_functions_in_yacc(A) ::= T_ISSET LPAREN isset_variables(B) RPAREN. {
1239     A = new PHP_ParseryyToken('isset(' . B->string . ')', B);
1240 }
internal_functions_in_yacc(A)1241 internal_functions_in_yacc(A) ::= T_EMPTY LPAREN variable(B) RPAREN. {
1242     A = new PHP_ParseryyToken('empty(' . B->string . ')', B);
1243 }
internal_functions_in_yacc(A)1244 internal_functions_in_yacc(A) ::= T_INCLUDE expr(B). {
1245     A = new PHP_ParseryyToken('include ' . B->string, B);
1246     A[] = array(
1247         'type' => 'include',
1248         'file' => B->string,
1249     );
1250 }
internal_functions_in_yacc(A)1251 internal_functions_in_yacc(A) ::= T_INCLUDE_ONCE expr(B). {
1252     A = new PHP_ParseryyToken('include_once ' . B->string, B);
1253     A[] = array(
1254         'type' => 'include_once',
1255         'file' => B->string,
1256     );
1257 }
internal_functions_in_yacc(A)1258 internal_functions_in_yacc(A) ::= T_EVAL LPAREN expr(B) RPAREN. {
1259     A = new PHP_ParseryyToken('eval ' . B->string, B);
1260 }
internal_functions_in_yacc(A)1261 internal_functions_in_yacc(A) ::= T_REQUIRE expr(B). {
1262     A = new PHP_ParseryyToken('require ' . B->string, B);
1263     A[] = array(
1264         'type' => 'require',
1265         'file' => B->string,
1266     );
1267 }
internal_functions_in_yacc(A)1268 internal_functions_in_yacc(A) ::= T_REQUIRE_ONCE expr(B). {
1269     A = new PHP_ParseryyToken('require_once ' . B->string, B);
1270     A[] = array(
1271         'type' => 'require_once',
1272         'file' => B->string,
1273     );
1274 }
1275 
isset_variables(A)1276 isset_variables(A) ::= variable(B). {A = B;}
isset_variables(A)1277 isset_variables(A) ::= isset_variables(B) COMMA variable(C). {
1278     A = new PHP_ParseryyToken(B->string . ', ' . C->string, B);
1279     A[] = C;
1280 }
1281 
class_constant(A)1282 class_constant(A) ::= fully_qualified_class_name(B) T_PAAMAYIM_NEKUDOTAYIM T_STRING(C). {
1283     A = new PHP_ParseryyToken(B . '::' . C, array('usedclass' => B));
1284     A[] = array('usedclassconstant' => B . '::' . C);
1285 }
1286 
fully_qualified_class_name(A)1287 fully_qualified_class_name(A) ::= T_STRING(B). {A = B;}
1288 
function_call(A)1289 function_call(A) ::= T_STRING(B) LPAREN function_call_parameter_list(C) RPAREN. {A = new PHP_ParseryyToken(B . '(' . (string) C . ')', C);}
function_call(A)1290 function_call(A) ::= fully_qualified_class_name(CLAS) T_PAAMAYIM_NEKUDOTAYIM T_STRING(FUNC) LPAREN function_call_parameter_list(PL) RPAREN. {
1291     A = new PHP_ParseryyToken(CLAS . '::' . FUNC . '(' . PL->string . ')',
1292             PL);
1293     A[] = array(
1294         'uses' => 'class',
1295         'name' => CLAS,
1296     );
1297     A[] = array(
1298         'uses' => 'method',
1299         'class' => CLAS,
1300         'name' => FUNC,
1301     );
1302 }
function_call(A)1303 function_call(A) ::= fully_qualified_class_name(CLAS) T_PAAMAYIM_NEKUDOTAYIM variable_without_objects(V) LPAREN function_call_parameter_list(PL) RPAREN. {
1304     A = new PHP_ParseryyToken(CLAS . '::' . (string) V . '(' . PL->string . ')', V);
1305     A[] = PL;
1306     A[] = array(
1307         'uses' => 'class',
1308         'name' => CLAS,
1309     );
1310 }
function_call(A)1311 function_call(A) ::= variable_without_objects(B) LPAREN function_call_parameter_list(PL) RPAREN. {
1312     A = new PHP_ParseryyToken((string) B . '(' . PL->string . ')', B);
1313     A[] = PL;
1314 }
1315 
scalar(A)1316 scalar(A) ::= T_STRING(B). {A = new PHP_ParseryyToken(B);}
scalar(A)1317 scalar(A) ::= T_STRING_VARNAME(B). {A = new PHP_ParseryyToken(B);}
scalar(A)1318 scalar(A) ::= class_constant(B). {A = new PHP_ParseryyToken(B);}
scalar(A)1319 scalar(A) ::= common_scalar(B). {A = new PHP_ParseryyToken(B);}
scalar(A)1320 scalar(A) ::= DOUBLEQUOTE encaps_list(B) DOUBLEQUOTE. {
1321     A = new PHP_ParseryyToken('"' . B->string . '"', B);
1322 }
scalar(A)1323 scalar(A) ::= SINGLEQUOTE encaps_list(B) SINGLEQUOTE. {
1324     A = new PHP_ParseryyToken("'" . B->string . "'", B);
1325 }
scalar(A)1326 scalar(A) ::= T_START_HEREDOC(HERE) encaps_list(B) T_END_HEREDOC(DOC). {
1327     A = new PHP_ParseryyToken(HERE->string . B->string . DOC->string, B);
1328 }
1329 
class_name_reference(A)1330 class_name_reference(A) ::= T_STRING(B). {A = B;}
class_name_reference(A)1331 class_name_reference(A) ::= dynamic_class_name_reference(B). {A = B;}
1332 
dynamic_class_name_reference(A)1333 dynamic_class_name_reference(A) ::= base_variable(B) T_OBJECT_OPERATOR object_property(C) dynamic_class_name_variable_properties(D). {
1334     A = new PHP_ParseryyToken(B->string . '->' . C->string . D->string, B);
1335     A[] = array('usedmember' => array(B->string, C->string));
1336     A[] = D;
1337 }
dynamic_class_name_reference(A)1338 dynamic_class_name_reference(A) ::= base_variable(B). {A = B;}
1339 
dynamic_class_name_variable_properties(A)1340 dynamic_class_name_variable_properties(A) ::= dynamic_class_name_variable_properties(B) dynamic_class_name_variable_property(C). {
1341     A = B;
1342     B[] = C;
1343 }
dynamic_class_name_variable_properties(A)1344 dynamic_class_name_variable_properties(A) ::= . {A = new PHP_ParseryyToken('');}
1345 
dynamic_class_name_variable_property(A)1346 dynamic_class_name_variable_property(A) ::= T_OBJECT_OPERATOR object_property(B). {
1347     A = new PHP_ParseryyToken('->' . B->string, array('usedmember' => B->string));
1348 }
1349 
ctor_arguments(A)1350 ctor_arguments(A) ::= LPAREN function_call_parameter_list(B) RPAREN. {
1351     A = new PHP_ParseryyToken('(' . B->string . ')', B);
1352 }
ctor_arguments(A)1353 ctor_arguments(A) ::= . {A = new PHP_ParseryyToken('');}
1354 
possible_comma(A)1355 possible_comma(A) ::= COMMA. {A = ',';}
possible_comma(A)1356 possible_comma(A) ::= . {A = '';}
1357 
for_expr(A)1358 for_expr(A) ::= non_empty_for_expr(B). {A = B;}
for_expr(A)1359 for_expr(A) ::= . {A = new PHP_ParseryyToken('');}
1360 
non_empty_for_expr(A)1361 non_empty_for_expr(A) ::= non_empty_for_expr(B) COMMA expr(C). {
1362     A = new PHP_ParseryyToken(B->string . ', ' . C->string, B);
1363     A[] = C;
1364 }
non_empty_for_expr(A)1365 non_empty_for_expr(A) ::= expr(B). {A = B;}
1366 
is_reference(A)1367 is_reference(A) ::= AMPERSAND. {A = true;}
is_reference(A)1368 is_reference(A) ::= . {A = false;}
1369