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 */
429