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