add .gitignore
[tedtools.git] / tmpl_scan.l
1 %{
2 #include <stdlib.h>
3 #include <limits.h>
4
5 #include <tlog.h>
6 #include <tmalloc.h>
7 #include <template.h>
8 #include <tmpl_gram.h>
9
10 #ifndef yylval
11 #define yylval tmpl_yylval
12 #endif
13
14 extern char* fileToParse;
15
16 static int yyerror(char *s, int line);
17 static int getIdent(char *word);
18
19 static char *strbuf = NULL;
20 static int length;
21 static int total;
22 static void addstring(char *s, int l); 
23 static void addchar(char s); 
24 static MemoryContext *lexContext;       
25
26 %}
27
28 %option 8bit
29 %option never-interactive
30 %option nodefault
31 %option noyywrap
32 %option nounput
33 %option prefix="tmpl_yy"
34 %option yylineno
35
36 %x      xVAR
37 %x      xEXPR
38 %x  xINCLUDE
39 %x  xQUOTED
40 %x  xCOMMENT
41
42 LEXEMCHARSTART  [a-zA-Z_]
43 LEXEMCHAR       [a-zA-Z0-9_]
44 PATH            [a-zA-Z0-9_/\.]
45 DIGIT           [0-9]
46
47 %%
48
49 <INITIAL>\<\%           {
50                                                 BEGIN xVAR;
51                                                 return VAR_OPEN;
52                                         }
53
54 <INITIAL>\<\@           {
55                                                 BEGIN xEXPR;
56                                                 return EXPR_OPEN;
57                                         }
58
59 <INITIAL>\<\&           {
60                                                 BEGIN xINCLUDE;
61                                                 return INCLUDE_OPEN;
62                                         }
63
64 <INITIAL>\<\#           {
65                                                 BEGIN xCOMMENT;
66                                         }
67
68 <xVAR>[,\|#]            {
69                                                 yylval.punct = *yytext;
70                                                 return yylval.punct;
71                                         }
72
73 <xVAR>\%\>                      {
74                                                 BEGIN INITIAL;
75                                                 return VAR_CLOSE;
76                                         }
77
78 <xVAR>\"                        {
79                                                 total = 1024;
80                                                 strbuf = mcalloc(lexContext, total);
81                                                 length=0;
82                                                 BEGIN xQUOTED;
83                                         }
84
85
86 <xQUOTED>\\(.|\n)       { addchar(yytext[1]); }
87
88 <xQUOTED>\"                     {
89                                                 yylval.str = strbuf;
90                                                 BEGIN xVAR;
91                                                 strbuf = NULL;
92                                                 return STRING;
93                                         }
94                                                 
95 <xQUOTED>[^\"\\]+       { addstring(yytext, yyleng); }
96
97 <xQUOTED>\\                     { 
98                                                 /* This is only needed for \ just before EOF */
99                                                 addchar(*yytext); 
100                                         }
101
102 <xEXPR,xVAR>{DIGIT}+    {
103                                         yylval.intval = strtoll(yytext, NULL, 0);
104                                                 return INTEGER;
105                                         }
106
107 <xEXPR,xVAR>{LEXEMCHARSTART}{LEXEMCHAR}* {
108                                                 yylval.str  = strlower(mcnstrdup(lexContext, yytext, yyleng));
109                                                 return  getIdent(yylval.str);
110                                         }
111
112 <xEXPR,xVAR>\|\|                        { return OR_P; }
113
114 <xEXPR,xVAR>\&\&                        { return AND_P; }
115
116 <xEXPR,xVAR>\!                  { return NOT_P; }
117
118 <xEXPR,xVAR>[\^\%\+\*\/\-\(\)\?\:]              {
119                                                 yylval.punct = *yytext;
120                                                 return yylval.punct;
121                                         }
122
123 <xEXPR,xVAR>(\<|\<=|\>=|\>|==|\!=|\<\>) {
124                                                 yylval.str  = mcnstrdup(lexContext, yytext, yyleng);
125                                                 return CMP_P;
126                                         }
127
128 <xEXPR,xVAR>{DIGIT}+"."{DIGIT}+ {
129                                         yylval.floatval = atof(yytext);
130                                                 return DOUBLE;
131                                         }
132
133 <xEXPR,xVAR>{DIGIT}+[eE]["+""-"]?{DIGIT}+    {
134                                         yylval.floatval = atof(yytext);
135                                                 return DOUBLE;
136                                         }
137
138 <xEXPR,xVAR>{DIGIT}+"."{DIGIT}+[eE]["+""-"]?{DIGIT}+   {
139                                                 yylval.floatval = atof(yytext);
140                                                 return DOUBLE;
141                                         }
142
143 <xEXPR>\@\>                     {
144                                                 BEGIN INITIAL;
145                                                 return  EXPR_CLOSE;
146                                         }
147
148 <xINCLUDE>{PATH}+       {
149                                                 yylval.str  = mcnstrdup(lexContext, yytext, yyleng);
150                                                 return FILENAME;
151                                         }
152
153 <xINCLUDE>\&\>          {
154                                                 BEGIN INITIAL;
155                                                 return INCLUDE_CLOSE;
156                                         }
157
158 <xCOMMENT>\#\>          {
159                                                 BEGIN INITIAL;
160                                         }
161
162 <xVAR,xINCLUDE,xEXPR,xCOMMENT>\n+       ;
163
164 <xVAR,xINCLUDE,xEXPR,xCOMMENT>[\r\t ]+  ;
165
166 <xCOMMENT>.             ;
167
168 <xVAR,xINCLUDE,xEXPR>.  { 
169                                                 return yyerror("Syntax error in template tag", yylineno); 
170                                         }
171
172 <xVAR,xQUOTED,xINCLUDE,xEXPR,xCOMMENT><<EOF>> { 
173                                                 return yyerror("unterminated template tag", yylineno); 
174                                         }
175
176 <INITIAL>[^\<]+         {
177                                                 yylval.str  = mcnstrdup(lexContext, yytext, yyleng);
178                                                 return TEXT_P;
179                                         }
180
181 <INITIAL>([^\<]*\<[^\&\#\@\%][^\<]*)+   {
182                                                 yylval.str  = mcnstrdup(lexContext, yytext, yyleng);
183                                                 return TEXT_P;
184                                         }
185                                 
186
187 <INITIAL>\<             {
188                                                 /* This is only needed for < just before EOF */
189                                                 yylval.str  = mcnstrdup(lexContext, yytext, yyleng);
190                                                 return TEXT_P;
191                                         }
192
193 <INITIAL><<EOF>>        {
194                                         yyterminate();
195                         }
196
197 %%
198
199 typedef struct KeyWord {
200         char    *word;
201         int             len;
202         int             id;
203 } KeyWord;
204
205 static KeyWord keywords[] = {
206         { "H",                  0,      HTMLESCAPE      },
207         { "U",                  0,      URLESCAPE       },
208         { "IF",                 0,      IF_P            },
209         { "ELSE",               0,      ELSE_P          },
210         { "LOOP",               0,      LOOP_P          },
211         { "SELF",               0,      SELF_P          },
212         { "ELSIF",              0,      ELSIF_P         },
213         { "ENDIF",              0,      ENDIF_P         },
214         { "ENDLOOP",    0,      ENDLOOP_P       } 
215 };
216
217 void
218 startTemplateLex(Template tmpl, FILE *in) {
219         if ( keywords->len == 0 ) {
220                 int i;
221                 for(i=0; i<sizeof(keywords)/sizeof(KeyWord);i++)
222                         keywords[i].len = strlen(keywords[i].word);
223         }
224
225         lexContext = tmpl->templateContext;
226
227         yylineno=1;
228         yyrestart(in);
229         BEGIN INITIAL;
230 }
231
232 static int
233 getIdent(char *word) {
234         int len = strlen(word);
235         int i;
236
237         if ( len > keywords[ sizeof(keywords)/sizeof(KeyWord)-1 ].len )
238                 return LEXEME;
239
240         for(i=0; i<sizeof(keywords)/sizeof(KeyWord) && len >= keywords[i].len; i++)
241                 if ( len == keywords[i].len && strcasecmp(word, keywords[i].word) == 0 )
242                         return keywords[i].id;
243
244         return LEXEME;
245 }
246
247 static int 
248 yyerror(char *s, int line) {
249         strbuf = NULL;
250         tlog(TL_CRIT,"template error at line %d in '%s': %s", line, fileToParse, s);
251
252         return 0;
253 }
254
255 static void
256 addstring(char *s, int l) {
257         while( length + l + 1 >= total ) {
258                 total*=2;
259                 strbuf=mcrealloc(strbuf, total);
260         }
261
262         memcpy( strbuf+length, s, l);
263         length+=l;
264         strbuf[length] = '\0';
265 }
266
267 static void
268 addchar(char s) {
269         if(  length + 2 >= total ) {
270                 total*=2;
271                 strbuf=mcrealloc(strbuf, total);
272         }
273
274         strbuf[ length++ ] = s;
275         strbuf[length] = '\0';
276 }
277
278