1
2/*
3  +------------------------------------------------------------------------+
4  | Phalcon Framework                                                      |
5  +------------------------------------------------------------------------+
6  | Copyright (c) 2011-present Phalcon Team (http://www.phalconphp.com)    |
7  +------------------------------------------------------------------------+
8  | This source file is subject to the New BSD License that is bundled     |
9  | with this package in the file docs/LICENSE.txt.                        |
10  |                                                                        |
11  | If you did not receive a copy of the license and are unable to         |
12  | obtain it through the world-wide-web, please send an email             |
13  | to license@phalconphp.com so we can send you a copy immediately.       |
14  +------------------------------------------------------------------------+
15  | Authors: Andres Gutierrez <andres@phalconphp.com>                      |
16  |          Eduar Carvajal <eduar@phalconphp.com>                         |
17  +------------------------------------------------------------------------+
18*/
19
20%token_prefix PHVOLT_
21%token_type {phvolt_parser_token*}
22%default_type {zval*}
23%extra_argument {phvolt_parser_status *status}
24%name phvolt_
25
26%right OPEN_DELIMITER .
27%left COMMA .
28%left IN .
29%left QUESTION COLON .
30%left RANGE .
31%left AND OR .
32%left IS EQUALS NOTEQUALS LESS GREATER GREATEREQUAL LESSEQUAL IDENTICAL NOTIDENTICAL .
33%left DIVIDE TIMES MOD .
34%left PLUS MINUS CONCAT .
35%right SBRACKET_OPEN .
36%left PIPE .
37%right NOT .
38%left INCR DECR .
39%right PARENTHESES_OPEN .
40%left DOT .
41
42%include {
43#include "parser.php5.inc.h"
44}
45
46%syntax_error {
47	{
48
49		smart_str error_str = {0};
50
51		char *token_name = NULL;
52		const phvolt_token_names *tokens = phvolt_tokens;
53		int token_len = 0;
54		int active_token = status->scanner_state->active_token;
55
56		if (status->scanner_state->start_length) {
57
58			if (active_token) {
59
60				do {
61					if (tokens->code == active_token) {
62						token_name = tokens->name;
63						token_len = tokens->len;
64						break;
65					}
66					++tokens;
67				} while (tokens[0].code != 0);
68
69			}
70
71			smart_str_appendl(&error_str, "Syntax error, unexpected token ", sizeof("Syntax error, unexpected token ") - 1);
72			if (!token_name) {
73				smart_str_appendl(&error_str, "UNKNOWN", sizeof("UNKNOWN") - 1);
74			} else {
75				smart_str_appendl(&error_str, token_name, token_len);
76			}
77
78			if (status->token->value) {
79				smart_str_appendc(&error_str, '(');
80				smart_str_appendl(&error_str, status->token->value, status->token->len);
81				smart_str_appendc(&error_str, ')');
82			}
83
84			smart_str_appendl(&error_str, " in ", sizeof(" in ") - 1);
85			smart_str_appendl(&error_str, Z_STRVAL_P(status->scanner_state->active_file), Z_STRLEN_P(status->scanner_state->active_file));
86			smart_str_appendl(&error_str, " on line ", sizeof(" on line ") - 1);
87
88			{
89				char stmp[MAX_LENGTH_OF_LONG + 1];
90				int str_len;
91				str_len = slprintf(stmp, sizeof(stmp), "%ld", status->scanner_state->active_line);
92				smart_str_appendl(&error_str, stmp, str_len);
93			}
94
95		} else {
96
97			smart_str_appendl(&error_str, "Syntax error, unexpected EOF in ", sizeof("Syntax error, unexpected EOF in ") - 1);
98			smart_str_appendl(&error_str, Z_STRVAL_P(status->scanner_state->active_file), Z_STRLEN_P(status->scanner_state->active_file));
99
100			/* Report unclosed 'if' blocks */
101			if ((status->scanner_state->if_level + status->scanner_state->old_if_level) > 0) {
102				if ((status->scanner_state->if_level + status->scanner_state->old_if_level) == 1) {
103					smart_str_appendl(&error_str, ", there is one 'if' block without close", sizeof(", there is one 'if' block without close") - 1);
104				} else {
105					smart_str_appendl(&error_str, ", there are ", sizeof(", there are ") - 1);
106					{
107						char stmp[MAX_LENGTH_OF_LONG + 1];
108						int str_len;
109						str_len = slprintf(stmp, sizeof(stmp), "%ld", status->scanner_state->if_level + status->scanner_state->old_if_level);
110						smart_str_appendl(&error_str, stmp, str_len);
111					}
112					smart_str_appendl(&error_str, " 'if' blocks without close", sizeof(" 'if' blocks without close") - 1);
113				}
114			}
115
116			/* Report unclosed 'for' blocks */
117			if (status->scanner_state->for_level > 0) {
118				if (status->scanner_state->for_level == 1) {
119					smart_str_appendl(&error_str, ", there is one 'for' block without close", sizeof(", there is one 'for' block without close") - 1);
120				} else {
121					smart_str_appendl(&error_str, ", there are ", sizeof(", there are ") - 1);
122					{
123						char stmp[MAX_LENGTH_OF_LONG + 1];
124						int str_len;
125						str_len = slprintf(stmp, sizeof(stmp), "%ld", status->scanner_state->if_level);
126						smart_str_appendl(&error_str, stmp, str_len);
127					}
128					smart_str_appendl(&error_str, " 'for' blocks without close", sizeof(" 'for' blocks without close") - 1);
129				}
130			}
131
132			/* Report unclosed 'switch' blocks */
133			if (status->scanner_state->switch_level > 0) {
134				smart_str_appendl(&error_str, ", there is a 'switch' block without 'endswitch'", sizeof(", there is a 'switch' block without 'endswitch'") - 1);
135			}
136
137		}
138
139		smart_str_0(&error_str);
140
141#if PHP_VERSION_ID < 70000
142		if (error_str.len) {
143			status->syntax_error = error_str.c;
144			status->syntax_error_len = error_str.len;
145		} else {
146			status->syntax_error = NULL;
147		}
148#else
149		if (error_str.s) {
150			status->syntax_error = estrndup(ZSTR_VAL(error_str.s), ZSTR_LEN(error_str.s));
151			status->syntax_error_len = ZSTR_LEN(error_str.s);
152		} else {
153			status->syntax_error = NULL;
154		}
155#endif
156	}
157
158	status->status = PHVOLT_PARSING_FAILED;
159}
160
161%token_destructor {
162	if ($$) {
163		if ($$->free_flag) {
164			efree($$->token);
165		}
166		efree($$);
167	}
168}
169
170program ::= volt_language(Q) . {
171	status->ret = Q;
172}
173
174volt_language(R) ::= statement_list(L) . {
175	R = L;
176}
177
178%destructor statement_list {
179#if PHP_VERSION_ID < 70000
180	zval_ptr_dtor(&$$);
181#endif
182}
183
184statement_list(R) ::= statement_list(L) statement(S) . {
185	R = phvolt_ret_zval_list(L, S);
186}
187
188statement_list(R) ::= statement(S) . {
189	R = phvolt_ret_zval_list(NULL, S);
190}
191
192%destructor statement {
193#if PHP_VERSION_ID < 70000
194	zval_ptr_dtor(&$$);
195#endif
196}
197
198statement(R) ::= raw_fragment(F) . {
199	R = F;
200}
201
202statement(R) ::= if_statement(I) . {
203	R = I;
204}
205
206statement(R) ::= elseif_statement(E) . {
207	R = E;
208}
209
210statement(R) ::= elsefor_statement(E) . {
211	R = E;
212}
213
214statement(R) ::= for_statement(E) . {
215	R = E;
216}
217
218statement(R) ::= switch_statement(E) . {
219	R = E;
220}
221
222statement(R) ::= case_clause(E) . {
223	R = E;
224}
225
226statement(R) ::= set_statement(S) . {
227	R = S;
228}
229
230statement(R) ::= echo_statement(E) . {
231	R = E;
232}
233
234statement(R) ::= block_statement(E) . {
235	R = E;
236}
237
238statement(R) ::= cache_statement(E) . {
239	R = E;
240}
241
242statement(R) ::= extends_statement(E) . {
243	R = E;
244}
245
246statement(R) ::= include_statement(E) . {
247	R = E;
248}
249
250statement(R) ::= do_statement(E) . {
251	R = E;
252}
253
254statement(R) ::= return_statement(E) . {
255	R = E;
256}
257
258statement(R) ::= autoescape_statement(E) . {
259	R = E;
260}
261
262statement(R) ::= raw_statement(E) . {
263	R = E;
264}
265
266statement(R) ::= break_statement(E) . {
267	R = E;
268}
269
270statement(R) ::= continue_statement(E) . {
271	R = E;
272}
273
274statement(R) ::= macro_statement(E) . {
275	R = E;
276}
277
278statement(R) ::= empty_statement(E) . {
279	R = E;
280}
281
282statement(R) ::= macro_call_statement(E) . {
283	R = E;
284}
285
286%destructor if_statement {
287#if PHP_VERSION_ID < 70000
288	zval_ptr_dtor(&$$);
289#endif
290}
291
292/* {% if EXPR %} STMT {% endif %} */
293if_statement(R) ::= OPEN_DELIMITER IF expr(E) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDIF CLOSE_DELIMITER . {
294	R = phvolt_ret_if_statement(E, T, NULL, status->scanner_state);
295}
296
297/* {% if EXPR %} {% endif %} */
298if_statement(R) ::= OPEN_DELIMITER IF expr(E) CLOSE_DELIMITER OPEN_DELIMITER ENDIF CLOSE_DELIMITER . {
299	R = phvolt_ret_if_statement(E, NULL, NULL, status->scanner_state);
300}
301
302/* {% if EXPR %} STMT {% esle %} STMT {% endif %} */
303if_statement(R) ::= OPEN_DELIMITER IF expr(E) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ELSE CLOSE_DELIMITER statement_list(F) OPEN_DELIMITER ENDIF CLOSE_DELIMITER . {
304	R = phvolt_ret_if_statement(E, T, F, status->scanner_state);
305}
306
307/* {% if EXPR %} STMT {% esle %} {% endif %} */
308if_statement(R) ::= OPEN_DELIMITER IF expr(E) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ELSE CLOSE_DELIMITER OPEN_DELIMITER ENDIF CLOSE_DELIMITER . {
309	R = phvolt_ret_if_statement(E, T, NULL, status->scanner_state);
310}
311
312/* {% if EXPR %} {% esle %} {% endif %} */
313if_statement(R) ::= OPEN_DELIMITER IF expr(E) CLOSE_DELIMITER OPEN_DELIMITER ELSE CLOSE_DELIMITER OPEN_DELIMITER ENDIF CLOSE_DELIMITER . {
314	R = phvolt_ret_if_statement(E, NULL, NULL, status->scanner_state);
315}
316
317%destructor elseif_statement {
318#if PHP_VERSION_ID < 70000
319	zval_ptr_dtor(&$$);
320#endif
321}
322
323elseif_statement(R) ::= OPEN_DELIMITER ELSEIF expr(E) CLOSE_DELIMITER . {
324	R = phvolt_ret_elseif_statement(E, status->scanner_state);
325}
326
327%destructor elsefor_statement {
328#if PHP_VERSION_ID < 70000
329	zval_ptr_dtor(&$$);
330#endif
331}
332
333elsefor_statement(R) ::= OPEN_DELIMITER ELSEFOR CLOSE_DELIMITER . {
334	R = phvolt_ret_elsefor_statement(status->scanner_state);
335}
336
337%destructor for_statement {
338#if PHP_VERSION_ID < 70000
339	zval_ptr_dtor(&$$);
340#endif
341}
342
343for_statement(R) ::= OPEN_DELIMITER FOR IDENTIFIER(I) IN expr(E) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDFOR CLOSE_DELIMITER . {
344	R = phvolt_ret_for_statement(I, NULL, E, NULL, T, status->scanner_state);
345}
346
347for_statement(R) ::= OPEN_DELIMITER FOR IDENTIFIER(I) IN expr(E) IF expr(IE) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDFOR CLOSE_DELIMITER . {
348	R = phvolt_ret_for_statement(I, NULL, E, IE, T, status->scanner_state);
349}
350
351for_statement(R) ::= OPEN_DELIMITER FOR IDENTIFIER(K) COMMA IDENTIFIER(V) IN expr(E) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDFOR CLOSE_DELIMITER . {
352	R = phvolt_ret_for_statement(V, K, E, NULL, T, status->scanner_state);
353}
354
355for_statement(R) ::= OPEN_DELIMITER FOR IDENTIFIER(K) COMMA IDENTIFIER(V) IN expr(E) IF expr(IE) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDFOR CLOSE_DELIMITER . {
356	R = phvolt_ret_for_statement(V, K, E, IE, T, status->scanner_state);
357}
358
359%destructor switch_statement {
360#if PHP_VERSION_ID < 70000
361	zval_ptr_dtor(&$$);
362#endif
363}
364
365/* {% switch EXPR %} STMT {% endswitch %} */
366switch_statement(R) ::= OPEN_DELIMITER SWITCH expr(E) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDSWITCH CLOSE_DELIMITER . {
367	R = phvolt_ret_switch_statement(E, T, status->scanner_state);
368}
369
370/* {% switch EXPR %} {% endswitch %} */
371switch_statement(R) ::= OPEN_DELIMITER SWITCH expr(E) CLOSE_DELIMITER OPEN_DELIMITER ENDSWITCH CLOSE_DELIMITER . {
372	R = phvolt_ret_switch_statement(E, NULL, status->scanner_state);
373}
374
375%destructor case_clause {
376#if PHP_VERSION_ID < 70000
377	zval_ptr_dtor(&$$);
378#endif
379}
380
381/* {% case EXPR %} {% endcase %} */
382case_clause(R) ::= OPEN_DELIMITER CASE expr(E) CLOSE_DELIMITER . {
383	R = phvolt_ret_case_clause(E, status->scanner_state);
384}
385
386/* {% default %} */
387case_clause(R) ::= OPEN_DELIMITER DEFAULT CLOSE_DELIMITER . {
388	R = phvolt_ret_case_clause(NULL, status->scanner_state);
389}
390
391%destructor set_statement {
392#if PHP_VERSION_ID < 70000
393	zval_ptr_dtor(&$$);
394#endif
395}
396
397set_statement(R) ::= OPEN_DELIMITER SET set_assignments(L) CLOSE_DELIMITER . {
398	R = phvolt_ret_set_statement(L);
399}
400
401%destructor set_assignments {
402#if PHP_VERSION_ID < 70000
403	zval_ptr_dtor(&$$);
404#endif
405}
406
407set_assignments(R) ::= set_assignments(L) COMMA set_assignment(S) . {
408	R = phvolt_ret_zval_list(L, S);
409}
410
411set_assignments(R) ::= set_assignment(S) . {
412	R = phvolt_ret_zval_list(NULL, S);
413}
414
415%destructor set_assignment {
416#if PHP_VERSION_ID < 70000
417	zval_ptr_dtor(&$$);
418#endif
419}
420
421set_assignment(R) ::= assignable_expr(I) ASSIGN expr(E) . {
422	R = phvolt_ret_set_assignment(I, PHVOLT_T_ASSIGN, E, status->scanner_state);
423}
424
425set_assignment(R) ::= assignable_expr(I) ADD_ASSIGN expr(E) . {
426	R = phvolt_ret_set_assignment(I, PHVOLT_T_ADD_ASSIGN, E, status->scanner_state);
427}
428
429set_assignment(R) ::= assignable_expr(I) SUB_ASSIGN expr(E) . {
430	R = phvolt_ret_set_assignment(I, PHVOLT_T_SUB_ASSIGN, E, status->scanner_state);
431}
432
433set_assignment(R) ::= assignable_expr(I) MUL_ASSIGN expr(E) . {
434	R = phvolt_ret_set_assignment(I, PHVOLT_T_MUL_ASSIGN, E, status->scanner_state);
435}
436
437set_assignment(R) ::= assignable_expr(I) DIV_ASSIGN expr(E) . {
438	R = phvolt_ret_set_assignment(I, PHVOLT_T_DIV_ASSIGN, E, status->scanner_state);
439}
440
441assignable_expr(R) ::= IDENTIFIER(I) . {
442	R = phvolt_ret_literal_zval(PHVOLT_T_IDENTIFIER, I, status->scanner_state);
443}
444
445assignable_expr(R) ::= assignable_expr(E) SBRACKET_OPEN expr(D) SBRACKET_CLOSE . {
446	R = phvolt_ret_expr(PHVOLT_T_ARRAYACCESS, E, D, NULL, status->scanner_state);
447}
448
449assignable_expr(R) ::= assignable_expr(E) DOT assignable_expr(D)  . {
450	R = phvolt_ret_expr(PHVOLT_T_DOT, E, D, NULL, status->scanner_state);
451}
452
453%destructor macro_statement {
454#if PHP_VERSION_ID < 70000
455	zval_ptr_dtor(&$$);
456#endif
457}
458
459macro_statement(R) ::= OPEN_DELIMITER MACRO IDENTIFIER(I) PARENTHESES_OPEN PARENTHESES_CLOSE CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDMACRO CLOSE_DELIMITER . {
460	R = phvolt_ret_macro_statement(I, NULL, T, status->scanner_state);
461}
462
463macro_statement(R) ::= OPEN_DELIMITER MACRO IDENTIFIER(I) PARENTHESES_OPEN macro_parameters(P) PARENTHESES_CLOSE CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDMACRO CLOSE_DELIMITER . {
464	R = phvolt_ret_macro_statement(I, P, T, status->scanner_state);
465}
466
467%destructor macro_parameters {
468#if PHP_VERSION_ID < 70000
469	zval_ptr_dtor(&$$);
470#endif
471}
472
473macro_parameters(R) ::= macro_parameters(L) COMMA macro_parameter(I) . {
474	R = phvolt_ret_zval_list(L, I);
475}
476
477macro_parameters(R) ::= macro_parameter(I) . {
478	R = phvolt_ret_zval_list(NULL, I);
479}
480
481%destructor macro_parameter {
482#if PHP_VERSION_ID < 70000
483	zval_ptr_dtor(&$$);
484#endif
485}
486
487macro_parameter(R) ::= IDENTIFIER(I) . {
488	R = phvolt_ret_macro_parameter(I, NULL, status->scanner_state);
489}
490
491macro_parameter(R) ::= IDENTIFIER(I) ASSIGN macro_parameter_default(D) . {
492	R = phvolt_ret_macro_parameter(I, D, status->scanner_state);
493}
494
495macro_parameter_default(R) ::= INTEGER(I) . {
496	R = phvolt_ret_literal_zval(PHVOLT_T_INTEGER, I, status->scanner_state);
497}
498
499macro_parameter_default(R) ::= STRING(S) . {
500	R = phvolt_ret_literal_zval(PHVOLT_T_STRING, S, status->scanner_state);
501}
502
503macro_parameter_default(R) ::= DOUBLE(D) . {
504	R = phvolt_ret_literal_zval(PHVOLT_T_DOUBLE, D, status->scanner_state);
505}
506
507macro_parameter_default(R) ::= NULL . {
508	R = phvolt_ret_literal_zval(PHVOLT_T_NULL, NULL, status->scanner_state);
509}
510
511macro_parameter_default(R) ::= FALSE . {
512	R = phvolt_ret_literal_zval(PHVOLT_T_FALSE, NULL, status->scanner_state);
513}
514
515macro_parameter_default(R) ::= TRUE . {
516	R = phvolt_ret_literal_zval(PHVOLT_T_TRUE, NULL, status->scanner_state);
517}
518
519%destructor macro_call_statement {
520#if PHP_VERSION_ID < 70000
521	zval_ptr_dtor(&$$);
522#endif
523}
524
525macro_call_statement(R) ::= OPEN_DELIMITER CALL expr(E) PARENTHESES_OPEN argument_list(L) PARENTHESES_CLOSE CLOSE_DELIMITER statement_list(C) OPEN_DELIMITER ENDCALL CLOSE_DELIMITER . {
526	R = phvolt_ret_macro_call_statement(E, L, C, status->scanner_state);
527}
528
529macro_call_statement(R) ::= OPEN_DELIMITER CALL expr(E) PARENTHESES_OPEN PARENTHESES_CLOSE CLOSE_DELIMITER OPEN_DELIMITER ENDCALL CLOSE_DELIMITER . {
530	R = phvolt_ret_macro_call_statement(E, NULL, NULL, status->scanner_state);
531}
532
533%destructor empty_statement {
534#if PHP_VERSION_ID < 70000
535	zval_ptr_dtor(&$$);
536#endif
537}
538
539empty_statement(R) ::= OPEN_DELIMITER CLOSE_DELIMITER . {
540	R = phvolt_ret_empty_statement(status->scanner_state);
541}
542
543%destructor echo_statement {
544#if PHP_VERSION_ID < 70000
545	zval_ptr_dtor(&$$);
546#endif
547}
548
549echo_statement(R) ::= OPEN_EDELIMITER expr(E) CLOSE_EDELIMITER . {
550	R = phvolt_ret_echo_statement(E, status->scanner_state);
551}
552
553%destructor block_statement {
554#if PHP_VERSION_ID < 70000
555	zval_ptr_dtor(&$$);
556#endif
557}
558
559block_statement(R) ::= OPEN_DELIMITER BLOCK IDENTIFIER(I) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDBLOCK CLOSE_DELIMITER . {
560	R = phvolt_ret_block_statement(I, T, status->scanner_state);
561}
562
563block_statement(R) ::= OPEN_DELIMITER BLOCK IDENTIFIER(I) CLOSE_DELIMITER OPEN_DELIMITER ENDBLOCK CLOSE_DELIMITER . {
564	R = phvolt_ret_block_statement(I, NULL, status->scanner_state);
565}
566
567%destructor cache_statement {
568#if PHP_VERSION_ID < 70000
569	zval_ptr_dtor(&$$);
570#endif
571}
572
573cache_statement(R) ::= OPEN_DELIMITER CACHE expr(E) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDCACHE CLOSE_DELIMITER . {
574	R = phvolt_ret_cache_statement(E, NULL, T, status->scanner_state);
575}
576
577cache_statement(R) ::= OPEN_DELIMITER CACHE expr(E) cache_lifetime(N) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDCACHE CLOSE_DELIMITER . {
578	R = phvolt_ret_cache_statement(E, N, T, status->scanner_state);
579}
580
581%destructor cache_lifetime {
582#if PHP_VERSION_ID < 70000
583	zval_ptr_dtor(&$$);
584#endif
585}
586
587cache_lifetime(R) ::= INTEGER(I) . {
588	R = phvolt_ret_literal_zval(PHVOLT_T_INTEGER, I, status->scanner_state);
589}
590
591cache_lifetime(R) ::= IDENTIFIER(I) . {
592	R = phvolt_ret_literal_zval(PHVOLT_T_IDENTIFIER, I, status->scanner_state);
593}
594
595%destructor raw_statement {
596#if PHP_VERSION_ID < 70000
597	zval_ptr_dtor(&$$);
598#endif
599}
600
601raw_statement(R) ::= OPEN_DELIMITER RAW CLOSE_DELIMITER statement(T) OPEN_DELIMITER ENDRAW CLOSE_DELIMITER . {
602	R = phvolt_ret_raw_statement(T, status->scanner_state);
603}
604
605%destructor extends_statement {
606#if PHP_VERSION_ID < 70000
607	zval_ptr_dtor(&$$);
608#endif
609}
610
611extends_statement(R) ::= OPEN_DELIMITER EXTENDS expr(S) CLOSE_DELIMITER . {
612	R = phvolt_ret_extends_statement(S, status->scanner_state);
613}
614
615%destructor include_statement {
616#if PHP_VERSION_ID < 70000
617	zval_ptr_dtor(&$$);
618#endif
619}
620
621include_statement(R) ::= OPEN_DELIMITER INCLUDE expr(E) CLOSE_DELIMITER . {
622	R = phvolt_ret_include_statement(E, NULL, status->scanner_state);
623}
624
625include_statement(R) ::= OPEN_DELIMITER INCLUDE expr(E) WITH expr(P) CLOSE_DELIMITER . {
626	R = phvolt_ret_include_statement(E, P, status->scanner_state);
627}
628
629%destructor do_statement {
630#if PHP_VERSION_ID < 70000
631	zval_ptr_dtor(&$$);
632#endif
633}
634
635do_statement(R) ::= OPEN_DELIMITER DO expr(E) CLOSE_DELIMITER . {
636	R = phvolt_ret_do_statement(E, status->scanner_state);
637}
638
639%destructor return_statement {
640#if PHP_VERSION_ID < 70000
641	zval_ptr_dtor(&$$);
642#endif
643}
644
645return_statement(R) ::= OPEN_DELIMITER RETURN expr(E) CLOSE_DELIMITER . {
646	R = phvolt_ret_return_statement(E, status->scanner_state);
647}
648
649%destructor autoescape_statement {
650#if PHP_VERSION_ID < 70000
651	zval_ptr_dtor(&$$);
652#endif
653}
654
655autoescape_statement(R) ::= OPEN_DELIMITER AUTOESCAPE FALSE CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDAUTOESCAPE CLOSE_DELIMITER . {
656	R = phvolt_ret_autoescape_statement(0, T, status->scanner_state);
657}
658
659autoescape_statement(R) ::= OPEN_DELIMITER AUTOESCAPE TRUE CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDAUTOESCAPE CLOSE_DELIMITER . {
660	R = phvolt_ret_autoescape_statement(1, T, status->scanner_state);
661}
662
663%destructor break_statement {
664#if PHP_VERSION_ID < 70000
665	zval_ptr_dtor(&$$);
666#endif
667}
668
669break_statement(R) ::= OPEN_DELIMITER BREAK CLOSE_DELIMITER . {
670	R = phvolt_ret_break_statement(status->scanner_state);
671}
672
673%destructor continue_statement {
674#if PHP_VERSION_ID < 70000
675	zval_ptr_dtor(&$$);
676#endif
677}
678
679continue_statement(R) ::= OPEN_DELIMITER CONTINUE CLOSE_DELIMITER . {
680	R = phvolt_ret_continue_statement(status->scanner_state);
681}
682
683%destructor raw_fragment {
684#if PHP_VERSION_ID < 70000
685	zval_ptr_dtor(&$$);
686#endif
687}
688
689raw_fragment(R) ::= RAW_FRAGMENT(F) . {
690	R = phvolt_ret_literal_zval(PHVOLT_T_RAW_FRAGMENT, F, status->scanner_state);
691}
692
693%destructor expr {
694#if PHP_VERSION_ID < 70000
695	zval_ptr_dtor(&$$);
696#endif
697}
698
699expr(R) ::= MINUS expr(E) . {
700	R = phvolt_ret_expr(PHVOLT_T_MINUS, NULL, E, NULL, status->scanner_state);
701}
702
703expr(R) ::= PLUS expr(E) . {
704	R = phvolt_ret_expr(PHVOLT_T_PLUS, NULL, E, NULL, status->scanner_state);
705}
706
707expr(R) ::= expr(O1) MINUS expr(O2) . {
708	R = phvolt_ret_expr(PHVOLT_T_SUB, O1, O2, NULL, status->scanner_state);
709}
710
711expr(R) ::= expr(O1) PLUS expr(O2) . {
712	R = phvolt_ret_expr(PHVOLT_T_ADD, O1, O2, NULL, status->scanner_state);
713}
714
715expr(R) ::= expr(O1) TIMES expr(O2) . {
716	R = phvolt_ret_expr(PHVOLT_T_MUL, O1, O2, NULL, status->scanner_state);
717}
718
719expr(R) ::= expr(O1) TIMES TIMES expr(O2) . {
720	R = phvolt_ret_expr(PHVOLT_T_POW, O1, O2, NULL, status->scanner_state);
721}
722
723expr(R) ::= expr(O1) DIVIDE expr(O2) . {
724	R = phvolt_ret_expr(PHVOLT_T_DIV, O1, O2, NULL, status->scanner_state);
725}
726
727expr(R) ::= expr(O1) DIVIDE DIVIDE expr(O2) . {
728	R = phvolt_ret_expr(PHVOLT_T_MOD, O1, O2, NULL, status->scanner_state);
729}
730
731expr(R) ::= expr(O1) MOD expr(O2) . {
732	R = phvolt_ret_expr(PHVOLT_T_MOD, O1, O2, NULL, status->scanner_state);
733}
734
735expr(R) ::= expr(O1) AND expr(O2) . {
736	R = phvolt_ret_expr(PHVOLT_T_AND, O1, O2, NULL, status->scanner_state);
737}
738
739expr(R) ::= expr(O1) OR expr(O2) . {
740	R = phvolt_ret_expr(PHVOLT_T_OR, O1, O2, NULL, status->scanner_state);
741}
742
743expr(R) ::= expr(O1) CONCAT expr(O2) . {
744	R = phvolt_ret_expr(PHVOLT_T_CONCAT, O1, O2, NULL, status->scanner_state);
745}
746
747expr(R) ::= expr(O1) PIPE expr(O2) . {
748	R = phvolt_ret_expr(PHVOLT_T_PIPE, O1, O2, NULL, status->scanner_state);
749}
750
751expr(R) ::= expr(O1) RANGE expr(O2) . {
752	R = phvolt_ret_expr(PHVOLT_T_RANGE, O1, O2, NULL, status->scanner_state);
753}
754
755expr(R) ::= expr(O1) EQUALS expr(O2) . {
756	R = phvolt_ret_expr(PHVOLT_T_EQUALS, O1, O2, NULL, status->scanner_state);
757}
758
759expr(R) ::= expr(O1) NOTEQUALS DEFINED . {
760	R = phvolt_ret_expr(PHVOLT_T_NOT_ISSET, O1, NULL, NULL, status->scanner_state);
761}
762
763expr(R) ::= expr(O1) IS DEFINED . {
764	R = phvolt_ret_expr(PHVOLT_T_ISSET, O1, NULL, NULL, status->scanner_state);
765}
766
767expr(R) ::= expr(O1) NOTEQUALS EMPTY . {
768	R = phvolt_ret_expr(PHVOLT_T_NOT_ISEMPTY, O1, NULL, NULL, status->scanner_state);
769}
770
771expr(R) ::= expr(O1) IS EMPTY . {
772	R = phvolt_ret_expr(PHVOLT_T_ISEMPTY, O1, NULL, NULL, status->scanner_state);
773}
774
775expr(R) ::= expr(O1) NOTEQUALS EVEN . {
776	R = phvolt_ret_expr(PHVOLT_T_NOT_ISEVEN, O1, NULL, NULL, status->scanner_state);
777}
778
779expr(R) ::= expr(O1) IS EVEN . {
780	R = phvolt_ret_expr(PHVOLT_T_ISEVEN, O1, NULL, NULL, status->scanner_state);
781}
782
783expr(R) ::= expr(O1) NOTEQUALS ODD . {
784	R = phvolt_ret_expr(PHVOLT_T_NOT_ISODD, O1, NULL, NULL, status->scanner_state);
785}
786
787expr(R) ::= expr(O1) IS ODD . {
788	R = phvolt_ret_expr(PHVOLT_T_ISODD, O1, NULL, NULL, status->scanner_state);
789}
790
791expr(R) ::= expr(O1) NOTEQUALS NUMERIC . {
792	R = phvolt_ret_expr(PHVOLT_T_NOT_ISNUMERIC, O1, NULL, NULL, status->scanner_state);
793}
794
795expr(R) ::= expr(O1) IS NUMERIC . {
796	R = phvolt_ret_expr(PHVOLT_T_ISNUMERIC, O1, NULL, NULL, status->scanner_state);
797}
798
799expr(R) ::= expr(O1) NOTEQUALS SCALAR . {
800	R = phvolt_ret_expr(PHVOLT_T_NOT_ISSCALAR, O1, NULL, NULL, status->scanner_state);
801}
802
803expr(R) ::= expr(O1) IS SCALAR . {
804	R = phvolt_ret_expr(PHVOLT_T_ISSCALAR, O1, NULL, NULL, status->scanner_state);
805}
806
807expr(R) ::= expr(O1) NOTEQUALS ITERABLE . {
808	R = phvolt_ret_expr(PHVOLT_T_NOT_ISITERABLE, O1, NULL, NULL, status->scanner_state);
809}
810
811expr(R) ::= expr(O1) IS ITERABLE . {
812	R = phvolt_ret_expr(PHVOLT_T_ISITERABLE, O1, NULL, NULL, status->scanner_state);
813}
814
815expr(R) ::= expr(O1) IS expr(O2) . {
816	R = phvolt_ret_expr(PHVOLT_T_IS, O1, O2, NULL, status->scanner_state);
817}
818
819expr(R) ::= expr(O1) NOTEQUALS expr(O2) . {
820	R = phvolt_ret_expr(PHVOLT_T_NOTEQUALS, O1, O2, NULL, status->scanner_state);
821}
822
823expr(R) ::= expr(O1) IDENTICAL expr(O2) . {
824	R = phvolt_ret_expr(PHVOLT_T_IDENTICAL, O1, O2, NULL, status->scanner_state);
825}
826
827expr(R) ::= expr(O1) NOTIDENTICAL expr(O2) . {
828	R = phvolt_ret_expr(PHVOLT_T_NOTIDENTICAL, O1, O2, NULL, status->scanner_state);
829}
830
831expr(R) ::= expr(O1) LESS expr(O2) . {
832	R = phvolt_ret_expr(PHVOLT_T_LESS, O1, O2, NULL, status->scanner_state);
833}
834
835expr(R) ::= expr(O1) GREATER expr(O2) . {
836	R = phvolt_ret_expr(PHVOLT_T_GREATER, O1, O2, NULL, status->scanner_state);
837}
838
839expr(R) ::= expr(O1) GREATEREQUAL expr(O2) . {
840	R = phvolt_ret_expr(PHVOLT_T_GREATEREQUAL, O1, O2, NULL, status->scanner_state);
841}
842
843expr(R) ::= expr(O1) LESSEQUAL expr(O2) . {
844	R = phvolt_ret_expr(PHVOLT_T_LESSEQUAL, O1, O2, NULL, status->scanner_state);
845}
846
847expr(R) ::= expr(O1) DOT expr(O2) . {
848	R = phvolt_ret_expr(PHVOLT_T_DOT, O1, O2, NULL, status->scanner_state);
849}
850
851expr(R) ::= expr(O1) IN expr(O2) . {
852	R = phvolt_ret_expr(PHVOLT_T_IN, O1, O2, NULL, status->scanner_state);
853}
854
855expr(R) ::= expr(O1) NOT IN expr(O2) . {
856	R = phvolt_ret_expr(PHVOLT_T_NOT_IN, O1, O2, NULL, status->scanner_state);
857}
858
859expr(R) ::= NOT expr(E) . {
860	R = phvolt_ret_expr(PHVOLT_T_NOT, NULL, E, NULL, status->scanner_state);
861}
862
863expr(R) ::= expr(E) INCR . {
864	R = phvolt_ret_expr(PHVOLT_T_INCR, E, NULL, NULL, status->scanner_state);
865}
866
867expr(R) ::= expr(E) DECR . {
868	R = phvolt_ret_expr(PHVOLT_T_DECR, E, NULL, NULL, status->scanner_state);
869}
870
871expr(R) ::= PARENTHESES_OPEN expr(E) PARENTHESES_CLOSE . {
872	R = phvolt_ret_expr(PHVOLT_T_ENCLOSED, E, NULL, NULL, status->scanner_state);
873}
874
875expr(R) ::= SBRACKET_OPEN SBRACKET_CLOSE . {
876	R = phvolt_ret_expr(PHVOLT_T_ARRAY, NULL, NULL, NULL, status->scanner_state);
877}
878
879expr(R) ::= SBRACKET_OPEN array_list(A) SBRACKET_CLOSE . {
880	R = phvolt_ret_expr(PHVOLT_T_ARRAY, A, NULL, NULL, status->scanner_state);
881}
882
883expr(R) ::= CBRACKET_OPEN CBRACKET_CLOSE . {
884	R = phvolt_ret_expr(PHVOLT_T_ARRAY, NULL, NULL, NULL, status->scanner_state);
885}
886
887expr(R) ::= CBRACKET_OPEN array_list(A) CBRACKET_CLOSE . {
888	R = phvolt_ret_expr(PHVOLT_T_ARRAY, A, NULL, NULL, status->scanner_state);
889}
890
891expr(R) ::= expr(E) SBRACKET_OPEN expr(D) SBRACKET_CLOSE . {
892	R = phvolt_ret_expr(PHVOLT_T_ARRAYACCESS, E, D, NULL, status->scanner_state);
893}
894
895expr(R) ::= expr(E) QUESTION expr(O1) COLON expr(O2) . {
896	R = phvolt_ret_expr(PHVOLT_T_TERNARY, O1, O2, E, status->scanner_state);
897}
898
899expr(R) ::= expr(E) SBRACKET_OPEN COLON slice_offset(N) SBRACKET_CLOSE . {
900	R = phvolt_ret_slice(E, NULL, N, status->scanner_state);
901}
902
903expr(R) ::= expr(E) SBRACKET_OPEN slice_offset(S) COLON SBRACKET_CLOSE . {
904	R = phvolt_ret_slice(E, S, NULL, status->scanner_state);
905}
906
907expr(R) ::= expr(E) SBRACKET_OPEN slice_offset(S) COLON slice_offset(N) SBRACKET_CLOSE . {
908	R = phvolt_ret_slice(E, S, N, status->scanner_state);
909}
910
911%destructor slice_offset {
912#if PHP_VERSION_ID < 70000
913	zval_ptr_dtor(&$$);
914#endif
915}
916
917slice_offset(R) ::= INTEGER(I) . {
918	R = phvolt_ret_literal_zval(PHVOLT_T_INTEGER, I, status->scanner_state);
919}
920
921slice_offset(R) ::= IDENTIFIER(I) . {
922	R = phvolt_ret_literal_zval(PHVOLT_T_IDENTIFIER, I, status->scanner_state);
923}
924
925%destructor array_list {
926#if PHP_VERSION_ID < 70000
927	zval_ptr_dtor(&$$);
928#endif
929}
930
931array_list(R) ::= array_list(L) COMMA array_item(I) . {
932	R = phvolt_ret_zval_list(L, I);
933}
934
935array_list(R) ::= array_item(I) . {
936	R = phvolt_ret_zval_list(NULL, I);
937}
938
939%destructor array_item {
940#if PHP_VERSION_ID < 70000
941	zval_ptr_dtor(&$$);
942#endif
943}
944
945array_item(R) ::= STRING(S) COLON expr(E) . {
946	R = phvolt_ret_named_item(S, E, status->scanner_state);
947}
948
949array_item(R) ::= expr(E) . {
950	R = phvolt_ret_named_item(NULL, E, status->scanner_state);
951}
952
953expr(R) ::= function_call(F) . {
954	R = F;
955}
956
957%destructor function_call {
958#if PHP_VERSION_ID < 70000
959	zval_ptr_dtor(&$$);
960#endif
961}
962
963function_call(R) ::= expr(E) PARENTHESES_OPEN argument_list(L) PARENTHESES_CLOSE . {
964	R = phvolt_ret_func_call(E, L, status->scanner_state);
965}
966
967function_call(R) ::= expr(E) PARENTHESES_OPEN PARENTHESES_CLOSE . {
968	R = phvolt_ret_func_call(E, NULL, status->scanner_state);
969}
970
971%destructor argument_list {
972#if PHP_VERSION_ID < 70000
973	zval_ptr_dtor(&$$);
974#endif
975}
976
977argument_list(R) ::= argument_list(L) COMMA argument_item(I) . {
978	R = phvolt_ret_zval_list(L, I);
979}
980
981argument_list(R) ::= argument_item(I) . {
982	R = phvolt_ret_zval_list(NULL, I);
983}
984
985%destructor argument_item {
986#if PHP_VERSION_ID < 70000
987	zval_ptr_dtor(&$$);
988#endif
989}
990
991argument_item(R) ::= expr(E) . {
992	R = phvolt_ret_named_item(NULL, E, status->scanner_state);
993}
994
995argument_item(R) ::= STRING(S) COLON expr(E) . {
996	R = phvolt_ret_named_item(S, E, status->scanner_state);
997}
998
999expr(R) ::= IDENTIFIER(I) . {
1000	R = phvolt_ret_literal_zval(PHVOLT_T_IDENTIFIER, I, status->scanner_state);
1001}
1002
1003expr(R) ::= INTEGER(I) . {
1004	R = phvolt_ret_literal_zval(PHVOLT_T_INTEGER, I, status->scanner_state);
1005}
1006
1007expr(R) ::= STRING(S) . {
1008	R = phvolt_ret_literal_zval(PHVOLT_T_STRING, S, status->scanner_state);
1009}
1010
1011expr(R) ::= DOUBLE(D) . {
1012	R = phvolt_ret_literal_zval(PHVOLT_T_DOUBLE, D, status->scanner_state);
1013}
1014
1015expr(R) ::= NULL . {
1016	R = phvolt_ret_literal_zval(PHVOLT_T_NULL, NULL, status->scanner_state);
1017}
1018
1019expr(R) ::= FALSE . {
1020	R = phvolt_ret_literal_zval(PHVOLT_T_FALSE, NULL, status->scanner_state);
1021}
1022
1023expr(R) ::= TRUE . {
1024	R = phvolt_ret_literal_zval(PHVOLT_T_TRUE, NULL, status->scanner_state);
1025}
1026