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> listnodes
38 %type <node> expression
39 %type <list> list_expression
42 %type <flags> opt_escape
43 %type <str> opt_format
44 %type <str> opt_default
50 %token <str> VAR_OPEN VAR_CLOSE EXPR_OPEN EXPR_CLOSE
51 INCLUDE_OPEN INCLUDE_CLOSE
52 %token <str> HTMLESCAPE URLESCAPE IF_P ELSE_P LOOP_P ENDIF_P ENDLOOP_P
55 %token <intval> INTEGER
56 %token <floatval> DOUBLE
73 listnodes { curTmpl->tree = $$ = $1; }
74 | { curTmpl->tree = $$ = NULL; }
80 if ( $1->type == CollectionNode ) {
81 GListPush( $1->nodeData.children, $2 );
84 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
85 $$->type = CollectionNode;
86 $$->nodeData.children = GListPush( $$->nodeData.children, $1 );
87 $$->nodeData.children = GListPush( $$->nodeData.children, $2 );
104 '|' HTMLESCAPE { $$=TND_HTMLESCAPE; }
105 | '|' URLESCAPE { $$=TND_URLESCAPE; }
110 ',' STRING { $$=$2; }
115 '#' STRING { $$=$2; }
120 expression ',' expression {
121 $$ = makeList2($1, $3);
123 | list_expression ',' expression {
124 $$ = GListPush($$, $3);
130 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
131 $$->type = VariableNode;
132 $$->nodeData.variable.varName = $1;
133 $$->nodeData.variable.varNameLength = strlen($1);
136 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
137 $$->type = VariableNode;
138 $$->nodeData.variable.flags = TND_GLOBAL;
139 $$->nodeData.variable.varName = $2;
140 $$->nodeData.variable.varNameLength = strlen($2);
143 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
144 $$->type = ConstNode;
145 $$->nodeData.value.type = valueString;
146 $$->nodeData.value.flags = TND_DEFINED;
147 $$->nodeData.value.value.stringValue = $1;
150 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
151 $$->type = ConstNode;
152 $$->nodeData.value.type = valueInt;
153 $$->nodeData.value.flags = TND_DEFINED;
154 $$->nodeData.value.value.intValue = $1;
157 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
158 $$->type = ConstNode;
159 $$->nodeData.value.type = valueDouble;
160 $$->nodeData.value.flags = TND_DEFINED;
161 $$->nodeData.value.value.doubleValue = $1;
163 | expression '+' expression {
164 $$ = newExpressionNode( "+", makeList2( $1, $3 ) );
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 %prec NEG {
179 $$ = newExpressionNode( "-", GListPush( NULL, $2 ) );
181 | expression AND_P expression {
182 $$ = newExpressionNode( "&&", makeList2( $1, $3 ) );
184 | expression OR_P expression {
185 $$ = newExpressionNode( "||", makeList2( $1, $3 ) );
187 | expression '?' expression ':' expression {
188 $$ = newExpressionNode( "?", GListPush( makeList2( $1, $3 ), $5 ) );
191 $$ = newExpressionNode( "!", GListPush( NULL, $2 ) );
193 | expression CMP_P expression {
194 $$ = newExpressionNode( $2, makeList2( $1, $3 ) );
197 $$ = newExpressionNode( $1, NULL );
199 | varname '(' expression ')' {
200 $$ = newExpressionNode( $1, GListPush( NULL, $3 ) );
202 | varname '(' list_expression ')' {
203 $$ = newExpressionNode( $1, $3 );
205 | '(' expression ')' { $$=$2; }
210 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
212 $$->nodeData.text.value = $1;
213 $$->nodeData.text.valueLength = strlen($1);
215 | VAR_OPEN expression opt_format opt_default opt_escape VAR_CLOSE {
216 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
217 $$->type = PrintNode;
218 $$->nodeData.print.expressionNode = $2;
219 $$->nodeData.print.formatValue = $3;
220 $$->nodeData.print.defaultValue = $4;
221 $$->nodeData.print.flags = $5;
223 | INCLUDE_OPEN FILENAME INCLUDE_CLOSE {
224 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
225 $$->type = IncludeNode;
226 $$->nodeData.includeFile = $2;
228 | EXPR_OPEN LOOP_P varname EXPR_CLOSE listnodes EXPR_OPEN ENDLOOP_P EXPR_CLOSE {
229 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
231 $$->nodeData.loop.varName = $3;
232 $$->nodeData.loop.varNameLength = strlen($3);
233 $$->nodeData.loop.bodyNode = $5;
235 | EXPR_OPEN IF_P expression EXPR_CLOSE listnodes EXPR_OPEN ENDIF_P EXPR_CLOSE {
236 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
237 $$->type = ConditionNode;
238 $$->nodeData.condition.expressionNode = $3;
239 $$->nodeData.condition.ifNode = $5;
241 | EXPR_OPEN IF_P expression EXPR_CLOSE listnodes EXPR_OPEN ELSE_P EXPR_CLOSE listnodes EXPR_OPEN ENDIF_P EXPR_CLOSE {
242 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
243 $$->type = ConditionNode;
244 $$->nodeData.condition.expressionNode = $3;
245 $$->nodeData.condition.ifNode = $5;
246 $$->nodeData.condition.elseNode = $9;
254 tlog(TL_CRIT,"template error at line %d in '%s': %s", tmpl_yylineno, fileToParse, s);
259 parseTemplateFile(Template tmpl, char* filename ) {
260 FILE *in = fopen(filename, "r");
264 tlog(TL_CRIT,"Can not open template file '%s': %s",
265 filename, strerror(errno));
270 curTmpl->tree = NULL;
272 fileToParse = filename;
273 startTemplateLex(tmpl, in);
282 newExpressionNode(char *op, GList *args) {
285 res = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
286 res->type = ExpressionNode;
287 res->nodeData.expression.functionName = op;
288 res->nodeData.expression.argsNode = args;
294 makeList2(void *a, void *b) {
295 return GListPush( GListPush(NULL, a), b );