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_INIT                            \
 
  36   LOCATION_RESET (*yylloc);                     \
 
  37   yylloc->file = infile;                        \
 
  38    /* This is only to avoid GCC warnings. */    \
 
  42 #define YY_USER_ACTION  LOCATION_COLUMNS (*yylloc, yyleng);
 
  43 #define YY_LINES        LOCATION_LINES (*yylloc, yyleng);
 
  44 #define YY_STEP         LOCATION_STEP (*yylloc);
 
  46 /* STRING_OBSTACK -- Used to store all the characters that we need to
 
  47    keep (to construct ID, STRINGS etc.).  Use the following macros to
 
  50    Use YY_OBS_GROW to append what has just been matched, and
 
  51    YY_OBS_FINISH to end the string (it puts the ending 0).
 
  52    YY_OBS_FINISH also stores this string in LAST_STRING, which can be
 
  53    used, and which is used by YY_OBS_FREE to free the last string.  */
 
  55 static struct obstack string_obstack;
 
  59   obstack_grow (&string_obstack, yytext, yyleng)
 
  61 #define YY_OBS_FINISH                                   \
 
  63     obstack_1grow (&string_obstack, '\0');              \
 
  64     last_string = obstack_finish (&string_obstack);     \
 
  69     obstack_free (&string_obstack, last_string);                \
 
  73 scanner_last_string_free (void)
 
  79 static int braces_level = 0;
 
  80 static int percent_percent_count = 0;
 
  82 /* Within well-formed rules, RULE_LENGTH is the number of values in
 
  83    the current rule so far, which says where to find `$0' with respect
 
  84    to the top of the stack.  It is not the same as the rule->length in
 
  85    the case of mid rule actions.
 
  87    Outside of well-formed rules, RULE_LENGTH has an undefined value.  */
 
  88 static int rule_length;
 
  90 static void handle_dollar (braced_code_t code_kind,
 
  91                            char *cp, location_t location);
 
  92 static void handle_at (braced_code_t code_kind,
 
  93                        char *cp, location_t location);
 
  97 %x SC_STRING SC_CHARACTER
 
  98 %x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
 
  99 %x SC_BRACED_CODE SC_PROLOGUE SC_EPILOGUE
 
 101 id       [.a-zA-Z_][.a-zA-Z_0-9]*
 
 103 eols     (\n|\r|\n\r|\r\n)+
 
 108   /* At each yylex invocation, mark the current position as the
 
 109      start of the next token.  */
 
 114   /*----------------------------.
 
 115   | Scanning Bison directives.  |
 
 116   `----------------------------*/
 
 119   "%binary"               return PERCENT_NONASSOC;
 
 120   "%debug"                return PERCENT_DEBUG;
 
 121   "%define"               return PERCENT_DEFINE;
 
 122   "%defines"              return PERCENT_DEFINES;
 
 123   "%destructor"           return PERCENT_DESTRUCTOR;
 
 124   "%dprec"                return PERCENT_DPREC;
 
 125   "%error"[-_]"verbose"   return PERCENT_ERROR_VERBOSE;
 
 126   "%expect"               return PERCENT_EXPECT;
 
 127   "%file-prefix"          return PERCENT_FILE_PREFIX;
 
 128   "%fixed"[-_]"output"[-_]"files"   return PERCENT_YACC;
 
 129   "%glr-parser"           return PERCENT_GLR_PARSER;
 
 130   "%left"                 return PERCENT_LEFT;
 
 131   "%locations"            return PERCENT_LOCATIONS;
 
 132   "%merge"                return PERCENT_MERGE;
 
 133   "%name"[-_]"prefix"     return PERCENT_NAME_PREFIX;
 
 134   "%no"[-_]"lines"        return PERCENT_NO_LINES;
 
 135   "%nonassoc"             return PERCENT_NONASSOC;
 
 136   "%nterm"                return PERCENT_NTERM;
 
 137   "%output"               return PERCENT_OUTPUT;
 
 138   "%parse-param"          return PERCENT_PARSE_PARAM;
 
 139   "%prec"                 { rule_length--; return PERCENT_PREC; }
 
 140   "%printer"              return PERCENT_PRINTER;
 
 141   "%pure"[-_]"parser"     return PERCENT_PURE_PARSER;
 
 142   "%right"                return PERCENT_RIGHT;
 
 143   "%lex-param"            return PERCENT_LEX_PARAM;
 
 144   "%skeleton"             return PERCENT_SKELETON;
 
 145   "%start"                return PERCENT_START;
 
 146   "%term"                 return PERCENT_TOKEN;
 
 147   "%token"                return PERCENT_TOKEN;
 
 148   "%token"[-_]"table"     return PERCENT_TOKEN_TABLE;
 
 149   "%type"                 return PERCENT_TYPE;
 
 150   "%union"                return PERCENT_UNION;
 
 151   "%verbose"              return PERCENT_VERBOSE;
 
 152   "%yacc"                 return PERCENT_YACC;
 
 155   ":"                     { rule_length = 0; return COLON; }
 
 156   "|"                     { rule_length = 0; return PIPE; }
 
 158   ";"                     return SEMICOLON;
 
 160   {eols}      YY_LINES; YY_STEP;
 
 163     yylval->symbol = symbol_get (yytext, *yylloc);
 
 168   {int}       yylval->integer = strtol (yytext, 0, 10); return INT;
 
 170   /* Characters.  We don't check there is only one.  */
 
 171   "'"         YY_OBS_GROW; yy_push_state (SC_ESCAPED_CHARACTER);
 
 174   "\""        YY_OBS_GROW; yy_push_state (SC_ESCAPED_STRING);
 
 177   "/*"        yy_push_state (SC_COMMENT);
 
 181   "%{"        yy_push_state (SC_PROLOGUE);
 
 183   /* Code in between braces.  */
 
 184   "{"         YY_OBS_GROW; ++braces_level; yy_push_state (SC_BRACED_CODE);
 
 188     obstack_grow (&string_obstack, yytext + 1, yyleng - 2);
 
 190     yylval->string = last_string;
 
 196     if (++percent_percent_count == 2)
 
 197       yy_push_state (SC_EPILOGUE);
 
 198     return PERCENT_PERCENT;
 
 202     LOCATION_PRINT (stderr, *yylloc);
 
 203     fprintf (stderr, _(": invalid character: `%c'\n"), *yytext);
 
 209   /*------------------------------------------------------------.
 
 210   | Whatever the start condition (but those which correspond to |
 
 211   | entity `swallowed' by Bison: SC_ESCAPED_STRING and          |
 
 212   | SC_ESCAPED_CHARACTER), no M4 character must escape as is.   |
 
 213   `------------------------------------------------------------*/
 
 215 <SC_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
 
 217   \[          if (YY_START != SC_COMMENT) obstack_sgrow (&string_obstack, "@<:@");
 
 218   \]          if (YY_START != SC_COMMENT) obstack_sgrow (&string_obstack, "@:>@");
 
 223   /*-----------------------------------------------------------.
 
 224   | Scanning a C comment. The initial `/ *' is already eaten.  |
 
 225   `-----------------------------------------------------------*/
 
 229   "*/" { /* End of the comment. */
 
 230     if (yy_top_state () == INITIAL)
 
 241   [^\[\]*\n\r]+         if (yy_top_state () != INITIAL) YY_OBS_GROW;
 
 242   {eols}        if (yy_top_state () != INITIAL) YY_OBS_GROW; YY_LINES;
 
 243   .             /* Stray `*'. */if (yy_top_state () != INITIAL) YY_OBS_GROW;
 
 246     LOCATION_PRINT (stderr, *yylloc);
 
 247     fprintf (stderr, _(": unexpected end of file in a comment\n"));
 
 253   /*----------------------------------------------------------------.
 
 254   | Scanning a C string, including its escapes.  The initial `"' is |
 
 256   `----------------------------------------------------------------*/
 
 261     assert (yy_top_state () == INITIAL);
 
 264     yylval->string = last_string;
 
 270   [^\"\n\r\\]+      YY_OBS_GROW;
 
 272   {eols}    obstack_1grow (&string_obstack, '\n'); YY_LINES;
 
 275     LOCATION_PRINT (stderr, *yylloc);
 
 276     fprintf (stderr, _(": unexpected end of file in a string\n"));
 
 277     assert (yy_top_state () == INITIAL);
 
 279     yylval->string = last_string;
 
 285   /*---------------------------------------------------------------.
 
 286   | Scanning a C character, decoding its escapes.  The initial "'" |
 
 287   | is already eaten.                                              |
 
 288   `---------------------------------------------------------------*/
 
 290 <SC_ESCAPED_CHARACTER>
 
 294     assert (yy_top_state () == INITIAL);
 
 297       yylval->symbol = symbol_get (last_string, *yylloc);
 
 298       symbol_class_set (yylval->symbol, token_sym, *yylloc);
 
 299       symbol_user_token_number_set (yylval->symbol,
 
 300                                     (unsigned char) last_string[1], *yylloc);
 
 308   [^\n\r\\] YY_OBS_GROW;
 
 310   {eols}    obstack_1grow (&string_obstack, '\n'); YY_LINES;
 
 313     LOCATION_PRINT (stderr, *yylloc);
 
 314     fprintf (stderr, _(": unexpected end of file in a character\n"));
 
 315     assert (yy_top_state () == INITIAL);
 
 317     yylval->string = last_string;
 
 324   /*----------------------------.
 
 325   | Decode escaped characters.  |
 
 326   `----------------------------*/
 
 328 <SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>
 
 331     long c = strtol (yytext + 1, 0, 8);
 
 334         LOCATION_PRINT (stderr, *yylloc);
 
 335         fprintf (stderr, _(": invalid escape: %s\n"), quote (yytext));
 
 339       obstack_1grow (&string_obstack, c);
 
 343     obstack_1grow (&string_obstack, strtol (yytext + 2, 0, 16));
 
 346   \\a   obstack_1grow (&string_obstack, '\a');
 
 347   \\b   obstack_1grow (&string_obstack, '\b');
 
 348   \\f   obstack_1grow (&string_obstack, '\f');
 
 349   \\n   obstack_1grow (&string_obstack, '\n');
 
 350   \\r   obstack_1grow (&string_obstack, '\r');
 
 351   \\t   obstack_1grow (&string_obstack, '\t');
 
 352   \\v   obstack_1grow (&string_obstack, '\v');
 
 353   \\[\\""'']   obstack_1grow (&string_obstack, yytext[1]);
 
 355     LOCATION_PRINT (stderr, *yylloc);
 
 356     fprintf (stderr, _(": unrecognized escape: %s\n"), quote (yytext));
 
 359   /* FLex wants this rule, in case of a `\<<EOF>>'. */
 
 364   /*----------------------------------------------------------.
 
 365   | Scanning a C character without decoding its escapes.  The |
 
 366   | initial "'" is already eaten.                             |
 
 367   `----------------------------------------------------------*/
 
 373     assert (yy_top_state () != INITIAL);
 
 377   [^\[\]\'\n\r\\]+     YY_OBS_GROW;
 
 378   \\(.|\n)             YY_OBS_GROW;
 
 379   /* FLex wants this rule, in case of a `\<<EOF>>'. */
 
 382   {eols}               YY_OBS_GROW; YY_LINES;
 
 385     LOCATION_PRINT (stderr, *yylloc);
 
 386     fprintf (stderr, _(": unexpected end of file in a character\n"));
 
 387     assert (yy_top_state () != INITIAL);
 
 393   /*----------------------------------------------------------------.
 
 394   | Scanning a C string, without decoding its escapes.  The initial |
 
 395   | `"' is already eaten.                                           |
 
 396   `----------------------------------------------------------------*/
 
 401     assert (yy_top_state () != INITIAL);
 
 406   [^\[\]\"\n\r\\]+      YY_OBS_GROW;
 
 407   \\(.|\n)              YY_OBS_GROW;
 
 408   /* FLex wants this rule, in case of a `\<<EOF>>'. */
 
 411   {eols}                YY_OBS_GROW; YY_LINES;
 
 414     LOCATION_PRINT (stderr, *yylloc);
 
 415     fprintf (stderr, _(": unexpected end of file in a string\n"));
 
 416     assert (yy_top_state () != INITIAL);
 
 422   /*---------------------------------------------------.
 
 423   | Strings, comments etc. can be found in user code.  |
 
 424   `---------------------------------------------------*/
 
 426 <SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
 
 428   /* Characters.  We don't check there is only one.  */
 
 429   "'"         YY_OBS_GROW; yy_push_state (SC_CHARACTER);
 
 432   "\""        YY_OBS_GROW; yy_push_state (SC_STRING);
 
 435   "/*"        YY_OBS_GROW; yy_push_state (SC_COMMENT);
 
 443   /*---------------------------------------------------------------.
 
 444   | Scanning some code in braces (%union and actions). The initial |
 
 445   | "{" is already eaten.                                          |
 
 446   `---------------------------------------------------------------*/
 
 452     if (--braces_level == 0)
 
 456         yylval->string = last_string;
 
 462   "{"           YY_OBS_GROW; braces_level++;
 
 464   "$"("<"[^>]+">")?(-?[0-9]+|"$") { handle_dollar (current_braced_code,
 
 466   "@"(-?[0-9]+|"$")               { handle_at (current_braced_code,
 
 469   [^$@\[\]/\'\"\{\}\n\r]+ YY_OBS_GROW;
 
 470   {eols}        YY_OBS_GROW; YY_LINES;
 
 472   /* A lose $, or /, or etc. */
 
 476     LOCATION_PRINT (stderr, *yylloc);
 
 477     fprintf (stderr, _(": unexpected end of file in a braced code\n"));
 
 480     yylval->string = last_string;
 
 487   /*--------------------------------------------------------------.
 
 488   | Scanning some prologue: from "%{" (already scanned) to "%}".  |
 
 489   `--------------------------------------------------------------*/
 
 496     yylval->string = last_string;
 
 500   [^%\[\]/\'\"\n\r]+ YY_OBS_GROW;
 
 502   {eols}             YY_OBS_GROW; YY_LINES;
 
 505     LOCATION_PRINT (stderr, *yylloc);
 
 506     fprintf (stderr, _(": unexpected end of file in a prologue\n"));
 
 509     yylval->string = last_string;
 
 515   /*---------------------------------------------------------------.
 
 516   | Scanning the epilogue (everything after the second "%%", which |
 
 517   | has already been eaten.                                        |
 
 518   `---------------------------------------------------------------*/
 
 522   ([^\[\]]|{eols})+  YY_OBS_GROW;
 
 527     yylval->string = last_string;
 
 535 /*------------------------------------------------------------------.
 
 536 | TEXT is pointing to a wannabee semantic value (i.e., a `$').      |
 
 538 | Possible inputs: $[<TYPENAME>]($|integer)                         |
 
 540 | Output to the STRING_OBSTACK a reference to this semantic value.  |
 
 541 `------------------------------------------------------------------*/
 
 544 handle_action_dollar (char *text, location_t location)
 
 546   const char *type_name = NULL;
 
 549   /* Get the type name if explicit. */
 
 562         type_name = symbol_list_n_type_name_get (current_rule, location, 0);
 
 563       if (!type_name && typed)
 
 564         complain_at (location, _("$$ of `%s' has no declared type"),
 
 565                      current_rule->sym->tag);
 
 568       obstack_fgrow1 (&string_obstack,
 
 569                       "]b4_lhs_value([%s])[", type_name);
 
 571   else if (('0' <= *cp && *cp <= '9') || *cp == '-')
 
 573       int n = strtol (cp, &cp, 10);
 
 576         complain_at (location, _("invalid value: %s%d"), "$", n);
 
 579           if (!type_name && n > 0)
 
 580             type_name = symbol_list_n_type_name_get (current_rule, location,
 
 582           if (!type_name && typed)
 
 583             complain_at (location, _("$%d of `%s' has no declared type"),
 
 584                       n, current_rule->sym->tag);
 
 587           obstack_fgrow3 (&string_obstack,
 
 588                           "]b4_rhs_value([%d], [%d], [%s])[",
 
 589                           rule_length, n, type_name);
 
 594       complain_at (location, _("%s is invalid"), quote (text));
 
 599 /*---------------------------------------------------------------.
 
 600 | TEXT is expexted tp be $$ in some code associated to a symbol: |
 
 601 | destructor or printer.                                         |
 
 602 `---------------------------------------------------------------*/
 
 605 handle_symbol_code_dollar (char *text, location_t location)
 
 609     obstack_sgrow (&string_obstack, "]b4_dollar_dollar[");
 
 611     complain_at (location, _("%s is invalid"), quote (text));
 
 615 /*-----------------------------------------------------------------.
 
 616 | Dispatch onto handle_action_dollar, or handle_destructor_dollar, |
 
 617 | depending upon CODE_KIND.                                        |
 
 618 `-----------------------------------------------------------------*/
 
 621 handle_dollar (braced_code_t braced_code_kind,
 
 622                char *text, location_t location)
 
 624   switch (braced_code_kind)
 
 626     case action_braced_code:
 
 627       handle_action_dollar (text, location);
 
 630     case destructor_braced_code:
 
 631     case printer_braced_code:
 
 632       handle_symbol_code_dollar (text, location);
 
 638 /*------------------------------------------------------.
 
 639 | TEXT is a location token (i.e., a `@...').  Output to |
 
 640 | STRING_OBSTACK a reference to this location.          |
 
 641 `------------------------------------------------------*/
 
 644 handle_action_at (char *text, location_t location)
 
 651       obstack_sgrow (&string_obstack, "]b4_lhs_location[");
 
 653   else if (('0' <= *cp && *cp <= '9') || *cp == '-')
 
 655       int n = strtol (cp, &cp, 10);
 
 658         complain_at (location, _("invalid value: %s%d"), "@", n);
 
 660         obstack_fgrow2 (&string_obstack, "]b4_rhs_location([%d], [%d])[",
 
 665       complain_at (location, _("%s is invalid"), quote (text));
 
 670 /*---------------------------------------------------------------.
 
 671 | TEXT is expexted tp be @$ in some code associated to a symbol: |
 
 672 | destructor or printer.                                         |
 
 673 `---------------------------------------------------------------*/
 
 676 handle_symbol_code_at (char *text, location_t location)
 
 680     obstack_sgrow (&string_obstack, "]b4_at_dollar[");
 
 682     complain_at (location, _("%s is invalid"), quote (text));
 
 686 /*-------------------------------------------------------------------.
 
 687 | Dispatch onto handle_action_at, or handle_destructor_at, depending |
 
 689 `-------------------------------------------------------------------*/
 
 692 handle_at (braced_code_t braced_code_kind,
 
 693            char *text, location_t location)
 
 695   switch (braced_code_kind)
 
 697     case action_braced_code:
 
 698       handle_action_at (text, location);
 
 701     case destructor_braced_code:
 
 702     case printer_braced_code:
 
 703       handle_symbol_code_at (text, location);
 
 709 /*-------------------------.
 
 710 | Initialize the scanner.  |
 
 711 `-------------------------*/
 
 714 scanner_initialize (void)
 
 716   obstack_init (&string_obstack);
 
 720 /*-----------------------------------------------.
 
 721 | Free all the memory allocated to the scanner.  |
 
 722 `-----------------------------------------------*/
 
 727   obstack_free (&string_obstack, 0);
 
 728   /* Reclaim Flex's buffers.  */
 
 729   yy_delete_buffer (YY_CURRENT_BUFFER);