Fix memory leak in SFSIterate
[tedtools.git] / tmpl_gram.y
1 %{
2 #include <errno.h>
3 #include <string.h>
4 #include <tlog.h>
5 #include <tmalloc.h>
6 #include <template.h>
7 #include <tmpl_gram.h>
8
9 extern char *fileToParse;
10 char *fileToParse;
11
12 int yylex(void);
13 int yyparse(void);
14 static int yyerror(char *s);
15 void startTemplateLex(Template tmpl, FILE *in);
16
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);
21
22
23 %}
24
25 %union {
26         char                                            *str;
27         char                                            punct;
28         int                                                     flags;
29         int                                                     intval;
30         double                                          floatval;
31         TemplateNode                            node;
32         GList                                           *list;
33 }
34
35 %type <node>                    node
36 %type <node>                    listnodes
37 %type <node>                    template
38 %type <node>                    expression
39 %type <list>                    list_expression
40 %type <str>                             varname
41
42 %type <flags>                   opt_escape
43 %type <str>                             opt_format
44 %type <str>                             opt_default
45
46 %token  <str>                   STRING
47 %token  <str>                   FILENAME
48 %token  <str>                   TEXT_P
49 %token  <str>                   LEXEME
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 
53 %token  <str>                   CMP_P
54
55 %token <intval>                 INTEGER
56 %token <floatval>               DOUBLE
57
58
59 %left '+' '-' 
60 %left '*' '/' '%'
61 %left '?' ':'
62 %left NEG
63
64 %left OR_P 
65 %left AND_P
66 %left NOT_P
67
68 %left CMP_P
69
70 %%
71
72 template:
73         listnodes       { curTmpl->tree = $$ = $1; }
74         |                       { curTmpl->tree = $$ = NULL; }
75         ;
76
77 listnodes:
78         node    { $$ = $1; }
79         | listnodes node {
80                         if ( $1->type == CollectionNode ) {
81                                 GListPush( $1->nodeData.children, $2 );
82                                 $$ = $1;
83                         } else {
84                                 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
85                                 $$->type = CollectionNode;
86                                 $$->nodeData.children = GListPush( $$->nodeData.children, $1 );
87                                 $$->nodeData.children = GListPush( $$->nodeData.children, $2 );
88                         }
89                 }
90         ;
91
92 varname:
93         LEXEME  
94         | HTMLESCAPE
95         | URLESCAPE
96         | IF_P
97         | ELSE_P
98         | LOOP_P
99         | ENDIF_P
100         | ENDLOOP_P
101         ;
102
103 opt_escape:
104         '|'     HTMLESCAPE              { $$=TND_HTMLESCAPE; }
105         | '|'   URLESCAPE       { $$=TND_URLESCAPE; }
106         |                               { $$=0; }
107         ;
108
109 opt_format:
110         ','     STRING          { $$=$2; }
111         |                       { $$=NULL; }
112         ;
113
114 opt_default:
115         '#'     STRING          { $$=$2; }
116         |                       { $$=NULL; }
117         ;
118
119 list_expression:
120         expression ',' expression                       { 
121                         $$ = makeList2($1, $3); 
122                 }
123         | list_expression ',' expression        {
124                         $$ = GListPush($$, $3);
125         }
126         ;
127
128 expression:
129         varname { 
130                         $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
131                         $$->type = VariableNode;
132                         $$->nodeData.variable.varName = $1; 
133                         $$->nodeData.variable.varNameLength = strlen($1);
134                 }
135         | '^' varname   { 
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);
141                 }
142         | STRING        { 
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;
148                 }
149         | INTEGER       { 
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;
155                 }
156         | DOUBLE        {
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;
162                 }
163         | expression '+' expression     { 
164                         $$ = newExpressionNode( "+", makeList2( $1, $3 ) ); 
165                 }
166         | expression '-' expression     { 
167                         $$ = newExpressionNode( "-", makeList2( $1, $3 ) ); 
168                 }
169         | expression '*' expression     { 
170                         $$ = newExpressionNode( "*", makeList2( $1, $3 ) ); 
171                 }
172         | expression '/' expression     { 
173                         $$ = newExpressionNode( "/", makeList2( $1, $3 ) ); 
174                 }
175         | expression '%' expression     { 
176                         $$ = newExpressionNode( "%", makeList2( $1, $3 ) ); 
177                 }
178         | '-' expression %prec NEG              { 
179                         $$ = newExpressionNode( "-", GListPush( NULL, $2 ) ); 
180                 }
181         | expression AND_P expression   { 
182                         $$ = newExpressionNode( "&&", makeList2( $1, $3 ) ); 
183                 }
184         | expression OR_P expression    { 
185                         $$ = newExpressionNode( "||", makeList2( $1, $3 ) ); 
186                 }
187         | expression '?' expression ':' expression      { 
188                         $$ = newExpressionNode( "?", GListPush( makeList2( $1, $3 ), $5 ) ); 
189                 }
190         | NOT_P expression                              { 
191                         $$ = newExpressionNode( "!", GListPush( NULL, $2 ) ); 
192                 }
193         | expression CMP_P expression   {
194                         $$ = newExpressionNode( $2, makeList2( $1, $3 ) ); 
195                 }
196         | varname '(' ')'                               { 
197                         $$ = newExpressionNode( $1, NULL ); 
198                 }
199         | varname '(' expression ')'    { 
200                         $$ = newExpressionNode( $1, GListPush( NULL, $3 ) ); 
201                 }
202         | varname '(' list_expression ')'       { 
203                         $$ = newExpressionNode( $1, $3 ); 
204                 }
205         | '(' expression ')'                    { $$=$2; }
206         ;
207
208 node:   
209         TEXT_P  {
210                                 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
211                                 $$->type = TextNode;
212                                 $$->nodeData.text.value = $1;
213                                 $$->nodeData.text.valueLength = strlen($1);
214                         }
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;
222                         }
223         | INCLUDE_OPEN FILENAME INCLUDE_CLOSE   {
224                                 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
225                                 $$->type = IncludeNode;
226                                 $$->nodeData.includeFile = $2;
227                         }
228         | EXPR_OPEN     LOOP_P varname EXPR_CLOSE listnodes EXPR_OPEN ENDLOOP_P EXPR_CLOSE {
229                                 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
230                                 $$->type = LoopNode;
231                                 $$->nodeData.loop.varName = $3; 
232                                 $$->nodeData.loop.varNameLength = strlen($3);
233                                 $$->nodeData.loop.bodyNode = $5;
234                 }
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;
240                 }
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;
247                 }
248         ;
249
250 %%
251
252 static int
253 yyerror(char *s) {
254         tlog(TL_CRIT,"template error at line %d in '%s': %s", tmpl_yylineno, fileToParse, s);
255         return 1;
256 }
257
258 int
259 parseTemplateFile(Template tmpl, char* filename ) {
260         FILE *in  = fopen(filename, "r");
261         int     err;
262
263         if ( in == NULL ) {
264                 tlog(TL_CRIT,"Can not open template file '%s': %s",
265                                                 filename, strerror(errno));
266                 return 3;
267         }
268
269         curTmpl = tmpl;
270         curTmpl->tree = NULL;
271
272         fileToParse = filename;
273         startTemplateLex(tmpl, in);
274         err = yyparse();
275
276         fclose(in);
277
278         return err;
279 }
280
281 static TemplateNode     
282 newExpressionNode(char *op, GList *args) {
283         TemplateNode    res;
284
285         res =  mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
286         res->type = ExpressionNode;
287         res->nodeData.expression.functionName = op;
288         res->nodeData.expression.argsNode = args;
289
290         return res;
291 }
292
293 static GList *
294 makeList2(void *a, void *b) {
295         return GListPush( GListPush(NULL, a), b );
296 }