lex.l - enscript - GNU Enscript
HTML git clone git://thinkerwim.org/enscript.git
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
lex.l (7736B)
---
1 %{
2 /*
3 * Lexer for states.
4 * Copyright (c) 1997-1998 Markku Rossi.
5 *
6 * Author: Markku Rossi <mtr@iki.fi>
7 */
8
9 /*
10 * This file is part of GNU Enscript.
11 *
12 * Enscript is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * Enscript is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with Enscript. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 /*
27 * $Id: lex.l,v 1.1.1.1 2003/03/05 07:25:52 mtr Exp $
28 */
29
30 #include "defs.h"
31 #include "gram.h"
32
33 static void eat_comment ();
34 static char *read_string ___P ((unsigned int *len_return));
35 static void read_regexp ___P ((Node *node));
36 %}
37
38 real [+-]?[0-9]+\.[0-9]*|[+-]?\.[0-9]+
39 integer [+-]?[0-9]+
40 symbol [a-zA-Z_][a-zA-Z_0-9]*|\$.
41
42 %%
43
44 "/*" { eat_comment (); }
45 [ \t\r\f] { ; }
46 \n { linenum++; }
47
48 \" { yylval.node = node_alloc (nSTRING);
49 yylval.node->u.str.data
50 = read_string (&yylval.node->u.str.len);
51 return tSTRING;
52 }
53
54 '[^\\]' { yylval.node = node_alloc (nINTEGER);
55 yylval.node->u.integer = yytext[1];
56 return tINTEGER;
57 }
58
59 '\\.' { yylval.node = node_alloc (nINTEGER);
60 switch (yytext[2])
61 {
62 case 'n':
63 yylval.node->u.integer = '\n';
64 break;
65
66 case 't':
67 yylval.node->u.integer = '\t';
68 break;
69
70 case 'v':
71 yylval.node->u.integer = '\v';
72 break;
73
74 case 'b':
75 yylval.node->u.integer = '\b';
76 break;
77
78 case 'r':
79 yylval.node->u.integer = '\r';
80 break;
81
82 case 'f':
83 yylval.node->u.integer = '\f';
84 break;
85
86 case 'a':
87 yylval.node->u.integer = '\a';
88 break;
89
90 default:
91 yylval.node->u.integer = yytext[2];
92 break;
93 }
94
95 return tINTEGER;
96 }
97
98 \/ { yylval.node = node_alloc (nREGEXP);
99 read_regexp (yylval.node);
100 return tREGEXP;
101 }
102
103 "BEGIN" { return tBEGIN; }
104 "END" { return tEND; }
105 "div" { return tDIV; }
106 "else" { return tELSE; }
107 "extends" { return tEXTENDS; }
108 "for" { return tFOR; }
109 "if" { return tIF; }
110 "local" { return tLOCAL; }
111 "namerules" { return tNAMERULES; }
112 "return" { return tRETURN; }
113 "start" { return tSTART; }
114 "startrules" { return tSTARTRULES; }
115 "state" { return tSTATE; }
116 "sub" { return tSUB; }
117 "while" { return tWHILE; }
118
119 "==" { return tEQ; }
120 "!=" { return tNE; }
121 "<=" { return tLE; }
122 ">=" { return tGE; }
123 "&&" { return tAND; }
124 "||" { return tOR; }
125 "++" { return tPLUSPLUS; }
126 "--" { return tMINUSMINUS; }
127 "+=" { return tADDASSIGN; }
128 "-=" { return tSUBASSIGN; }
129 "*=" { return tMULASSIGN; }
130 "div=" { return tDIVASSIGN; }
131
132 {real} { yylval.node = node_alloc (nREAL);
133 yylval.node->u.real = atof (yytext);
134 return tREAL;
135 }
136 {integer} { yylval.node = node_alloc (nINTEGER);
137 yylval.node->u.integer = atoi (yytext);
138 return tINTEGER;
139 }
140 {symbol} { yylval.node = node_alloc (nSYMBOL);
141 yylval.node->u.sym = xstrdup (yytext);
142 return tSYMBOL;
143 }
144
145 . { return yytext[0]; }
146
147 %%
148
149 static void
150 eat_comment ()
151 {
152 int c;
153
154 while ((c = input ()) != EOF)
155 {
156 if (c == '\n')
157 linenum++;
158 else if (c == '*')
159 {
160 c = input ();
161 if (c == '/')
162 /* All done. */
163 return;
164
165 if (c == EOF)
166 {
167 yyerror (_("error: EOF in comment"));
168 break;
169 }
170 unput (c);
171 }
172 }
173 yyerror (_("error: EOF in comment"));
174 }
175
176
177 int
178 yywrap ()
179 {
180 return 1;
181 }
182
183 static char *
184 read_string (len_return)
185 unsigned int *len_return;
186 {
187 char *buf = NULL;
188 char *buf2;
189 int buflen = 0;
190 int bufpos = 0;
191 int ch;
192 int done = 0;
193
194 while (!done)
195 {
196 ch = input ();
197 if (ch == '\n')
198 linenum++;
199
200 switch (ch)
201 {
202 case EOF:
203 unexpected_eof:
204 yyerror (_("error: EOF in string constant"));
205 done = 1;
206 break;
207
208 case '"':
209 done = 1;
210 break;
211
212 case '\\':
213 ch = input ();
214 switch (ch)
215 {
216 case 'n':
217 ch = '\n';
218 break;
219
220 case 't':
221 ch = '\t';
222 break;
223
224 case 'v':
225 ch = '\v';
226 break;
227
228 case 'b':
229 ch = '\b';
230 break;
231
232 case 'r':
233 ch = '\r';
234 break;
235
236 case 'f':
237 ch = '\f';
238 break;
239
240 case 'a':
241 ch = '\a';
242 break;
243
244 case EOF:
245 goto unexpected_eof;
246 break;
247
248 default:
249 if (ch == '0')
250 {
251 int i;
252 int val = 0;
253
254 for (i = 0; i < 3; i++)
255 {
256 ch = input ();
257 if ('0' <= ch && ch <= '7')
258 val = val * 8 + ch - '0';
259 else
260 {
261 unput (ch);
262 break;
263 }
264 }
265 ch = val;
266 }
267 break;
268 }
269 /* FALLTHROUGH */
270
271 default:
272 if (bufpos >= buflen)
273 {
274 buflen += 1024;
275 buf = (char *) xrealloc (buf, buflen);
276 }
277 buf[bufpos++] = ch;
278 break;
279 }
280 }
281
282 buf2 = (char *) xmalloc (bufpos + 1);
283 memcpy (buf2, buf, bufpos);
284 buf2[bufpos] = '\0';
285 xfree (buf);
286
287 *len_return = bufpos;
288
289 return buf2;
290 }
291
292
293 static void
294 read_regexp (node)
295 Node *node;
296 {
297 char *buf = NULL;
298 char *buf2;
299 int buflen = 0;
300 int bufpos = 0;
301 int ch;
302 int done = 0;
303
304 while (!done)
305 {
306 ch = input ();
307 switch (ch)
308 {
309 case EOF:
310 unexpected_eof:
311 yyerror (_("error: EOF in regular expression"));
312 done = 1;
313 break;
314
315 case '/':
316 done = 1;
317 break;
318
319 case '\\':
320 ch = input ();
321 switch (ch)
322 {
323 case '\n':
324 /* Line break. */
325 linenum++;
326 continue;
327 break;
328
329 case 'n':
330 ch = '\n';
331 break;
332
333 case 'r':
334 ch = '\r';
335 break;
336
337 case 'f':
338 ch = '\f';
339 break;
340
341 case 't':
342 ch = '\t';
343 break;
344
345 case '/':
346 case '\\':
347 /* Quote these. */
348 break;
349
350 case EOF:
351 goto unexpected_eof;
352 break;
353
354 default:
355 if (ch == '0')
356 {
357 int i;
358 int val = 0;
359
360 for (i = 0; i < 3; i++)
361 {
362 ch = input ();
363 if ('0' <= ch && ch <= '7')
364 val = val * 8 + ch - '0';
365 else
366 {
367 unput (ch);
368 break;
369 }
370 }
371 ch = val;
372 }
373 else
374 {
375 /* Pass it through. */
376 unput (ch);
377 ch = '\\';
378 }
379 break;
380 }
381 /* FALLTHROUGH */
382
383 default:
384 if (bufpos >= buflen)
385 {
386 buflen += 1024;
387 buf = (char *) xrealloc (buf, buflen);
388 }
389 buf[bufpos++] = ch;
390 break;
391 }
392 }
393
394 /* Possible options. */
395 done = 0;
396 while (!done)
397 {
398 ch = input ();
399 switch (ch)
400 {
401 case 'i':
402 /* Case-insensitive regular expression. */
403 node->u.re.flags |= fRE_CASE_INSENSITIVE;
404 break;
405
406 default:
407 /* Unknown option => this belongs to the next token. */
408 unput (ch);
409 done = 1;
410 break;
411 }
412 }
413
414 buf2 = (char *) xmalloc (bufpos + 1);
415 memcpy (buf2, buf, bufpos);
416 buf2[bufpos] = '\0';
417 xfree (buf);
418
419 node->u.re.data = buf2;
420 node->u.re.len = bufpos;
421 }
422
423
424 /*
425 Local variables:
426 mode: c
427 End:
428 */