1 | %{ |
---|
2 | /* |
---|
3 | * Lexer for states. |
---|
4 | * Copyright (c) 1997 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 | * 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.1.1.1 2002-05-29 18:21:16 ghudson 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 | |
---|
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 | 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 | 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 | "END" { return tEND; } |
---|
107 | "div" { return tDIV; } |
---|
108 | "else" { return tELSE; } |
---|
109 | "for" { return tFOR; } |
---|
110 | "if" { return tIF; } |
---|
111 | "local" { return tLOCAL; } |
---|
112 | "namerules" { return tNAMERULES; } |
---|
113 | "return" { return tRETURN; } |
---|
114 | "start" { return tSTART; } |
---|
115 | "startrules" { return tSTARTRULES; } |
---|
116 | "state" { return tSTATE; } |
---|
117 | "sub" { return tSUB; } |
---|
118 | "while" { return tWHILE; } |
---|
119 | |
---|
120 | "==" { return tEQ; } |
---|
121 | "!=" { return tNE; } |
---|
122 | "<=" { return tLE; } |
---|
123 | ">=" { return tGE; } |
---|
124 | "&&" { return tAND; } |
---|
125 | "||" { return tOR; } |
---|
126 | "++" { return tPLUSPLUS; } |
---|
127 | "--" { return tMINUSMINUS; } |
---|
128 | "+=" { return tADDASSIGN; } |
---|
129 | "-=" { return tSUBASSIGN; } |
---|
130 | "*=" { return tMULASSIGN; } |
---|
131 | "div=" { return tDIVASSIGN; } |
---|
132 | |
---|
133 | {real} { yylval.node = node_alloc (nREAL); |
---|
134 | yylval.node->u.real = atof (yytext); |
---|
135 | return tREAL; |
---|
136 | } |
---|
137 | {integer} { yylval.node = node_alloc (nINTEGER); |
---|
138 | yylval.node->u.integer = atoi (yytext); |
---|
139 | return tINTEGER; |
---|
140 | } |
---|
141 | {symbol} { yylval.node = node_alloc (nSYMBOL); |
---|
142 | yylval.node->u.sym = xstrdup (yytext); |
---|
143 | return tSYMBOL; |
---|
144 | } |
---|
145 | |
---|
146 | . { return yytext[0]; } |
---|
147 | |
---|
148 | %% |
---|
149 | |
---|
150 | static void |
---|
151 | eat_comment () |
---|
152 | { |
---|
153 | int c; |
---|
154 | |
---|
155 | while ((c = input ()) != EOF) |
---|
156 | { |
---|
157 | if (c == '\n') |
---|
158 | linenum++; |
---|
159 | else if (c == '*') |
---|
160 | { |
---|
161 | c = input (); |
---|
162 | if (c == '/') |
---|
163 | /* All done. */ |
---|
164 | return; |
---|
165 | |
---|
166 | if (c == EOF) |
---|
167 | { |
---|
168 | yyerror (_("error: EOF in comment")); |
---|
169 | break; |
---|
170 | } |
---|
171 | unput (c); |
---|
172 | } |
---|
173 | } |
---|
174 | yyerror (_("error: EOF in comment")); |
---|
175 | } |
---|
176 | |
---|
177 | |
---|
178 | int |
---|
179 | yywrap () |
---|
180 | { |
---|
181 | return 1; |
---|
182 | } |
---|
183 | |
---|
184 | static char * |
---|
185 | read_string (len_return) |
---|
186 | unsigned int *len_return; |
---|
187 | { |
---|
188 | char *buf = NULL; |
---|
189 | char *buf2; |
---|
190 | int buflen = 0; |
---|
191 | int bufpos = 0; |
---|
192 | int ch; |
---|
193 | int done = 0; |
---|
194 | |
---|
195 | while (!done) |
---|
196 | { |
---|
197 | ch = input (); |
---|
198 | if (ch == '\n') |
---|
199 | linenum++; |
---|
200 | |
---|
201 | switch (ch) |
---|
202 | { |
---|
203 | case EOF: |
---|
204 | unexpected_eof: |
---|
205 | yyerror (_("error: EOF in string constant")); |
---|
206 | done = 1; |
---|
207 | break; |
---|
208 | |
---|
209 | case '"': |
---|
210 | done = 1; |
---|
211 | break; |
---|
212 | |
---|
213 | case '\\': |
---|
214 | ch = input (); |
---|
215 | switch (ch) |
---|
216 | { |
---|
217 | case 'n': |
---|
218 | ch = '\n'; |
---|
219 | break; |
---|
220 | |
---|
221 | case 't': |
---|
222 | ch = '\t'; |
---|
223 | break; |
---|
224 | |
---|
225 | case 'v': |
---|
226 | ch = '\v'; |
---|
227 | break; |
---|
228 | |
---|
229 | case 'b': |
---|
230 | ch = '\b'; |
---|
231 | break; |
---|
232 | |
---|
233 | case 'r': |
---|
234 | ch = '\r'; |
---|
235 | break; |
---|
236 | |
---|
237 | case 'f': |
---|
238 | ch = '\f'; |
---|
239 | break; |
---|
240 | |
---|
241 | case 'a': |
---|
242 | ch = '\a'; |
---|
243 | break; |
---|
244 | |
---|
245 | case EOF: |
---|
246 | goto unexpected_eof; |
---|
247 | break; |
---|
248 | |
---|
249 | default: |
---|
250 | if (ch == '0') |
---|
251 | { |
---|
252 | int i; |
---|
253 | int val = 0; |
---|
254 | |
---|
255 | for (i = 0; i < 3; i++) |
---|
256 | { |
---|
257 | ch = input (); |
---|
258 | if ('0' <= ch && ch <= '7') |
---|
259 | val = val * 8 + ch - '0'; |
---|
260 | else |
---|
261 | { |
---|
262 | unput (ch); |
---|
263 | break; |
---|
264 | } |
---|
265 | } |
---|
266 | ch = val; |
---|
267 | } |
---|
268 | break; |
---|
269 | } |
---|
270 | /* FALLTHROUGH */ |
---|
271 | |
---|
272 | default: |
---|
273 | if (bufpos >= buflen) |
---|
274 | { |
---|
275 | buflen += 1024; |
---|
276 | buf = (char *) xrealloc (buf, buflen); |
---|
277 | } |
---|
278 | buf[bufpos++] = ch; |
---|
279 | break; |
---|
280 | } |
---|
281 | } |
---|
282 | |
---|
283 | buf2 = (char *) xmalloc (bufpos + 1); |
---|
284 | memcpy (buf2, buf, bufpos); |
---|
285 | buf2[bufpos] = '\0'; |
---|
286 | xfree (buf); |
---|
287 | |
---|
288 | *len_return = bufpos; |
---|
289 | |
---|
290 | return buf2; |
---|
291 | } |
---|
292 | |
---|
293 | |
---|
294 | static void |
---|
295 | read_regexp (node) |
---|
296 | Node *node; |
---|
297 | { |
---|
298 | char *buf = NULL; |
---|
299 | char *buf2; |
---|
300 | int buflen = 0; |
---|
301 | int bufpos = 0; |
---|
302 | int ch; |
---|
303 | int done = 0; |
---|
304 | |
---|
305 | while (!done) |
---|
306 | { |
---|
307 | ch = input (); |
---|
308 | switch (ch) |
---|
309 | { |
---|
310 | case EOF: |
---|
311 | unexpected_eof: |
---|
312 | yyerror (_("error: EOF in regular expression")); |
---|
313 | done = 1; |
---|
314 | break; |
---|
315 | |
---|
316 | case '/': |
---|
317 | done = 1; |
---|
318 | break; |
---|
319 | |
---|
320 | case '\\': |
---|
321 | ch = input (); |
---|
322 | switch (ch) |
---|
323 | { |
---|
324 | case '\n': |
---|
325 | /* Line break. */ |
---|
326 | linenum++; |
---|
327 | continue; |
---|
328 | break; |
---|
329 | |
---|
330 | case 'n': |
---|
331 | ch = '\n'; |
---|
332 | break; |
---|
333 | |
---|
334 | case 'r': |
---|
335 | ch = '\r'; |
---|
336 | break; |
---|
337 | |
---|
338 | case 'f': |
---|
339 | ch = '\f'; |
---|
340 | break; |
---|
341 | |
---|
342 | case 't': |
---|
343 | ch = '\t'; |
---|
344 | break; |
---|
345 | |
---|
346 | case '/': |
---|
347 | case '\\': |
---|
348 | /* Quote these. */ |
---|
349 | break; |
---|
350 | |
---|
351 | case EOF: |
---|
352 | goto unexpected_eof; |
---|
353 | break; |
---|
354 | |
---|
355 | default: |
---|
356 | if (ch == '0') |
---|
357 | { |
---|
358 | int i; |
---|
359 | int val = 0; |
---|
360 | |
---|
361 | for (i = 0; i < 3; i++) |
---|
362 | { |
---|
363 | ch = input (); |
---|
364 | if ('0' <= ch && ch <= '7') |
---|
365 | val = val * 8 + ch - '0'; |
---|
366 | else |
---|
367 | { |
---|
368 | unput (ch); |
---|
369 | break; |
---|
370 | } |
---|
371 | } |
---|
372 | ch = val; |
---|
373 | } |
---|
374 | else |
---|
375 | { |
---|
376 | /* Pass it through. */ |
---|
377 | unput (ch); |
---|
378 | ch = '\\'; |
---|
379 | } |
---|
380 | break; |
---|
381 | } |
---|
382 | /* FALLTHROUGH */ |
---|
383 | |
---|
384 | default: |
---|
385 | if (bufpos >= buflen) |
---|
386 | { |
---|
387 | buflen += 1024; |
---|
388 | buf = (char *) xrealloc (buf, buflen); |
---|
389 | } |
---|
390 | buf[bufpos++] = ch; |
---|
391 | break; |
---|
392 | } |
---|
393 | } |
---|
394 | |
---|
395 | /* Possible options. */ |
---|
396 | done = 0; |
---|
397 | while (!done) |
---|
398 | { |
---|
399 | ch = input (); |
---|
400 | switch (ch) |
---|
401 | { |
---|
402 | case 'i': |
---|
403 | /* Case-insensitive regular expression. */ |
---|
404 | node->u.re.flags |= fRE_CASE_INSENSITIVE; |
---|
405 | break; |
---|
406 | |
---|
407 | default: |
---|
408 | /* Unknown option => this belongs to the next token. */ |
---|
409 | unput (ch); |
---|
410 | done = 1; |
---|
411 | break; |
---|
412 | } |
---|
413 | } |
---|
414 | |
---|
415 | buf2 = (char *) xmalloc (bufpos + 1); |
---|
416 | memcpy (buf2, buf, bufpos); |
---|
417 | buf2[bufpos] = '\0'; |
---|
418 | xfree (buf); |
---|
419 | |
---|
420 | node->u.re.data = buf2; |
---|
421 | node->u.re.len = bufpos; |
---|
422 | } |
---|
423 | |
---|
424 | |
---|
425 | /* |
---|
426 | Local variables: |
---|
427 | mode: c |
---|
428 | End: |
---|
429 | */ |
---|