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