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 SELF_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 );
105 '|' HTMLESCAPE { $$=TND_HTMLESCAPE; }
106 | '|' URLESCAPE { $$=TND_URLESCAPE; }
111 ',' STRING { $$=$2; }
116 '#' STRING { $$=$2; }
121 expression ',' expression {
122 $$ = makeList2($1, $3);
124 | list_expression ',' expression {
125 $$ = GListPush($$, $3);
131 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
132 $$->type = VariableNode;
133 $$->nodeData.variable.varName = $1;
134 $$->nodeData.variable.varNameLength = strlen($1);
137 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
138 $$->type = VariableNode;
139 $$->nodeData.variable.flags = TND_GLOBAL;
140 $$->nodeData.variable.varName = $2;
141 $$->nodeData.variable.varNameLength = strlen($2);
144 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
145 $$->type = ConstNode;
146 $$->nodeData.value.type = valueString;
147 $$->nodeData.value.flags = TND_DEFINED;
148 $$->nodeData.value.value.stringValue = $1;
151 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
152 $$->type = ConstNode;
153 $$->nodeData.value.type = valueInt;
154 $$->nodeData.value.flags = TND_DEFINED;
155 $$->nodeData.value.value.intValue = $1;
158 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
159 $$->type = ConstNode;
160 $$->nodeData.value.type = valueDouble;
161 $$->nodeData.value.flags = TND_DEFINED;
162 $$->nodeData.value.value.doubleValue = $1;
164 | expression '+' expression {
165 $$ = newExpressionNode( "+", makeList2( $1, $3 ) );
167 | expression '-' expression {
168 $$ = newExpressionNode( "-", makeList2( $1, $3 ) );
170 | expression '*' expression {
171 $$ = newExpressionNode( "*", makeList2( $1, $3 ) );
173 | expression '/' expression {
174 $$ = newExpressionNode( "/", makeList2( $1, $3 ) );
176 | expression '%' expression {
177 $$ = newExpressionNode( "%", makeList2( $1, $3 ) );
179 | '-' expression %prec NEG {
180 $$ = newExpressionNode( "-", GListPush( NULL, $2 ) );
182 | expression AND_P expression {
183 $$ = newExpressionNode( "&&", makeList2( $1, $3 ) );
185 | expression OR_P expression {
186 $$ = newExpressionNode( "||", makeList2( $1, $3 ) );
188 | expression '?' expression ':' expression {
189 $$ = newExpressionNode( "?", GListPush( makeList2( $1, $3 ), $5 ) );
192 $$ = newExpressionNode( "!", GListPush( NULL, $2 ) );
194 | expression CMP_P expression {
195 $$ = newExpressionNode( $2, makeList2( $1, $3 ) );
198 $$ = newExpressionNode( $1, NULL );
200 | varname '(' expression ')' {
201 $$ = newExpressionNode( $1, GListPush( NULL, $3 ) );
203 | varname '(' list_expression ')' {
204 $$ = newExpressionNode( $1, $3 );
206 | '(' expression ')' { $$=$2; }
211 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
213 $$->nodeData.text.value = $1;
214 $$->nodeData.text.valueLength = strlen($1);
216 | VAR_OPEN expression opt_format opt_default opt_escape VAR_CLOSE {
217 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
218 $$->type = PrintNode;
219 $$->nodeData.print.expressionNode = $2;
220 $$->nodeData.print.formatValue = $3;
221 $$->nodeData.print.defaultValue = $4;
222 $$->nodeData.print.flags = $5;
224 | INCLUDE_OPEN FILENAME INCLUDE_CLOSE {
225 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
226 $$->type = IncludeNode;
227 $$->nodeData.includeFile = $2;
229 | EXPR_OPEN SELF_P EXPR_CLOSE {
230 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
233 | EXPR_OPEN LOOP_P varname EXPR_CLOSE listnodes EXPR_OPEN ENDLOOP_P EXPR_CLOSE {
234 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
236 $$->nodeData.loop.varName = $3;
237 $$->nodeData.loop.varNameLength = strlen($3);
238 $$->nodeData.loop.bodyNode = $5;
240 | EXPR_OPEN IF_P expression EXPR_CLOSE listnodes EXPR_OPEN ENDIF_P EXPR_CLOSE {
241 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
242 $$->type = ConditionNode;
243 $$->nodeData.condition.expressionNode = $3;
244 $$->nodeData.condition.ifNode = $5;
246 | EXPR_OPEN IF_P expression EXPR_CLOSE listnodes EXPR_OPEN ELSE_P 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;
251 $$->nodeData.condition.elseNode = $9;
259 tlog(TL_CRIT,"template error at line %d in '%s': %s", tmpl_yylineno, fileToParse, s);
264 parseTemplateFile(Template tmpl, char* filename ) {
265 FILE *in = fopen(filename, "r");
269 tlog(TL_CRIT,"Can not open template file '%s': %s",
270 filename, strerror(errno));
275 curTmpl->tree = NULL;
277 fileToParse = filename;
278 startTemplateLex(tmpl, in);
287 newExpressionNode(char *op, GList *args) {
290 res = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
291 res->type = ExpressionNode;
292 res->nodeData.expression.functionName = op;
293 res->nodeData.expression.argsNode = args;
299 makeList2(void *a, void *b) {
300 return GListPush( GListPush(NULL, a), b );