Fix bug in GListTruncate, extends templates tests
[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
20 %}
21
22 %union {
23         char                            *str;
24         char                            punct;
25         int                                     varname;
26         int                                     flags;
27         TemplateNode            node;
28 }
29
30 %type <node>                    node
31 %type <node>                    listnodes
32 %type <node>                    template
33 %type <node>                    condition
34 %type <node>                    condition_varname
35 %type <str>                             varname
36
37 %type <flags>                   opt_escape
38 %type <flags>                   opt_global
39 %type <str>                             opt_default
40 %type <str>                             opt_format
41
42 %token  <str>                   OR_P
43 %token  <str>                   STRING
44 %token  <str>                   FILENAME
45 %token  <str>                   TEXT_P
46 %token  <str>                   LEXEME
47 %token  <str>                   VAR_OPEN VAR_CLOSE EXPR_OPEN EXPR_CLOSE 
48                                                 INCLUDE_OPEN INCLUDE_CLOSE
49 %token  <str>                   HTMLESCAPE URLESCAPE IF_P ELSE_P LOOP_P ENDIF_P ENDLOOP_P 
50                                                 NOT_P   DEFINED_P
51
52 %%
53
54 template:
55         listnodes       { curTmpl->tree = $$ = $1; }
56         |                       { curTmpl->tree = $$ = NULL; }
57         ;
58
59 listnodes:
60         node    { $$ = $1; }
61         | listnodes node {
62                         if ( $1->type == CollectionNode ) {
63                                 GListPush( $1->nodeData.children, $2 );
64                                 $$ = $1;
65                         } else {
66                                 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
67                                 $$->type = CollectionNode;
68                                 $$->nodeData.children = GListPush( $$->nodeData.children, $1 );
69                                 $$->nodeData.children = GListPush( $$->nodeData.children, $2 );
70                         }
71                 }
72         ;
73
74 varname:
75         LEXEME  
76         | HTMLESCAPE
77         | URLESCAPE
78         | IF_P
79         | ELSE_P
80         | LOOP_P
81         | ENDIF_P
82         | ENDLOOP_P
83         | NOT_P
84         | DEFINED_P
85         ;
86
87 opt_escape:
88         '|'     HTMLESCAPE              { $$=TND_HTMLESCAPE; }
89         | '|'   URLESCAPE       { $$=TND_URLESCAPE; }
90         |                               { $$=0; }
91         ;
92
93 opt_global:
94         '^'                                     { $$=TND_GLOBAL; }
95         |                               { $$=0; }
96         ;
97
98 opt_format:
99         ','     STRING          { $$=$2; }
100         |                       { $$=NULL; }
101         ;
102
103 opt_default:
104         OR_P STRING             { $$=$2; }
105         |                       { $$=NULL; }
106         ;
107
108 condition_varname:
109         varname {
110                                 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
111                                 $$->type = ConditionNode;
112                                 $$->nodeData.condition.varName = $1; 
113                                 $$->nodeData.condition.varNameLength = strlen($1);
114                 }
115         | '^' varname {
116                                 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
117                                 $$->type = ConditionNode;
118                                 $$->nodeData.condition.flags = TND_GLOBAL;
119                                 $$->nodeData.condition.varName = $2; 
120                                 $$->nodeData.condition.varNameLength = strlen($2);
121                 }
122         ;
123
124 condition:
125         condition_varname { 
126                                 $$ = $1; 
127                 }
128         | DEFINED_P condition_varname {
129                                 $$ = $2;
130                                 $$->nodeData.condition.flags |= TND_DEFINED;
131                 }
132         | NOT_P condition {
133                                 $$ = $2;
134                                 if ( $$->nodeData.condition.flags & TND_NOT )
135                                         $$->nodeData.condition.flags &= ~TND_NOT;
136                                 else
137                                         $$->nodeData.condition.flags |= TND_NOT;
138                 }
139         ;
140
141 node:   
142         TEXT_P  {
143                                 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
144                                 $$->type = TextNode;
145                                 $$->nodeData.text.value = $1;
146                                 $$->nodeData.text.valueLength = strlen($1);
147                         }
148         | VAR_OPEN opt_global varname opt_format opt_default opt_escape VAR_CLOSE {
149                                 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
150                                 $$->type = VariableNode;
151                                 $$->nodeData.variable.varName = $3;
152                                 $$->nodeData.variable.varNameLength = strlen($3);
153                                 $$->nodeData.variable.formatValue = $4;
154                                 $$->nodeData.variable.defaultValue = $5;
155                                 $$->nodeData.variable.flags = $2 | $6;
156                         }
157         | INCLUDE_OPEN FILENAME INCLUDE_CLOSE   {
158                                 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
159                                 $$->type = IncludeNode;
160                                 $$->nodeData.includeFile = $2;
161                         }
162         | EXPR_OPEN     LOOP_P varname EXPR_CLOSE listnodes EXPR_OPEN ENDLOOP_P EXPR_CLOSE {
163                                 $$ = mc0alloc( curTmpl->templateContext, sizeof(TemplateNodeData) );
164                                 $$->type = LoopNode;
165                                 $$->nodeData.loop.varName = $3; 
166                                 $$->nodeData.loop.varNameLength = strlen($3);
167                                 $$->nodeData.loop.bodyNode = $5;
168                 }
169         | EXPR_OPEN IF_P condition EXPR_CLOSE listnodes EXPR_OPEN ENDIF_P EXPR_CLOSE {
170                                 $$ = $3;
171                                 $$->nodeData.condition.ifNode = $5;
172                 }
173         | EXPR_OPEN IF_P condition EXPR_CLOSE listnodes EXPR_OPEN ELSE_P EXPR_CLOSE listnodes EXPR_OPEN ENDIF_P EXPR_CLOSE {
174                                 $$ = $3;
175                                 $$->nodeData.condition.ifNode = $5;
176                                 $$->nodeData.condition.elseNode = $9;
177                 }
178         ;
179
180 %%
181
182 static int
183 yyerror(char *s) {
184         tlog(TL_CRIT,"template error at line %d in '%s': %s", tmpl_yylineno, fileToParse, s);
185         return 1;
186 }
187
188 int
189 parseTemplateFile(Template tmpl, char* filename ) {
190         FILE *in  = fopen(filename, "r");
191         int     err;
192
193         if ( in == NULL ) {
194                 tlog(TL_CRIT,"Can not open template file '%s': %s",
195                                                 filename, strerror(errno));
196                 return 3;
197         }
198
199         curTmpl = tmpl;
200         curTmpl->tree = NULL;
201
202         fileToParse = filename;
203         startTemplateLex(tmpl, in);
204         err = yyparse();
205
206         fclose(in);
207
208         return err;
209 }
210