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