4 +---------------------------------------------------------------------------------+
5 | Copyright (c) 2010 Haanga |
6 +---------------------------------------------------------------------------------+
7 | Redistribution and use in source and binary forms, with or without |
8 | modification, are permitted provided that the following conditions are met: |
9 | 1. Redistributions of source code must retain the above copyright |
10 | notice, this list of conditions and the following disclaimer. |
12 | 2. Redistributions in binary form must reproduce the above copyright |
13 | notice, this list of conditions and the following disclaimer in the |
14 | documentation and/or other materials provided with the distribution. |
16 | 3. All advertising materials mentioning features or use of this software |
17 | must display the following acknowledgement: |
18 | This product includes software developed by César D. Rodas. |
20 | 4. Neither the name of the César D. Rodas nor the |
21 | names of its contributors may be used to endorse or promote products |
22 | derived from this software without specific prior written permission. |
24 | THIS SOFTWARE IS PROVIDED BY CÉSAR D. RODAS ''AS IS'' AND ANY |
25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
27 | DISCLAIMED. IN NO EVENT SHALL CÉSAR D. RODAS BE LIABLE FOR ANY |
28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE |
34 +---------------------------------------------------------------------------------+
35 | Authors: César Rodas <crodas@php.net> |
36 +---------------------------------------------------------------------------------+
40 %declare_class
{ class Parser
}
52 %nonassoc T_GT T_GE T_LT T_LE.
55 %left T_TIMES T_DIV T_MOD.
59 foreach
($this->yy_get_expected_tokens
($yymajor) as
$token) {
60 $expect[] = self
::$yyTokenName[$token];
62 throw new Exception
('Unexpected ' .
$this->tokenName
($yymajor) .
'(' .
$TOKEN.
'), expected one of: ' . implode
(',', $expect));
66 start
::= body
(B
).
{ $this->body
= B
; }
68 body
(A
) ::= body
(B
) code
(C
).
{ A
=B
; A
[] = C
; }
69 body
(A
) ::= .
{ A
= array
(); }
71 /* List of statements */
72 code
(A
) ::= T_OPEN_TAG stmts
(B
).
{ A
= B
; }
73 code
(A
) ::= T_HTML
(B
).
{ A
= array
('operation' => 'html', 'html' => B
); }
74 code
(A
) ::= T_COMMENT_OPEN T_COMMENT
(B
).
{ B
=rtrim
(B
); A
= array
('operation' => 'comment', 'comment' => substr
(B
, 0, strlen
(B
)-2)); }
75 code
(A
) ::= T_PRINT_OPEN filtered_var
(B
) T_PRINT_CLOSE.
{ A
= array
('operation' => 'print_var', 'variable' => B
); }
77 stmts
(A
) ::= T_EXTENDS var_or_string
(B
) T_CLOSE_TAG.
{ A
= array
('operation' => 'base', B
); }
78 stmts
(A
) ::= stmt
(B
) T_CLOSE_TAG.
{ A
= B
; }
79 stmts
(A
) ::= for_stmt
(B
).
{ A
= B
; }
80 stmts
(A
) ::= ifchanged_stmt
(B
).
{ A
= B
; }
81 stmts
(A
) ::= block_stmt
(B
).
{ A
= B
; }
82 stmts
(A
) ::= filter_stmt
(B
).
{ A
= B
; }
83 stmts
(A
) ::= if_stmt
(B
).
{ A
= B
; }
84 stmts
(A
) ::= T_INCLUDE var_or_string
(B
) T_CLOSE_TAG.
{ A
= array
('operation' => 'include', B
); }
85 stmts
(A
) ::= custom_tag
(B
).
{ A
= B
; }
86 stmts
(A
) ::= alias
(B
).
{ A
= B
; }
87 stmts
(A
) ::= ifequal
(B
).
{ A
= B
; }
88 stmts
(A
) ::= T_AUTOESCAPE T_OFF|T_ON
(B
) T_CLOSE_TAG body
(X
) T_OPEN_TAG T_END_AUTOESCAPE T_CLOSE_TAG.
{ A
= array
('operation' => 'autoescape', 'value' => strtolower
(@B
), 'body' => X
); }
93 custom_tag
(A
) ::= T_CUSTOM_TAG
(B
) T_CLOSE_TAG.
{ A
= array
('operation' => 'custom_tag', 'name' => B
, 'list'=>array
()); }
94 custom_tag
(A
) ::= T_CUSTOM_TAG
(B
) T_AS varname
(C
) T_CLOSE_TAG.
{ A
= array
('operation' => 'custom_tag', 'name' => B
, 'as' => C
, 'list'=>array
()); }
95 custom_tag
(A
) ::= T_CUSTOM_TAG
(B
) var_list
(X
) T_CLOSE_TAG.
{ A
= array
('operation' => 'custom_tag', 'name' => B
, 'list' => X
); }
96 custom_tag
(A
) ::= T_CUSTOM_TAG
(B
) var_list
(X
) T_AS varname
(C
) T_CLOSE_TAG.
{ A
= array
('operation' => 'custom_tag', 'name' => B
, 'as' => C
, 'list' => X
); }
98 custom_tag
(A
) ::= T_CUSTOM_BLOCK
(B
) T_CLOSE_TAG body
(X
) T_OPEN_TAG T_CUSTOM_END
(C
) T_CLOSE_TAG.
{ if
('end'.B
!= C
) { throw new Exception
("Unexpected ".C
); } A
= array
('operation' => 'custom_tag', 'name' => B
, 'body' => X
, 'list' => array
());}
101 alias
(A
) ::= T_WITH varname
(B
) T_AS varname
(C
) T_CLOSE_TAG body
(X
) T_OPEN_TAG T_ENDWITH T_CLOSE_TAG.
{ A
= array
('operation' => 'alias', 'var' => B
, 'as' => C
, 'body' => X
); }
103 /* Simple statements (don't require a end_tag or a body ) */
104 stmt
(A
) ::= regroup
(B
).
{ A
= B
; }
105 stmt
::= T_LOAD
string(B
).
{
107 throw new Haanga_CompilerException
(B.
" is not a valid file");
113 for_stmt
(A
) ::= T_FOR varname
(B
) T_IN filtered_var
(C
) T_CLOSE_TAG body
(D
) T_OPEN_TAG T_CLOSEFOR T_CLOSE_TAG.
{
114 A
= array
('operation' => 'loop', 'variable' => B
, 'array' => C
, 'body' => D
, 'index' => NULL
);
116 for_stmt
(A
) ::= T_FOR varname
(I
) T_COMMA varname
(B
) T_IN filtered_var
(C
) T_CLOSE_TAG body
(D
) T_OPEN_TAG T_CLOSEFOR T_CLOSE_TAG.
{
117 A
= array
('operation' => 'loop', 'variable' => B
, 'array' => C
, 'body' => D
, 'index' => I
);
119 for_stmt
(A
) ::= T_FOR varname
(B
) T_IN filtered_var
(C
) T_CLOSE_TAG body
(D
) T_OPEN_TAG T_EMPTY T_CLOSE_TAG body
(E
) T_OPEN_TAG T_CLOSEFOR T_CLOSE_TAG.
{
120 A
= array
('operation' => 'loop', 'variable' => B
, 'array' => C
, 'body' => D
, 'empty' => E
, 'index' => NULL
);
122 for_stmt
(A
) ::= T_FOR varname
(I
) T_COMMA varname
(B
) T_IN filtered_var
(C
) T_CLOSE_TAG body
(D
) T_OPEN_TAG T_EMPTY T_CLOSE_TAG body
(E
) T_OPEN_TAG T_CLOSEFOR T_CLOSE_TAG.
{
123 A
= array
('operation' => 'loop', 'variable' => B
, 'array' => C
, 'body' => D
, 'empty' => E
, 'index' => I
);
126 if_stmt
(A
) ::= T_IF expr
(B
) T_CLOSE_TAG body
(X
) T_OPEN_TAG T_ENDIF T_CLOSE_TAG.
{ A
= array
('operation' => 'if', 'expr' => B
, 'body' => X
); }
127 if_stmt
(A
) ::= T_IF expr
(B
) T_CLOSE_TAG body
(X
) T_OPEN_TAG T_ELSE T_CLOSE_TAG body
(Y
) T_OPEN_TAG T_ENDIF T_CLOSE_TAG.
{ A
= array
('operation' => 'if', 'expr' => B
, 'body' => X
, 'else' => Y
); }
130 ifchanged_stmt
(A
) ::= T_IFCHANGED T_CLOSE_TAG body
(B
) T_OPEN_TAG T_ENDIFCHANGED T_CLOSE_TAG.
{
131 A
= array
('operation' => 'ifchanged', 'body' => B
);
134 ifchanged_stmt
(A
) ::= T_IFCHANGED var_list
(X
) T_CLOSE_TAG body
(B
) T_OPEN_TAG T_ENDIFCHANGED T_CLOSE_TAG.
{
135 A
= array
('operation' => 'ifchanged', 'body' => B
, 'check' => X
);
137 ifchanged_stmt
(A
) ::= T_IFCHANGED T_CLOSE_TAG body
(B
) T_OPEN_TAG T_ELSE T_CLOSE_TAG body
(C
) T_OPEN_TAG T_ENDIFCHANGED T_CLOSE_TAG.
{
138 A
= array
('operation' => 'ifchanged', 'body' => B
, 'else' => C
);
141 ifchanged_stmt
(A
) ::= T_IFCHANGED var_list
(X
) T_CLOSE_TAG body
(B
) T_OPEN_TAG T_ELSE T_CLOSE_TAG body
(C
) T_OPEN_TAG T_ENDIFCHANGED T_CLOSE_TAG.
{
142 A
= array
('operation' => 'ifchanged', 'body' => B
, 'check' => X
, 'else' => C
);
146 ifequal
(A
) ::= T_IFEQUAL fvar_or_string
(B
) fvar_or_string
(C
) T_CLOSE_TAG body
(X
) T_OPEN_TAG T_END_IFEQUAL T_CLOSE_TAG.
{ A
= array
('operation' => 'ifequal', 'cmp' => '==', 1 => B
, 2 => C
, 'body' => X
); }
147 ifequal
(A
) ::= T_IFEQUAL fvar_or_string
(B
) fvar_or_string
(C
) T_CLOSE_TAG body
(X
) T_OPEN_TAG T_ELSE T_CLOSE_TAG body
(Y
) T_OPEN_TAG T_END_IFEQUAL T_CLOSE_TAG.
{ A
= array
('operation' => 'ifequal', 'cmp' => '==', 1 => B
, 2 => C
, 'body' => X
, 'else' => Y
); }
148 ifequal
(A
) ::= T_IFNOTEQUAL fvar_or_string
(B
) fvar_or_string
(C
) T_CLOSE_TAG body
(X
) T_OPEN_TAG T_END_IFNOTEQUAL T_CLOSE_TAG.
{ A
= array
('operation' => 'ifequal', 'cmp' => '!=', 1 => B
, 2 => C
, 'body' => X
); }
149 ifequal
(A
) ::= T_IFNOTEQUAL fvar_or_string
(B
) fvar_or_string
(C
) T_CLOSE_TAG body
(X
) T_OPEN_TAG T_ELSE T_CLOSE_TAG body
(Y
) T_OPEN_TAG T_END_IFNOTEQUAL T_CLOSE_TAG.
{ A
= array
('operation' => 'ifequal', 'cmp' => '!=', 1 => B
, 2 => C
, 'body' => X
, 'else' => Y
); }
153 block_stmt
(A
) ::= T_BLOCK varname
(B
) T_CLOSE_TAG body
(C
) T_OPEN_TAG T_END_BLOCK T_CLOSE_TAG.
{ A
= array
('operation' => 'block', 'name' => B
, 'body' => C
); }
155 block_stmt
(A
) ::= T_BLOCK varname
(B
) T_CLOSE_TAG body
(C
) T_OPEN_TAG T_END_BLOCK varname T_CLOSE_TAG.
{ A
= array
('operation' => 'block', 'name' => B
, 'body' => C
); }
157 block_stmt
(A
) ::= T_BLOCK T_NUMERIC
(B
) T_CLOSE_TAG body
(C
) T_OPEN_TAG T_END_BLOCK T_CLOSE_TAG.
{ A
= array
('operation' => 'block', 'name' => B
, 'body' => C
); }
159 block_stmt
(A
) ::= T_BLOCK T_NUMERIC
(B
) T_CLOSE_TAG body
(C
) T_OPEN_TAG T_END_BLOCK T_NUMERIC T_CLOSE_TAG.
{ A
= array
('operation' => 'block', 'name' => B
, 'body' => C
); }
162 filter_stmt
(A
) ::= T_FILTER filtered_var
(B
) T_CLOSE_TAG body
(X
) T_OPEN_TAG T_END_FILTER T_CLOSE_TAG.
{ A
= array
('operation' => 'filter', 'functions' => B
, 'body' => X
); }
165 regroup
(A
) ::= T_REGROUP filtered_var
(B
) T_BY varname
(C
) T_AS varname
(X
).
{ A
=array
('operation' => 'regroup', 'array' => B
, 'row' => C
, 'as' => X
); }
167 /* variables with filters */
168 filtered_var
(A
) ::= filtered_var
(B
) T_PIPE varname_args
(C
).
{ A
= B
; A
[] = C
; }
169 filtered_var
(A
) ::= varname_args
(B
).
{ A
= array
(B
); }
171 varname_args
(A
) ::= varname
(B
) T_COLON var_or_string
(X
) .
{ A
= array
(B
, 'args'=>array
(X
)); }
172 varname_args
(A
) ::= varname
(B
).
{ A
= B
; }
174 /* List of variables */
175 var_list
(A
) ::= var_list
(B
) var_or_string
(C
).
{ A
= B
; A
[] = C
; }
176 var_list
(A
) ::= var_list
(B
) T_COMMA var_or_string
(C
).
{ A
= B
; A
[] = C
; }
177 var_list
(A
) ::= var_or_string
(B
).
{ A
= array
(B
); }
180 /* variable or string (used on var_list) */
181 var_or_string
(A
) ::= varname
(B
).
{ A
= array
('var' => B
); }
182 var_or_string
(A
) ::= T_NUMERIC
(B
).
{ A
= array
('number' => B
); }
183 var_or_string
(A
) ::= string(B
).
{ A
= array
('string' => B
); }
185 fvar_or_string
(A
) ::= filtered_var
(B
).
{ A
= array
('var_filter' => B
); }
186 fvar_or_string
(A
) ::= T_NUMERIC
(B
).
{ A
= array
('number' => B
); }
187 fvar_or_string
(A
) ::= string(B
).
{ A
= array
('string' => B
); }
190 string(A
) ::= T_STRING_SINGLE_INIT s_content
(B
) T_STRING_SINGLE_END.
{ A
= B
; }
191 string(A
) ::= T_STRING_DOUBLE_INIT s_content
(B
) T_STRING_DOUBLE_END.
{ A
= B
; }
192 s_content
(A
) ::= s_content
(B
) T_STRING_CONTENT
(C
).
{ A
= B.C
; }
193 s_content
(A
) ::= T_STRING_CONTENT
(B
).
{ A
= B
; }
196 expr
(A
) ::= expr
(B
) T_AND
(X
) expr
(C
).
{ A
= array
('op_expr' => @X
, B
, C
); }
197 expr
(A
) ::= expr
(B
) T_OR
(X
) expr
(C
).
{ A
= array
('op_expr' => @X
, B
, C
); }
198 expr
(A
) ::= expr
(B
) T_PLUS|T_MINUS
(X
) expr
(C
).
{ A
= array
('op_expr' => @X
, B
, C
); }
199 expr
(A
) ::= expr
(B
) T_EQ|T_NE|T_GT|T_GE|T_LT|T_LE|T_IN
(X
) expr
(C
).
{ A
= array
('op_expr' => trim
(@X
), B
, C
); }
200 expr
(A
) ::= expr
(B
) T_TIMES|T_DIV|T_MOD
(X
) expr
(C
).
{ A
= array
('op_expr' => @X
, B
, C
); }
201 expr
(A
) ::= T_LPARENT expr
(B
) T_RPARENT.
{ A
= array
('op_expr' => 'expr', B
); }
202 expr
(A
) ::= fvar_or_string
(B
).
{ A
= B
; }
205 varname
(A
) ::= varname
(B
) T_DOT T_ALPHA
(C
).
{ if
(!is_array
(B
)) { A
= array
(B
); } else
{ A
= B
; } A
[]=C
;}
206 varname
(A
) ::= varname
(B
) T_BRACKETS_OPEN var_or_string
(C
) T_BRACKETS_CLOSE.
{ if
(!is_array
(B
)) { A
= array
(B
); } else
{ A
= B
; } A
[]=C
;}
207 varname
(A
) ::= T_ALPHA
(B
).
{ A
= B
; }
208 /* T_CUSTOM|T_CUSTOM_BLOCK are also T_ALPHA */
209 varname
(A
) ::= T_CUSTOM_TAG|T_CUSTOM_BLOCK
(B
).
{ A
= B
; }