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.php7.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		smart_str_0(&error_str);
139
140		if (error_str.s) {
141			status->syntax_error = estrndup(ZSTR_VAL(error_str.s), ZSTR_LEN(error_str.s));
142			status->syntax_error_len = ZSTR_LEN(error_str.s);
143		} else {
144			status->syntax_error = NULL;
145		}
146	}
147
148	status->status = PHVOLT_PARSING_FAILED;
149}
150
151%token_destructor {
152	if ($$) {
153		if ($$->free_flag) {
154			efree($$->token);
155		}
156		efree($$);
157	}
158}
159
160program ::= volt_language(Q) . {
161	ZVAL_ZVAL(&status->ret, &Q, 1, 1);
162}
163
164volt_language(R) ::= statement_list(L) . {
165	R = L;
166}
167
168%destructor statement_list {
169	zval_ptr_dtor(&$$);
170}
171
172statement_list(R) ::= statement_list(L) statement(S) . {
173	phvolt_ret_zval_list(&R, &L, &S);
174}
175
176statement_list(R) ::= statement(S) . {
177	phvolt_ret_zval_list(&R, NULL, &S);
178}
179
180%destructor statement {
181	zval_ptr_dtor(&$$);
182}
183
184statement(R) ::= raw_fragment(F) . {
185	R = F;
186}
187
188statement(R) ::= if_statement(I) . {
189	R = I;
190}
191
192statement(R) ::= elseif_statement(E) . {
193	R = E;
194}
195
196statement(R) ::= elsefor_statement(E) . {
197	R = E;
198}
199
200statement(R) ::= for_statement(E) . {
201	R = E;
202}
203
204statement(R) ::= switch_statement(E) . {
205	R = E;
206}
207
208statement(R) ::= case_clause(E) . {
209	R = E;
210}
211
212statement(R) ::= set_statement(S) . {
213	R = S;
214}
215
216statement(R) ::= echo_statement(E) . {
217	R = E;
218}
219
220statement(R) ::= block_statement(E) . {
221	R = E;
222}
223
224statement(R) ::= cache_statement(E) . {
225	R = E;
226}
227
228statement(R) ::= extends_statement(E) . {
229	R = E;
230}
231
232statement(R) ::= include_statement(E) . {
233	R = E;
234}
235
236statement(R) ::= do_statement(E) . {
237	R = E;
238}
239
240statement(R) ::= return_statement(E) . {
241	R = E;
242}
243
244statement(R) ::= autoescape_statement(E) . {
245	R = E;
246}
247
248statement(R) ::= raw_statement(E) . {
249	R = E;
250}
251
252statement(R) ::= break_statement(E) . {
253	R = E;
254}
255
256statement(R) ::= continue_statement(E) . {
257	R = E;
258}
259
260statement(R) ::= macro_statement(E) . {
261	R = E;
262}
263
264statement(R) ::= empty_statement(E) . {
265	R = E;
266}
267
268statement(R) ::= macro_call_statement(E) . {
269	R = E;
270}
271
272%destructor if_statement {
273	zval_ptr_dtor(&$$);
274}
275
276/* {% if EXPR %} STMT {% endif %} */
277if_statement(R) ::= OPEN_DELIMITER IF expr(E) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDIF CLOSE_DELIMITER . {
278	phvolt_ret_if_statement(&R, &E, &T, NULL, status->scanner_state);
279}
280
281/* {% if EXPR %} {% endif %} */
282if_statement(R) ::= OPEN_DELIMITER IF expr(E) CLOSE_DELIMITER OPEN_DELIMITER ENDIF CLOSE_DELIMITER . {
283	phvolt_ret_if_statement(&R, &E, NULL, NULL, status->scanner_state);
284}
285
286/* {% if EXPR %} STMT {% esle %} STMT {% endif %} */
287if_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 . {
288	phvolt_ret_if_statement(&R, &E, &T, &F, status->scanner_state);
289}
290
291/* {% if EXPR %} STMT {% esle %} {% endif %} */
292if_statement(R) ::= OPEN_DELIMITER IF expr(E) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ELSE CLOSE_DELIMITER OPEN_DELIMITER ENDIF CLOSE_DELIMITER . {
293	phvolt_ret_if_statement(&R, &E, &T, NULL, status->scanner_state);
294}
295
296/* {% if EXPR %} {% esle %} {% endif %} */
297if_statement(R) ::= OPEN_DELIMITER IF expr(E) CLOSE_DELIMITER OPEN_DELIMITER ELSE CLOSE_DELIMITER OPEN_DELIMITER ENDIF CLOSE_DELIMITER . {
298	phvolt_ret_if_statement(&R, &E, NULL, NULL, status->scanner_state);
299}
300
301%destructor elseif_statement {
302	zval_ptr_dtor(&$$);
303}
304
305elseif_statement(R) ::= OPEN_DELIMITER ELSEIF expr(E) CLOSE_DELIMITER . {
306	phvolt_ret_elseif_statement(&R, &E, status->scanner_state);
307}
308
309%destructor elsefor_statement {
310	zval_ptr_dtor(&$$);
311}
312
313elsefor_statement(R) ::= OPEN_DELIMITER ELSEFOR CLOSE_DELIMITER . {
314	phvolt_ret_elsefor_statement(&R, status->scanner_state);
315}
316
317%destructor for_statement {
318	zval_ptr_dtor(&$$);
319}
320
321for_statement(R) ::= OPEN_DELIMITER FOR IDENTIFIER(I) IN expr(E) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDFOR CLOSE_DELIMITER . {
322	phvolt_ret_for_statement(&R, I, NULL, &E, NULL, &T, status->scanner_state);
323}
324
325for_statement(R) ::= OPEN_DELIMITER FOR IDENTIFIER(I) IN expr(E) IF expr(IE) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDFOR CLOSE_DELIMITER . {
326	phvolt_ret_for_statement(&R, I, NULL, &E, &IE, &T, status->scanner_state);
327}
328
329for_statement(R) ::= OPEN_DELIMITER FOR IDENTIFIER(K) COMMA IDENTIFIER(V) IN expr(E) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDFOR CLOSE_DELIMITER . {
330	phvolt_ret_for_statement(&R, V, K, &E, NULL, &T, status->scanner_state);
331}
332
333for_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 . {
334	phvolt_ret_for_statement(&R, V, K, &E, &IE, &T, status->scanner_state);
335}
336
337%destructor switch_statement {
338	zval_ptr_dtor(&$$);
339}
340
341/* {% switch EXPR %} STMT {% endswitch %} */
342switch_statement(R) ::= OPEN_DELIMITER SWITCH expr(E) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDSWITCH CLOSE_DELIMITER . {
343	phvolt_ret_switch_statement(&R, &E, &T, status->scanner_state);
344}
345
346/* {% switch EXPR %} {% endswitch %} */
347switch_statement(R) ::= OPEN_DELIMITER SWITCH expr(E) CLOSE_DELIMITER OPEN_DELIMITER ENDSWITCH CLOSE_DELIMITER . {
348	phvolt_ret_switch_statement(&R, &E, NULL, status->scanner_state);
349}
350
351%destructor case_clause {
352	zval_ptr_dtor(&$$);
353}
354
355/* {% case EXPR %} {% endcase %} */
356case_clause(R) ::= OPEN_DELIMITER CASE expr(E) CLOSE_DELIMITER . {
357	phvolt_ret_case_clause(&R, &E, status->scanner_state);
358}
359
360/* {% default %} */
361case_clause(R) ::= OPEN_DELIMITER DEFAULT CLOSE_DELIMITER . {
362	phvolt_ret_case_clause(&R, NULL, status->scanner_state);
363}
364
365%destructor set_statement {
366	zval_ptr_dtor(&$$);
367}
368
369set_statement(R) ::= OPEN_DELIMITER SET set_assignments(L) CLOSE_DELIMITER . {
370	phvolt_ret_set_statement(&R, &L);
371}
372
373%destructor set_assignments {
374	zval_ptr_dtor(&$$);
375}
376
377set_assignments(R) ::= set_assignments(L) COMMA set_assignment(S) . {
378	phvolt_ret_zval_list(&R, &L, &S);
379}
380
381set_assignments(R) ::= set_assignment(S) . {
382	phvolt_ret_zval_list(&R, NULL, &S);
383}
384
385%destructor set_assignment {
386	zval_ptr_dtor(&$$);
387}
388
389set_assignment(R) ::= assignable_expr(I) ASSIGN expr(E) . {
390	phvolt_ret_set_assignment(&R, &I, PHVOLT_T_ASSIGN, &E, status->scanner_state);
391}
392
393set_assignment(R) ::= assignable_expr(I) ADD_ASSIGN expr(E) . {
394	phvolt_ret_set_assignment(&R, &I, PHVOLT_T_ADD_ASSIGN, &E, status->scanner_state);
395}
396
397set_assignment(R) ::= assignable_expr(I) SUB_ASSIGN expr(E) . {
398	phvolt_ret_set_assignment(&R, &I, PHVOLT_T_SUB_ASSIGN, &E, status->scanner_state);
399}
400
401set_assignment(R) ::= assignable_expr(I) MUL_ASSIGN expr(E) . {
402	phvolt_ret_set_assignment(&R, &I, PHVOLT_T_MUL_ASSIGN, &E, status->scanner_state);
403}
404
405set_assignment(R) ::= assignable_expr(I) DIV_ASSIGN expr(E) . {
406	phvolt_ret_set_assignment(&R, &I, PHVOLT_T_DIV_ASSIGN, &E, status->scanner_state);
407}
408
409assignable_expr(R) ::= IDENTIFIER(I) . {
410	phvolt_ret_literal_zval(&R, PHVOLT_T_IDENTIFIER, I, status->scanner_state);
411}
412
413assignable_expr(R) ::= assignable_expr(E) SBRACKET_OPEN expr(D) SBRACKET_CLOSE . {
414	phvolt_ret_expr(&R, PHVOLT_T_ARRAYACCESS, &E, &D, NULL, status->scanner_state);
415}
416
417assignable_expr(R) ::= assignable_expr(E) DOT assignable_expr(D)  . {
418	phvolt_ret_expr(&R, PHVOLT_T_DOT, &E, &D, NULL, status->scanner_state);
419}
420
421%destructor macro_statement {
422	zval_ptr_dtor(&$$);
423}
424
425macro_statement(R) ::= OPEN_DELIMITER MACRO IDENTIFIER(I) PARENTHESES_OPEN PARENTHESES_CLOSE CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDMACRO CLOSE_DELIMITER . {
426	phvolt_ret_macro_statement(&R, I, NULL, &T, status->scanner_state);
427}
428
429macro_statement(R) ::= OPEN_DELIMITER MACRO IDENTIFIER(I) PARENTHESES_OPEN macro_parameters(P) PARENTHESES_CLOSE CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDMACRO CLOSE_DELIMITER . {
430	phvolt_ret_macro_statement(&R, I, &P, &T, status->scanner_state);
431}
432
433%destructor macro_parameters {
434	zval_ptr_dtor(&$$);
435}
436
437macro_parameters(R) ::= macro_parameters(L) COMMA macro_parameter(I) . {
438	phvolt_ret_zval_list(&R, &L, &I);
439}
440
441macro_parameters(R) ::= macro_parameter(I) . {
442	phvolt_ret_zval_list(&R, NULL, &I);
443}
444
445%destructor macro_parameter {
446	zval_ptr_dtor(&$$);
447}
448
449macro_parameter(R) ::= IDENTIFIER(I) . {
450	phvolt_ret_macro_parameter(&R, I, NULL, status->scanner_state);
451}
452
453macro_parameter(R) ::= IDENTIFIER(I) ASSIGN macro_parameter_default(D) . {
454	phvolt_ret_macro_parameter(&R, I, &D, status->scanner_state);
455}
456
457macro_parameter_default(R) ::= INTEGER(I) . {
458	phvolt_ret_literal_zval(&R, PHVOLT_T_INTEGER, I, status->scanner_state);
459}
460
461macro_parameter_default(R) ::= STRING(S) . {
462	phvolt_ret_literal_zval(&R, PHVOLT_T_STRING, S, status->scanner_state);
463}
464
465macro_parameter_default(R) ::= DOUBLE(D) . {
466	phvolt_ret_literal_zval(&R, PHVOLT_T_DOUBLE, D, status->scanner_state);
467}
468
469macro_parameter_default(R) ::= NULL . {
470	phvolt_ret_literal_zval(&R, PHVOLT_T_NULL, NULL, status->scanner_state);
471}
472
473macro_parameter_default(R) ::= FALSE . {
474	phvolt_ret_literal_zval(&R, PHVOLT_T_FALSE, NULL, status->scanner_state);
475}
476
477macro_parameter_default(R) ::= TRUE . {
478	phvolt_ret_literal_zval(&R, PHVOLT_T_TRUE, NULL, status->scanner_state);
479}
480
481%destructor macro_call_statement {
482	zval_ptr_dtor(&$$);
483}
484
485macro_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 . {
486	phvolt_ret_macro_call_statement(&R, &E, &L, &C, status->scanner_state);
487}
488
489macro_call_statement(R) ::= OPEN_DELIMITER CALL expr(E) PARENTHESES_OPEN PARENTHESES_CLOSE CLOSE_DELIMITER OPEN_DELIMITER ENDCALL CLOSE_DELIMITER . {
490	phvolt_ret_macro_call_statement(&R, &E, NULL, NULL, status->scanner_state);
491}
492
493%destructor empty_statement {
494	zval_ptr_dtor(&$$);
495}
496
497empty_statement(R) ::= OPEN_DELIMITER CLOSE_DELIMITER . {
498	phvolt_ret_empty_statement(&R, status->scanner_state);
499}
500
501%destructor echo_statement {
502	zval_ptr_dtor(&$$);
503}
504
505echo_statement(R) ::= OPEN_EDELIMITER expr(E) CLOSE_EDELIMITER . {
506	phvolt_ret_echo_statement(&R, &E, status->scanner_state);
507}
508
509%destructor block_statement {
510	zval_ptr_dtor(&$$);
511}
512
513block_statement(R) ::= OPEN_DELIMITER BLOCK IDENTIFIER(I) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDBLOCK CLOSE_DELIMITER . {
514	phvolt_ret_block_statement(&R, I, &T, status->scanner_state);
515}
516
517block_statement(R) ::= OPEN_DELIMITER BLOCK IDENTIFIER(I) CLOSE_DELIMITER OPEN_DELIMITER ENDBLOCK CLOSE_DELIMITER . {
518	phvolt_ret_block_statement(&R, I, NULL, status->scanner_state);
519}
520
521%destructor cache_statement {
522	zval_ptr_dtor(&$$);
523}
524
525cache_statement(R) ::= OPEN_DELIMITER CACHE expr(E) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDCACHE CLOSE_DELIMITER . {
526	phvolt_ret_cache_statement(&R, &E, NULL, &T, status->scanner_state);
527}
528
529cache_statement(R) ::= OPEN_DELIMITER CACHE expr(E) cache_lifetime(N) CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDCACHE CLOSE_DELIMITER . {
530	phvolt_ret_cache_statement(&R, &E, &N, &T, status->scanner_state);
531}
532
533%destructor cache_lifetime {
534	zval_ptr_dtor(&$$);
535}
536
537cache_lifetime(R) ::= INTEGER(I) . {
538	phvolt_ret_literal_zval(&R, PHVOLT_T_INTEGER, I, status->scanner_state);
539}
540
541cache_lifetime(R) ::= IDENTIFIER(I) . {
542	phvolt_ret_literal_zval(&R, PHVOLT_T_IDENTIFIER, I, status->scanner_state);
543}
544
545%destructor raw_statement {
546	zval_ptr_dtor(&$$);
547}
548
549raw_statement(R) ::= OPEN_DELIMITER RAW CLOSE_DELIMITER statement(T) OPEN_DELIMITER ENDRAW CLOSE_DELIMITER . {
550	phvolt_ret_raw_statement(&R, &T, status->scanner_state);
551}
552
553%destructor extends_statement {
554	zval_ptr_dtor(&$$);
555}
556
557extends_statement(R) ::= OPEN_DELIMITER EXTENDS expr(S) CLOSE_DELIMITER . {
558	phvolt_ret_extends_statement(&R, &S, status->scanner_state);
559}
560
561%destructor include_statement {
562	zval_ptr_dtor(&$$);
563}
564
565include_statement(R) ::= OPEN_DELIMITER INCLUDE expr(E) CLOSE_DELIMITER . {
566	phvolt_ret_include_statement(&R, &E, NULL, status->scanner_state);
567}
568
569include_statement(R) ::= OPEN_DELIMITER INCLUDE expr(E) WITH expr(P) CLOSE_DELIMITER . {
570	phvolt_ret_include_statement(&R, &E, &P, status->scanner_state);
571}
572
573%destructor do_statement {
574	zval_ptr_dtor(&$$);
575}
576
577do_statement(R) ::= OPEN_DELIMITER DO expr(E) CLOSE_DELIMITER . {
578	phvolt_ret_do_statement(&R, &E, status->scanner_state);
579}
580
581%destructor return_statement {
582	zval_ptr_dtor(&$$);
583}
584
585return_statement(R) ::= OPEN_DELIMITER RETURN expr(E) CLOSE_DELIMITER . {
586	phvolt_ret_return_statement(&R, &E, status->scanner_state);
587}
588
589%destructor autoescape_statement {
590	zval_ptr_dtor(&$$);
591}
592
593autoescape_statement(R) ::= OPEN_DELIMITER AUTOESCAPE FALSE CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDAUTOESCAPE CLOSE_DELIMITER . {
594	phvolt_ret_autoescape_statement(&R, 0, &T, status->scanner_state);
595}
596
597autoescape_statement(R) ::= OPEN_DELIMITER AUTOESCAPE TRUE CLOSE_DELIMITER statement_list(T) OPEN_DELIMITER ENDAUTOESCAPE CLOSE_DELIMITER . {
598	phvolt_ret_autoescape_statement(&R, 1, &T, status->scanner_state);
599}
600
601%destructor break_statement {
602	zval_ptr_dtor(&$$);
603}
604
605break_statement(R) ::= OPEN_DELIMITER BREAK CLOSE_DELIMITER . {
606	phvolt_ret_break_statement(&R, status->scanner_state);
607}
608
609%destructor continue_statement {
610	zval_ptr_dtor(&$$);
611}
612
613continue_statement(R) ::= OPEN_DELIMITER CONTINUE CLOSE_DELIMITER . {
614	phvolt_ret_continue_statement(&R, status->scanner_state);
615}
616
617%destructor raw_fragment {
618	zval_ptr_dtor(&$$);
619}
620
621raw_fragment(R) ::= RAW_FRAGMENT(F) . {
622	phvolt_ret_literal_zval(&R, PHVOLT_T_RAW_FRAGMENT, F, status->scanner_state);
623}
624
625%destructor expr {
626	zval_ptr_dtor(&$$);
627}
628
629expr(R) ::= MINUS expr(E) . {
630	phvolt_ret_expr(&R, PHVOLT_T_MINUS, NULL, &E, NULL, status->scanner_state);
631}
632
633expr(R) ::= PLUS expr(E) . {
634	phvolt_ret_expr(&R, PHVOLT_T_PLUS, NULL, &E, NULL, status->scanner_state);
635}
636
637expr(R) ::= expr(O1) MINUS expr(O2) . {
638	phvolt_ret_expr(&R, PHVOLT_T_SUB, &O1, &O2, NULL, status->scanner_state);
639}
640
641expr(R) ::= expr(O1) PLUS expr(O2) . {
642	phvolt_ret_expr(&R, PHVOLT_T_ADD, &O1, &O2, NULL, status->scanner_state);
643}
644
645expr(R) ::= expr(O1) TIMES expr(O2) . {
646	phvolt_ret_expr(&R, PHVOLT_T_MUL, &O1, &O2, NULL, status->scanner_state);
647}
648
649expr(R) ::= expr(O1) TIMES TIMES expr(O2) . {
650	phvolt_ret_expr(&R, PHVOLT_T_POW, &O1, &O2, NULL, status->scanner_state);
651}
652
653expr(R) ::= expr(O1) DIVIDE expr(O2) . {
654	phvolt_ret_expr(&R, PHVOLT_T_DIV, &O1, &O2, NULL, status->scanner_state);
655}
656
657expr(R) ::= expr(O1) DIVIDE DIVIDE expr(O2) . {
658	phvolt_ret_expr(&R, PHVOLT_T_MOD, &O1, &O2, NULL, status->scanner_state);
659}
660
661expr(R) ::= expr(O1) MOD expr(O2) . {
662	phvolt_ret_expr(&R, PHVOLT_T_MOD, &O1, &O2, NULL, status->scanner_state);
663}
664
665expr(R) ::= expr(O1) AND expr(O2) . {
666	phvolt_ret_expr(&R, PHVOLT_T_AND, &O1, &O2, NULL, status->scanner_state);
667}
668
669expr(R) ::= expr(O1) OR expr(O2) . {
670	phvolt_ret_expr(&R, PHVOLT_T_OR, &O1, &O2, NULL, status->scanner_state);
671}
672
673expr(R) ::= expr(O1) CONCAT expr(O2) . {
674	phvolt_ret_expr(&R, PHVOLT_T_CONCAT, &O1, &O2, NULL, status->scanner_state);
675}
676
677expr(R) ::= expr(O1) PIPE expr(O2) . {
678	phvolt_ret_expr(&R, PHVOLT_T_PIPE, &O1, &O2, NULL, status->scanner_state);
679}
680
681expr(R) ::= expr(O1) RANGE expr(O2) . {
682	phvolt_ret_expr(&R, PHVOLT_T_RANGE, &O1, &O2, NULL, status->scanner_state);
683}
684
685expr(R) ::= expr(O1) EQUALS expr(O2) . {
686	phvolt_ret_expr(&R, PHVOLT_T_EQUALS, &O1, &O2, NULL, status->scanner_state);
687}
688
689expr(R) ::= expr(O1) NOTEQUALS DEFINED . {
690	phvolt_ret_expr(&R, PHVOLT_T_NOT_ISSET, &O1, NULL, NULL, status->scanner_state);
691}
692
693expr(R) ::= expr(O1) IS DEFINED . {
694	phvolt_ret_expr(&R, PHVOLT_T_ISSET, &O1, NULL, NULL, status->scanner_state);
695}
696
697expr(R) ::= expr(O1) NOTEQUALS EMPTY . {
698	phvolt_ret_expr(&R, PHVOLT_T_NOT_ISEMPTY, &O1, NULL, NULL, status->scanner_state);
699}
700
701expr(R) ::= expr(O1) IS EMPTY . {
702	phvolt_ret_expr(&R, PHVOLT_T_ISEMPTY, &O1, NULL, NULL, status->scanner_state);
703}
704
705expr(R) ::= expr(O1) NOTEQUALS EVEN . {
706	phvolt_ret_expr(&R, PHVOLT_T_NOT_ISEVEN, &O1, NULL, NULL, status->scanner_state);
707}
708
709expr(R) ::= expr(O1) IS EVEN . {
710	phvolt_ret_expr(&R, PHVOLT_T_ISEVEN, &O1, NULL, NULL, status->scanner_state);
711}
712
713expr(R) ::= expr(O1) NOTEQUALS ODD . {
714	phvolt_ret_expr(&R, PHVOLT_T_NOT_ISODD, &O1, NULL, NULL, status->scanner_state);
715}
716
717expr(R) ::= expr(O1) IS ODD . {
718	phvolt_ret_expr(&R, PHVOLT_T_ISODD, &O1, NULL, NULL, status->scanner_state);
719}
720
721expr(R) ::= expr(O1) NOTEQUALS NUMERIC . {
722	phvolt_ret_expr(&R, PHVOLT_T_NOT_ISNUMERIC, &O1, NULL, NULL, status->scanner_state);
723}
724
725expr(R) ::= expr(O1) IS NUMERIC . {
726	phvolt_ret_expr(&R, PHVOLT_T_ISNUMERIC, &O1, NULL, NULL, status->scanner_state);
727}
728
729expr(R) ::= expr(O1) NOTEQUALS SCALAR . {
730	phvolt_ret_expr(&R, PHVOLT_T_NOT_ISSCALAR, &O1, NULL, NULL, status->scanner_state);
731}
732
733expr(R) ::= expr(O1) IS SCALAR . {
734	phvolt_ret_expr(&R, PHVOLT_T_ISSCALAR, &O1, NULL, NULL, status->scanner_state);
735}
736
737expr(R) ::= expr(O1) NOTEQUALS ITERABLE . {
738	phvolt_ret_expr(&R, PHVOLT_T_NOT_ISITERABLE, &O1, NULL, NULL, status->scanner_state);
739}
740
741expr(R) ::= expr(O1) IS ITERABLE . {
742	phvolt_ret_expr(&R, PHVOLT_T_ISITERABLE, &O1, NULL, NULL, status->scanner_state);
743}
744
745expr(R) ::= expr(O1) IS expr(O2) . {
746	phvolt_ret_expr(&R, PHVOLT_T_IS, &O1, &O2, NULL, status->scanner_state);
747}
748
749expr(R) ::= expr(O1) NOTEQUALS expr(O2) . {
750	phvolt_ret_expr(&R, PHVOLT_T_NOTEQUALS, &O1, &O2, NULL, status->scanner_state);
751}
752
753expr(R) ::= expr(O1) IDENTICAL expr(O2) . {
754	phvolt_ret_expr(&R, PHVOLT_T_IDENTICAL, &O1, &O2, NULL, status->scanner_state);
755}
756
757expr(R) ::= expr(O1) NOTIDENTICAL expr(O2) . {
758	phvolt_ret_expr(&R, PHVOLT_T_NOTIDENTICAL, &O1, &O2, NULL, status->scanner_state);
759}
760
761expr(R) ::= expr(O1) LESS expr(O2) . {
762	phvolt_ret_expr(&R, PHVOLT_T_LESS, &O1, &O2, NULL, status->scanner_state);
763}
764
765expr(R) ::= expr(O1) GREATER expr(O2) . {
766	phvolt_ret_expr(&R, PHVOLT_T_GREATER, &O1, &O2, NULL, status->scanner_state);
767}
768
769expr(R) ::= expr(O1) GREATEREQUAL expr(O2) . {
770	phvolt_ret_expr(&R, PHVOLT_T_GREATEREQUAL, &O1, &O2, NULL, status->scanner_state);
771}
772
773expr(R) ::= expr(O1) LESSEQUAL expr(O2) . {
774	phvolt_ret_expr(&R, PHVOLT_T_LESSEQUAL, &O1, &O2, NULL, status->scanner_state);
775}
776
777expr(R) ::= expr(O1) DOT expr(O2) . {
778	phvolt_ret_expr(&R, PHVOLT_T_DOT, &O1, &O2, NULL, status->scanner_state);
779}
780
781expr(R) ::= expr(O1) IN expr(O2) . {
782	phvolt_ret_expr(&R, PHVOLT_T_IN, &O1, &O2, NULL, status->scanner_state);
783}
784
785expr(R) ::= expr(O1) NOT IN expr(O2) . {
786	phvolt_ret_expr(&R, PHVOLT_T_NOT_IN, &O1, &O2, NULL, status->scanner_state);
787}
788
789expr(R) ::= NOT expr(E) . {
790	phvolt_ret_expr(&R, PHVOLT_T_NOT, NULL, &E, NULL, status->scanner_state);
791}
792
793expr(R) ::= expr(E) INCR . {
794	phvolt_ret_expr(&R, PHVOLT_T_INCR, &E, NULL, NULL, status->scanner_state);
795}
796
797expr(R) ::= expr(E) DECR . {
798	phvolt_ret_expr(&R, PHVOLT_T_DECR, &E, NULL, NULL, status->scanner_state);
799}
800
801expr(R) ::= PARENTHESES_OPEN expr(E) PARENTHESES_CLOSE . {
802	phvolt_ret_expr(&R, PHVOLT_T_ENCLOSED, &E, NULL, NULL, status->scanner_state);
803}
804
805expr(R) ::= SBRACKET_OPEN SBRACKET_CLOSE . {
806	phvolt_ret_expr(&R, PHVOLT_T_ARRAY, NULL, NULL, NULL, status->scanner_state);
807}
808
809expr(R) ::= SBRACKET_OPEN array_list(A) SBRACKET_CLOSE . {
810	phvolt_ret_expr(&R, PHVOLT_T_ARRAY, &A, NULL, NULL, status->scanner_state);
811}
812
813expr(R) ::= CBRACKET_OPEN CBRACKET_CLOSE . {
814	phvolt_ret_expr(&R, PHVOLT_T_ARRAY, NULL, NULL, NULL, status->scanner_state);
815}
816
817expr(R) ::= CBRACKET_OPEN array_list(A) CBRACKET_CLOSE . {
818	phvolt_ret_expr(&R, PHVOLT_T_ARRAY, &A, NULL, NULL, status->scanner_state);
819}
820
821expr(R) ::= expr(E) SBRACKET_OPEN expr(D) SBRACKET_CLOSE . {
822	phvolt_ret_expr(&R, PHVOLT_T_ARRAYACCESS, &E, &D, NULL, status->scanner_state);
823}
824
825expr(R) ::= expr(E) QUESTION expr(O1) COLON expr(O2) . {
826	phvolt_ret_expr(&R, PHVOLT_T_TERNARY, &O1, &O2, &E, status->scanner_state);
827}
828
829expr(R) ::= expr(E) SBRACKET_OPEN COLON slice_offset(N) SBRACKET_CLOSE . {
830	phvolt_ret_slice(&R, &E, NULL, &N, status->scanner_state);
831}
832
833expr(R) ::= expr(E) SBRACKET_OPEN slice_offset(S) COLON SBRACKET_CLOSE . {
834	phvolt_ret_slice(&R, &E, &S, NULL, status->scanner_state);
835}
836
837expr(R) ::= expr(E) SBRACKET_OPEN slice_offset(S) COLON slice_offset(N) SBRACKET_CLOSE . {
838	phvolt_ret_slice(&R, &E, &S, &N, status->scanner_state);
839}
840
841%destructor slice_offset {
842	zval_ptr_dtor(&$$);
843}
844
845slice_offset(R) ::= INTEGER(I) . {
846	phvolt_ret_literal_zval(&R, PHVOLT_T_INTEGER, I, status->scanner_state);
847}
848
849slice_offset(R) ::= IDENTIFIER(I) . {
850	phvolt_ret_literal_zval(&R, PHVOLT_T_IDENTIFIER, I, status->scanner_state);
851}
852
853%destructor array_list {
854	zval_ptr_dtor(&$$);
855}
856
857array_list(R) ::= array_list(L) COMMA array_item(I) . {
858	phvolt_ret_zval_list(&R, &L, &I);
859}
860
861array_list(R) ::= array_item(I) . {
862	phvolt_ret_zval_list(&R, NULL, &I);
863}
864
865%destructor array_item {
866	zval_ptr_dtor(&$$);
867}
868
869array_item(R) ::= STRING(S) COLON expr(E) . {
870	phvolt_ret_named_item(&R, S, &E, status->scanner_state);
871}
872
873array_item(R) ::= expr(E) . {
874	phvolt_ret_named_item(&R, NULL, &E, status->scanner_state);
875}
876
877expr(R) ::= function_call(F) . {
878	R = F;
879}
880
881%destructor function_call {
882	zval_ptr_dtor(&$$);
883}
884
885function_call(R) ::= expr(E) PARENTHESES_OPEN argument_list(L) PARENTHESES_CLOSE . {
886	phvolt_ret_func_call(&R, &E, &L, status->scanner_state);
887}
888
889function_call(R) ::= expr(E) PARENTHESES_OPEN PARENTHESES_CLOSE . {
890	phvolt_ret_func_call(&R, &E, NULL, status->scanner_state);
891}
892
893%destructor argument_list {
894	zval_ptr_dtor(&$$);
895}
896
897argument_list(R) ::= argument_list(L) COMMA argument_item(I) . {
898	phvolt_ret_zval_list(&R, &L, &I);
899}
900
901argument_list(R) ::= argument_item(I) . {
902	phvolt_ret_zval_list(&R, NULL, &I);
903}
904
905%destructor argument_item {
906	zval_ptr_dtor(&$$);
907}
908
909argument_item(R) ::= expr(E) . {
910	phvolt_ret_named_item(&R, NULL, &E, status->scanner_state);
911}
912
913argument_item(R) ::= STRING(S) COLON expr(E) . {
914	phvolt_ret_named_item(&R, S, &E, status->scanner_state);
915}
916
917expr(R) ::= IDENTIFIER(I) . {
918	phvolt_ret_literal_zval(&R, PHVOLT_T_IDENTIFIER, I, status->scanner_state);
919}
920
921expr(R) ::= INTEGER(I) . {
922	phvolt_ret_literal_zval(&R, PHVOLT_T_INTEGER, I, status->scanner_state);
923}
924
925expr(R) ::= STRING(S) . {
926	phvolt_ret_literal_zval(&R, PHVOLT_T_STRING, S, status->scanner_state);
927}
928
929expr(R) ::= DOUBLE(D) . {
930	phvolt_ret_literal_zval(&R, PHVOLT_T_DOUBLE, D, status->scanner_state);
931}
932
933expr(R) ::= NULL . {
934	phvolt_ret_literal_zval(&R, PHVOLT_T_NULL, NULL, status->scanner_state);
935}
936
937expr(R) ::= FALSE . {
938	phvolt_ret_literal_zval(&R, PHVOLT_T_FALSE, NULL, status->scanner_state);
939}
940
941expr(R) ::= TRUE . {
942	phvolt_ret_literal_zval(&R, PHVOLT_T_TRUE, NULL, status->scanner_state);
943}
944