1 /* Bison Grammar Scanner -*- C -*-
2 Copyright (C) 2002 Free Software Foundation, Inc.
4 This file is part of Bison, the GNU Compiler Compiler.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 %option debug nodefault noyywrap nounput never-interactive stack
23 %option prefix="gram_" outfile="lex.yy.c"
33 /* Each time we match a string, move the end cursor to its end. */
34 #define YY_USER_ACTION LOCATION_COLUMNS (*yylloc, yyleng)
35 #define YY_LINES LOCATION_LINES (*yylloc, yyleng); lineno += yyleng;
36 #define YY_STEP LOCATION_STEP (*yylloc)
39 /* STRING_OBSTACK -- Used to store all the characters that we need to
40 keep (to construct ID, STRINGS etc.). Use the following macros to
43 Use YY_OBS_GROW to append what has just been matched, and
44 YY_OBS_FINISH to end the string (it puts the ending 0).
45 YY_OBS_FINISH also stores this string in LAST_STRING, which can be
46 used, and which is used by YY_OBS_FREE to free the last string. */
48 static struct obstack string_obstack;
52 obstack_grow (&string_obstack, yytext, yyleng)
54 #define YY_OBS_FINISH \
56 obstack_1grow (&string_obstack, '\0'); \
57 last_string = obstack_finish (&string_obstack); \
62 obstack_free (&string_obstack, last_string); \
66 scanner_last_string_free (void)
72 /* This is only to avoid GCC warnings. */
73 #define YY_USER_INIT if (yycontrol) {;};
76 static int braces_level = 0;
77 static int percent_percent_count = 0;
79 static void handle_dollar PARAMS ((char *cp));
80 static void handle_at PARAMS ((char *cp));
84 %x SC_STRING SC_CHARACTER
85 %x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
86 %x SC_BRACED_CODE SC_PROLOGUE SC_EPILOGUE
88 id [.a-zA-Z][.a-zA-Z_0-9]*
90 eols (\n|\r|\n\r|\r\n)+
95 /* At each yylex invocation, mark the current position as the
96 start of the next token. */
99 fprintf (stderr, "FOO1: ");
100 LOCATION_PRINT (stderr, *yylloc);
101 fprintf (stderr, "\n");
105 fprintf (stderr, "BAR1: ");
106 LOCATION_PRINT (stderr, *yylloc);
107 fprintf (stderr, "\n");
112 /*----------------------------.
113 | Scanning Bison directives. |
114 `----------------------------*/
117 "%binary" return PERCENT_NONASSOC;
118 "%debug" return PERCENT_DEBUG;
119 "%define" return PERCENT_DEFINE;
120 "%defines" return PERCENT_DEFINES;
121 "%error"[-_]"verbose" return PERCENT_ERROR_VERBOSE;
122 "%expect" return PERCENT_EXPECT;
123 "%file-prefix" return PERCENT_FILE_PREFIX;
124 "%fixed"[-_]"output"[-_]"files" return PERCENT_YACC;
125 "%left" return PERCENT_LEFT;
126 "%locations" return PERCENT_LOCATIONS;
127 "%name"[-_]"prefix" return PERCENT_NAME_PREFIX;
128 "%no"[-_]"lines" return PERCENT_NO_LINES;
129 "%nonassoc" return PERCENT_NONASSOC;
130 "%nterm" return PERCENT_NTERM;
131 "%output" return PERCENT_OUTPUT;
132 "%prec" return PERCENT_PREC;
133 "%pure"[-_]"parser" return PERCENT_PURE_PARSER;
134 "%right" return PERCENT_RIGHT;
135 "%skeleton" return PERCENT_SKELETON;
136 "%start" return PERCENT_START;
137 "%term" return PERCENT_TOKEN;
138 "%token" return PERCENT_TOKEN;
139 "%token"[-_]"table" return PERCENT_TOKEN_TABLE;
140 "%type" return PERCENT_TYPE;
141 "%union" return PERCENT_UNION;
142 "%verbose" return PERCENT_VERBOSE;
143 "%yacc" return PERCENT_YACC;
148 ";" return SEMICOLON;
150 {eols} YY_LINES; YY_STEP;
153 yylval->symbol = getsym (yytext);
157 {int} yylval->integer = strtol (yytext, 0, 10); return INT;
159 /* Characters. We don't check there is only one. */
160 \' YY_OBS_GROW; yy_push_state (SC_ESCAPED_CHARACTER);
163 \" YY_OBS_GROW; yy_push_state (SC_ESCAPED_STRING);
166 "/*" yy_push_state (SC_COMMENT);
170 "%{" yy_push_state (SC_PROLOGUE);
172 /* Code in between braces. */
173 "{" YY_OBS_GROW; ++braces_level; yy_push_state (SC_BRACED_CODE);
177 obstack_grow (&string_obstack, yytext + 1, yyleng - 2);
179 yylval->string = last_string;
185 if (++percent_percent_count == 2)
186 yy_push_state (SC_EPILOGUE);
187 return PERCENT_PERCENT;
191 LOCATION_PRINT (stderr, *yylloc);
192 fprintf (stderr, ": invalid character: `%c'\n", *yytext);
198 /*------------------------------------------------------------.
199 | Whatever the start condition (but those which correspond to |
200 | entity `swallowed' by Bison: SC_ESCAPED_STRING and |
201 | SC_ESCAPED_CHARACTER), no M4 character must escape as is. |
202 `------------------------------------------------------------*/
204 <SC_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
206 \[ if (YY_START != SC_COMMENT) obstack_sgrow (&string_obstack, "@<:@");
207 \] if (YY_START != SC_COMMENT) obstack_sgrow (&string_obstack, "@:>@");
212 /*-----------------------------------------------------------.
213 | Scanning a C comment. The initial `/ *' is already eaten. |
214 `-----------------------------------------------------------*/
218 "*/" { /* End of the comment. */
219 if (yy_top_state () == INITIAL)
230 [^\[\]*\n\r]+ if (yy_top_state () != INITIAL) YY_OBS_GROW;
231 {eols} if (yy_top_state () != INITIAL) YY_OBS_GROW; YY_LINES;
232 . /* Stray `*'. */if (yy_top_state () != INITIAL) YY_OBS_GROW;
235 LOCATION_PRINT (stderr, *yylloc);
236 fprintf (stderr, ": unexpected end of file in a comment\n");
242 /*----------------------------------------------------------------.
243 | Scanning a C string, including its escapes. The initial `"' is |
245 `----------------------------------------------------------------*/
250 assert (yy_top_state () == INITIAL);
253 yylval->string = last_string;
258 [^\"\n\r\\]+ YY_OBS_GROW;
260 {eols} obstack_1grow (&string_obstack, '\n'); YY_LINES;
263 LOCATION_PRINT (stderr, *yylloc);
264 fprintf (stderr, ": unexpected end of file in a string\n");
265 assert (yy_top_state () == INITIAL);
267 yylval->string = last_string;
273 /*---------------------------------------------------------------.
274 | Scanning a C character, decoding its escapes. The initial "'" |
275 | is already eaten. |
276 `---------------------------------------------------------------*/
278 <SC_ESCAPED_CHARACTER>
282 assert (yy_top_state () == INITIAL);
285 yylval->symbol = getsym (last_string);
286 symbol_class_set (yylval->symbol, token_sym);
287 symbol_user_token_number_set (yylval->symbol, last_string[1]);
294 [^\'\n\r\\] YY_OBS_GROW;
296 {eols} obstack_1grow (&string_obstack, '\n'); YY_LINES;
299 LOCATION_PRINT (stderr, *yylloc);
300 fprintf (stderr, ": unexpected end of file in a character\n");
301 assert (yy_top_state () == INITIAL);
303 yylval->string = last_string;
310 /*----------------------------.
311 | Decode escaped characters. |
312 `----------------------------*/
314 <SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>
317 long c = strtol (yytext + 1, 0, 8);
320 LOCATION_PRINT (stderr, *yylloc);
321 fprintf (stderr, ": invalid escape: %s\n", yytext);
325 obstack_1grow (&string_obstack, c);
329 obstack_1grow (&string_obstack, strtol (yytext + 2, 0, 16));
332 \\a obstack_1grow (&string_obstack, '\a');
333 \\b obstack_1grow (&string_obstack, '\b');
334 \\f obstack_1grow (&string_obstack, '\f');
335 \\n obstack_1grow (&string_obstack, '\n');
336 \\r obstack_1grow (&string_obstack, '\r');
337 \\t obstack_1grow (&string_obstack, '\t');
338 \\v obstack_1grow (&string_obstack, '\v');
339 \\[\\""] obstack_1grow (&string_obstack, yytext[1]);
341 LOCATION_PRINT (stderr, *yylloc);
342 fprintf (stderr, ": unrecognized escape: %s\n", yytext);
348 /*----------------------------------------------------------.
349 | Scanning a C character without decoding its escapes. The |
350 | initial "'" is already eaten. |
351 `----------------------------------------------------------*/
357 assert (yy_top_state () != INITIAL);
361 [^\[\]\'\n\r\\] YY_OBS_GROW;
364 {eols} YY_OBS_GROW; YY_LINES;
367 LOCATION_PRINT (stderr, *yylloc);
368 fprintf (stderr, ": unexpected end of file in a character\n");
369 assert (yy_top_state () != INITIAL);
375 /*----------------------------------------------------------------.
376 | Scanning a C string, without decoding its escapes. The initial |
377 | `"' is already eaten. |
378 `----------------------------------------------------------------*/
383 assert (yy_top_state () != INITIAL);
388 [^\[\]\"\n\r\\]+ YY_OBS_GROW;
391 {eols} YY_OBS_GROW; YY_LINES;
394 LOCATION_PRINT (stderr, *yylloc);
395 fprintf (stderr, ": unexpected end of file in a string\n");
396 assert (yy_top_state () != INITIAL);
402 /*---------------------------------------------------.
403 | Strings, comments etc. can be found in user code. |
404 `---------------------------------------------------*/
406 <SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
408 /* Characters. We don't check there is only one. */
409 \' YY_OBS_GROW; yy_push_state (SC_CHARACTER);
412 \" YY_OBS_GROW; yy_push_state (SC_STRING);
415 "/*" YY_OBS_GROW; yy_push_state (SC_COMMENT);
420 /*---------------------------------------------------------------.
421 | Scanning some code in braces (%union and actions). The initial |
422 | "{" is already eaten. |
423 `---------------------------------------------------------------*/
429 if (--braces_level == 0)
433 yylval->string = last_string;
438 "{" YY_OBS_GROW; braces_level++;
440 "$"("<".*">")?(-?[0-9]+|"$") { handle_dollar (yytext); }
441 "@"(-?[0-9]+|"$") { handle_at (yytext); }
443 [^$@\[\]/\'\"\{\}\n\r]+ YY_OBS_GROW;
444 {eols} YY_OBS_GROW; YY_LINES;
446 /* A lose $, or /, or etc. */
450 LOCATION_PRINT (stderr, *yylloc);
451 fprintf (stderr, ": unexpected end of file in a braced code\n");
454 yylval->string = last_string;
461 /*--------------------------------------------------------------.
462 | Scanning some prologue: from "%{" (already scanned) to "%}". |
463 `--------------------------------------------------------------*/
470 yylval->string = last_string;
474 [^%\[\]/\'\"\n\r]+ YY_OBS_GROW;
475 "%"+[^%\}\n\r]+ YY_OBS_GROW;
476 {eols} YY_OBS_GROW; YY_LINES;
479 LOCATION_PRINT (stderr, *yylloc);
480 fprintf (stderr, ": unexpected end of file in a prologue\n");
483 yylval->string = last_string;
490 /*---------------------------------------------------------------.
491 | Scanning the epilogue (everything after the second "%%", which |
492 | has already been eaten. |
493 `---------------------------------------------------------------*/
497 ([^\[\]]|{eols})+ YY_OBS_GROW;
502 yylval->string = last_string;
510 /*------------------------------------------------------------------.
511 | CP is pointing to a wannabee semantic value (i.e., a `$'). |
513 | Possible inputs: $[<TYPENAME>]($|integer) |
515 | Output to the STRING_OBSTACK a reference to this semantic value. |
516 `------------------------------------------------------------------*/
519 handle_dollar (char *cp)
521 const char *type_name = NULL;
523 /* RULE_LENGTH is the number of values in the current rule so far,
524 which says where to find `$0' with respect to the top of the
525 stack. It is not the same as the rule->length in the case of mid
529 for (rhs = current_rule->next; rhs; rhs = rhs->next)
534 /* Get the type name if explicit. */
547 type_name = get_type_name (0, current_rule);
548 if (!type_name && typed)
549 complain (_("$$ of `%s' has no declared type"),
550 current_rule->sym->tag);
553 obstack_fgrow1 (&string_obstack,
554 "]b4_lhs_value([%s])[", type_name);
556 else if (isdigit (*cp) || *cp == '-')
558 int n = strtol (cp, &cp, 10);
561 complain (_("invalid value: %s%d"), "$", n);
564 if (!type_name && n > 0)
565 type_name = get_type_name (n, current_rule);
566 if (!type_name && typed)
567 complain (_("$%d of `%s' has no declared type"),
568 n, current_rule->sym->tag);
571 obstack_fgrow3 (&string_obstack,
572 "]b4_rhs_value([%d], [%d], [%s])[",
573 rule_length, n, type_name);
580 complain (_("%s is invalid"), quote (buf));
584 /*-------------------------------------------------------.
585 | CP is pointing to a location (i.e., a `@'). Output to |
586 | STRING_OBSTACK a reference to this location. |
587 `-------------------------------------------------------*/
592 /* RULE_LENGTH is the number of values in the current rule so far,
593 which says where to find `$0' with respect to the top of the
594 stack. It is not the same as the rule->length in the case of mid
598 for (rhs = current_rule->next; rhs; rhs = rhs->next)
606 obstack_sgrow (&string_obstack, "]b4_lhs_location[");
608 else if (isdigit (*cp) || *cp == '-')
610 int n = strtol (cp, &cp, 10);
612 complain (_("invalid value: %s%d"), "@", n);
614 obstack_fgrow2 (&string_obstack, "]b4_rhs_location([%d], [%d])[",
621 complain (_("%s is invalid"), quote (buf));
626 scanner_initialize (void)
628 obstack_init (&string_obstack);
635 obstack_free (&string_obstack, 0);