9 extern char *fileToParse;
14 static int yyerror(char *s);
15 void startTemplateLex(Template tmpl, FILE *in);
17 static Template curTmpl;
18 extern int tmpl_yylineno;
19 static TemplateNode newExpressionNode(char *op, GList *args);
20 static GList *makeList2(void *a, void *b);
36 %type <node> ifnode elsenode elsifnode
37 %type <node> listnodes
39 %type <node> expression
40 %type <list> list_expression
44 %type <flags> opt_escape
45 %type <str> opt_format
46 %type <str> opt_default
52 %token <str> VAR_OPEN VAR_CLOSE EXPR_OPEN EXPR_CLOSE
53 INCLUDE_OPEN INCLUDE_CLOSE
54 %token <str> HTMLESCAPE URLESCAPE IF_P ELSIF_P ELSE_P LOOP_P ENDIF_P ENDLOOP_P SELF_P
57 %token <intval> INTEGER
58 %token <floatval> DOUBLE
75 listnodes { curTmpl->tree = $$ = $1; }
76 | { curTmpl->tree = $$ = NULL; }
82 if ( $1->type == CollectionNode ) {
83 GListPush( $1->nodeData.children, $2 );
86 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
87 $$->type = CollectionNode;
88 $$->nodeData.children = GListPush( $$->nodeData.children, $1 );
89 $$->nodeData.children = GListPush( $$->nodeData.children, $2 );
107 '|' HTMLESCAPE { $$=TND_HTMLESCAPE; }
108 | '|' URLESCAPE { $$=TND_URLESCAPE; }
113 ',' STRING { $$=$2; }
118 '#' STRING { $$=$2; }
123 expression ',' expression {
124 $$ = makeList2($1, $3);
126 | list_expression ',' expression {
127 $$ = GListPush($$, $3);
133 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
134 $$->type = VariableNode;
135 $$->nodeData.variable.varName = $1;
136 $$->nodeData.variable.varNameLength = strlen($1);
139 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
140 $$->type = VariableNode;
141 $$->nodeData.variable.flags = TND_GLOBAL;
142 $$->nodeData.variable.varName = $2;
143 $$->nodeData.variable.varNameLength = strlen($2);
146 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
147 $$->type = ConstNode;
148 $$->nodeData.value.type = valueString;
149 $$->nodeData.value.flags = TND_DEFINED;
150 $$->nodeData.value.value.stringValue = $1;
153 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
154 $$->type = ConstNode;
155 $$->nodeData.value.type = valueInt;
156 $$->nodeData.value.flags = TND_DEFINED;
157 $$->nodeData.value.value.intValue = $1;
160 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
161 $$->type = ConstNode;
162 $$->nodeData.value.type = valueDouble;
163 $$->nodeData.value.flags = TND_DEFINED;
164 $$->nodeData.value.value.doubleValue = $1;
166 | expression '+' expression {
167 $$ = newExpressionNode( "+", makeList2( $1, $3 ) );
169 | expression '-' expression {
170 $$ = newExpressionNode( "-", makeList2( $1, $3 ) );
172 | expression '*' expression {
173 $$ = newExpressionNode( "*", makeList2( $1, $3 ) );
175 | expression '/' expression {
176 $$ = newExpressionNode( "/", makeList2( $1, $3 ) );
178 | expression '%' expression {
179 $$ = newExpressionNode( "%", makeList2( $1, $3 ) );
181 | '-' expression %prec NEG {
182 $$ = newExpressionNode( "-", GListPush( NULL, $2 ) );
184 | expression AND_P expression {
185 $$ = newExpressionNode( "&&", makeList2( $1, $3 ) );
187 | expression OR_P expression {
188 $$ = newExpressionNode( "||", makeList2( $1, $3 ) );
190 | expression '?' expression ':' expression {
191 $$ = newExpressionNode( "?", GListPush( makeList2( $1, $3 ), $5 ) );
194 $$ = newExpressionNode( "!", GListPush( NULL, $2 ) );
196 | expression CMP_P expression {
197 $$ = newExpressionNode( $2, makeList2( $1, $3 ) );
200 $$ = newExpressionNode( $1, NULL );
202 | varname '(' expression ')' {
203 $$ = newExpressionNode( $1, GListPush( NULL, $3 ) );
205 | varname '(' list_expression ')' {
206 $$ = newExpressionNode( $1, $3 );
208 | '(' expression ')' { $$=$2; }
217 EXPR_OPEN ELSE_P EXPR_CLOSE listnodes EXPR_OPEN ENDIF_P EXPR_CLOSE {
223 EXPR_OPEN elsif expression EXPR_CLOSE listnodes EXPR_OPEN ENDIF_P EXPR_CLOSE {
224 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
225 $$->type = ConditionNode;
226 $$->nodeData.condition.expressionNode = $3;
227 $$->nodeData.condition.ifNode = $5;
229 | EXPR_OPEN elsif expression EXPR_CLOSE listnodes elsenode {
230 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
231 $$->type = ConditionNode;
232 $$->nodeData.condition.expressionNode = $3;
233 $$->nodeData.condition.ifNode = $5;
234 $$->nodeData.condition.elseNode = $6;
236 | EXPR_OPEN elsif expression EXPR_CLOSE listnodes elsifnode {
237 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
238 $$->type = ConditionNode;
239 $$->nodeData.condition.expressionNode = $3;
240 $$->nodeData.condition.ifNode = $5;
241 $$->nodeData.condition.elseNode = $6;
246 EXPR_OPEN IF_P expression EXPR_CLOSE listnodes EXPR_OPEN ENDIF_P EXPR_CLOSE {
247 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
248 $$->type = ConditionNode;
249 $$->nodeData.condition.expressionNode = $3;
250 $$->nodeData.condition.ifNode = $5;
252 | EXPR_OPEN IF_P expression EXPR_CLOSE listnodes elsenode {
253 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
254 $$->type = ConditionNode;
255 $$->nodeData.condition.expressionNode = $3;
256 $$->nodeData.condition.ifNode = $5;
257 $$->nodeData.condition.elseNode = $6;
259 | EXPR_OPEN IF_P expression EXPR_CLOSE listnodes elsifnode {
260 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
261 $$->type = ConditionNode;
262 $$->nodeData.condition.expressionNode = $3;
263 $$->nodeData.condition.ifNode = $5;
264 $$->nodeData.condition.elseNode = $6;
271 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
273 $$->nodeData.text.value = $1;
274 $$->nodeData.text.valueLength = strlen($1);
276 | VAR_OPEN expression opt_format opt_default opt_escape VAR_CLOSE {
277 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
278 $$->type = PrintNode;
279 $$->nodeData.print.expressionNode = $2;
280 $$->nodeData.print.formatValue = $3;
281 $$->nodeData.print.defaultValue = $4;
282 $$->nodeData.print.flags = $5;
284 | INCLUDE_OPEN FILENAME INCLUDE_CLOSE {
285 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
286 $$->type = IncludeNode;
287 $$->nodeData.includeFile = $2;
289 | EXPR_OPEN SELF_P EXPR_CLOSE {
290 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
293 | EXPR_OPEN LOOP_P varname EXPR_CLOSE listnodes EXPR_OPEN ENDLOOP_P EXPR_CLOSE {
294 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
296 $$->nodeData.loop.varName = $3;
297 $$->nodeData.loop.varNameLength = strlen($3);
298 $$->nodeData.loop.bodyNode = $5;
307 tlog(TL_CRIT,"template error at line %d in '%s': %s", tmpl_yylineno, fileToParse, s);
312 parseTemplateFile(Template tmpl, char* filename ) {
313 FILE *in = fopen(filename, "r");
317 tlog(TL_CRIT,"Can not open template file '%s': %s",
318 filename, strerror(errno));
323 curTmpl->tree = NULL;
325 fileToParse = filename;
326 startTemplateLex(tmpl, in);
335 newExpressionNode(char *op, GList *args) {
338 res = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
339 res->type = ExpressionNode;
340 res->nodeData.expression.functionName = op;
341 res->nodeData.expression.argsNode = args;
347 makeList2(void *a, void *b) {
348 return GListPush( GListPush(NULL, a), b );