1 /* Bison Action Scanner                             -*- C -*-
 
   3    Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
 
   5    This file is part of Bison, the GNU Compiler Compiler.
 
   7    This program is free software: you can redistribute it and/or modify
 
   8    it under the terms of the GNU General Public License as published by
 
   9    the Free Software Foundation, either version 3 of the License, or
 
  10    (at your option) any later version.
 
  12    This program is distributed in the hope that it will be useful,
 
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  15    GNU General Public License for more details.
 
  17    You should have received a copy of the GNU General Public License
 
  18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
  20 %option debug nodefault nounput noyywrap never-interactive
 
  21 %option prefix="code_" outfile="lex.yy.c"
 
  24 /* Work around a bug in flex 2.5.31.  See Debian bug 333231
 
  25    <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>.  */
 
  29 #define FLEX_PREFIX(Id) code_ ## Id
 
  30 #include <src/flex-scanner.h>
 
  32 #include <src/complain.h>
 
  33 #include <src/reader.h>
 
  34 #include <src/getargs.h>
 
  35 #include <get-errno.h>
 
  38 #include <src/scan-code.h>
 
  39 #include <src/symlist.h>
 
  41 /* The current calling start condition: SC_RULE_ACTION or
 
  43 # define YY_DECL static char *code_lex (code_props *self, int sc_context)
 
  46 #define YY_USER_ACTION  location_compute (loc, &loc->end, yytext, yyleng);
 
  48 static void handle_action_dollar (symbol_list *rule, char *cp,
 
  50 static void handle_action_at (symbol_list *rule, char *cp, location at_loc);
 
  51 static location the_location;
 
  52 static location *loc = &the_location;
 
  54 /* A string representing the most recent translation.  */
 
  55 static char *last_string;
 
  57 /* True if an untyped $$ or $n was seen.  */
 
  58 static bool untyped_var_seen;
 
  60  /* C and C++ comments in code. */
 
  61 %x SC_COMMENT SC_LINE_COMMENT
 
  62  /* Strings and characters in code. */
 
  63 %x SC_STRING SC_CHARACTER
 
  64  /* Whether in a rule or symbol action.  Specifies the translation
 
  66 %x SC_RULE_ACTION SC_SYMBOL_ACTION
 
  69 /* POSIX says that a tag must be both an id and a C union member, but
 
  70    historically almost any character is allowed in a tag.  We disallow
 
  71    NUL and newline, as this simplifies our implementation.  */
 
  74 /* Zero or more instances of backslash-newline.  Following GCC, allow
 
  75    white space between the backslash and the newline.  */
 
  76 splice   (\\[ \f\t\v]*\n)*
 
  81   /* Nesting level of the current code in braces.  */
 
  84   /* This scanner is special: it is invoked only once, henceforth
 
  85      is expected to return only once.  This initialization is
 
  86      therefore done once per action to translate. */
 
  87   aver (sc_context == SC_SYMBOL_ACTION
 
  88         || sc_context == SC_RULE_ACTION
 
  89         || sc_context == INITIAL);
 
  93   /*------------------------------------------------------------.
 
  94   | Scanning a C comment.  The initial `/ *' is already eaten.  |
 
  95   `------------------------------------------------------------*/
 
  99   "*"{splice}"/"  STRING_GROW; BEGIN sc_context;
 
 103   /*--------------------------------------------------------------.
 
 104   | Scanning a line comment.  The initial `//' is already eaten.  |
 
 105   `--------------------------------------------------------------*/
 
 109   "\n"           STRING_GROW; BEGIN sc_context;
 
 110   {splice}       STRING_GROW;
 
 114   /*--------------------------------------------.
 
 115   | Scanning user-code characters and strings.  |
 
 116   `--------------------------------------------*/
 
 118 <SC_CHARACTER,SC_STRING>
 
 120   {splice}|\\{splice}.  STRING_GROW;
 
 125   "'"           STRING_GROW; BEGIN sc_context;
 
 130   "\""          STRING_GROW; BEGIN sc_context;
 
 134 <SC_RULE_ACTION,SC_SYMBOL_ACTION>{
 
 149     BEGIN SC_LINE_COMMENT;
 
 155   "$"("<"{tag}">")?(-?[0-9]+|"$")  {
 
 156     handle_action_dollar (self->rule, yytext, *loc);
 
 159     handle_action_at (self->rule, yytext, *loc);
 
 163     warn_at (*loc, _("stray `$'"));
 
 164     obstack_sgrow (&obstack_for_string, "$][");
 
 167     warn_at (*loc, _("stray `@'"));
 
 168     obstack_sgrow (&obstack_for_string, "@@");
 
 171   "{"  STRING_GROW; ++braces_level;
 
 173     bool outer_brace = --braces_level == 0;
 
 175     /* As an undocumented Bison extension, append `;' before the last
 
 176        brace in braced code, so that the user code can omit trailing
 
 177        `;'.  But do not append `;' if emulating Yacc, since Yacc does
 
 178        not append one.  Also, some output languages (like Java) do not
 
 179        accept an extra semicolon, so don't append if the user specified
 
 180        a skeleton or language.
 
 182        FIXME: Bison should warn if a semicolon seems to be necessary
 
 183        here, and should omit the semicolon if it seems unnecessary
 
 184        (e.g., after ';', '{', or '}', each followed by comments or
 
 185        white space).  Such a warning shouldn't depend on --yacc; it
 
 186        should depend on a new --pedantic option, which would cause
 
 187        Bison to warn if it detects an extension to POSIX.  --pedantic
 
 188        should also diagnose other Bison extensions like %yacc.
 
 189        Perhaps there should also be a GCC-style --pedantic-errors
 
 190        option, so that such warnings are diagnosed as errors.  */
 
 191     if (outer_brace && !yacc_flag && language_prio == default_prio
 
 192         && skeleton_prio == default_prio)
 
 193       obstack_1grow (&obstack_for_string, ';');
 
 202     obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
 
 203     self->is_value_used = true;
 
 206     obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
 
 207     locations_flag = true;
 
 212   /*-----------------------------------------.
 
 213   | Escape M4 quoting characters in C code.  |
 
 214   `-----------------------------------------*/
 
 218   \$    obstack_sgrow (&obstack_for_string, "$][");
 
 219   \@    obstack_sgrow (&obstack_for_string, "@@");
 
 220   \[    obstack_sgrow (&obstack_for_string, "@{");
 
 221   \]    obstack_sgrow (&obstack_for_string, "@}");
 
 224   /*-----------------------------------------------------.
 
 225   | By default, grow the string obstack with the input.  |
 
 226   `-----------------------------------------------------*/
 
 230  /* End of processing. */
 
 238 /* Keeps track of the maximum number of semantic values to the left of
 
 239    a handle (those referenced by $0, $-1, etc.) are required by the
 
 240    semantic actions of this grammar. */
 
 241 int max_left_semantic_context = 0;
 
 244 /*------------------------------------------------------------------.
 
 245 | TEXT is pointing to a wannabee semantic value (i.e., a `$').      |
 
 247 | Possible inputs: $[<TYPENAME>]($|integer)                         |
 
 249 | Output to OBSTACK_FOR_STRING a reference to this semantic value.  |
 
 250 `------------------------------------------------------------------*/
 
 253 handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
 
 255   char const *type_name = NULL;
 
 257   symbol_list *effective_rule;
 
 258   int effective_rule_length;
 
 260   if (rule->midrule_parent_rule)
 
 262       effective_rule = rule->midrule_parent_rule;
 
 263       effective_rule_length = rule->midrule_parent_rhs_index - 1;
 
 267       effective_rule = rule;
 
 268       effective_rule_length = symbol_list_length (rule->next);
 
 271   /* Get the type name if explicit. */
 
 279       if (untyped_var_seen)
 
 280         complain_at (dollar_loc, _("explicit type given in untyped grammar"));
 
 287         type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
 
 291           if (union_seen | tag_seen)
 
 293               if (rule->midrule_parent_rule)
 
 294                 complain_at (dollar_loc,
 
 295                              _("$$ for the midrule at $%d of `%s'"
 
 296                                " has no declared type"),
 
 297                              rule->midrule_parent_rhs_index,
 
 298                              effective_rule->content.sym->tag);
 
 300                 complain_at (dollar_loc, _("$$ of `%s' has no declared type"),
 
 301                              rule->content.sym->tag);
 
 304             untyped_var_seen = true;
 
 308       obstack_fgrow1 (&obstack_for_string,
 
 309                       "]b4_lhs_value([%s])[", type_name);
 
 310       rule->action_props.is_value_used = true;
 
 314       long int num = strtol (cp, NULL, 10);
 
 316       if (1 - INT_MAX + effective_rule_length <= num
 
 317           && num <= effective_rule_length)
 
 320           if (max_left_semantic_context < 1 - n)
 
 321             max_left_semantic_context = 1 - n;
 
 322           if (!type_name && 0 < n)
 
 324               symbol_list_n_type_name_get (effective_rule, dollar_loc, n);
 
 327               if (union_seen | tag_seen)
 
 328                 complain_at (dollar_loc, _("$%d of `%s' has no declared type"),
 
 329                              n, effective_rule->content.sym->tag);
 
 331                 untyped_var_seen = true;
 
 335           obstack_fgrow3 (&obstack_for_string,
 
 336                           "]b4_rhs_value(%d, %d, [%s])[",
 
 337                           effective_rule_length, n, type_name);
 
 339             symbol_list_n_get (effective_rule, n)->action_props.is_value_used =
 
 343         complain_at (dollar_loc, _("integer out of range: %s"), quote (text));
 
 348 /*------------------------------------------------------.
 
 349 | TEXT is a location token (i.e., a `@...').  Output to |
 
 350 | OBSTACK_FOR_STRING a reference to this location.      |
 
 351 `------------------------------------------------------*/
 
 354 handle_action_at (symbol_list *rule, char *text, location at_loc)
 
 357   int effective_rule_length =
 
 358     (rule->midrule_parent_rule
 
 359      ? rule->midrule_parent_rhs_index - 1
 
 360      : symbol_list_length (rule->next));
 
 362   locations_flag = true;
 
 365     obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
 
 368       long int num = strtol (cp, NULL, 10);
 
 370       if (1 - INT_MAX + effective_rule_length <= num
 
 371           && num <= effective_rule_length)
 
 374           obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
 
 375                           effective_rule_length, n);
 
 378         complain_at (at_loc, _("integer out of range: %s"), quote (text));
 
 383 /*-------------------------.
 
 384 | Initialize the scanner.  |
 
 385 `-------------------------*/
 
 387 /* Translate the dollars and ats in \a self, in the context \a sc_context
 
 388    (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL).  */
 
 391 translate_action (code_props *self, int sc_context)
 
 394   static bool initialized = false;
 
 397       obstack_init (&obstack_for_string);
 
 402   loc->start = loc->end = self->location.start;
 
 403   yy_switch_to_buffer (yy_scan_string (self->code));
 
 404   res = code_lex (self, sc_context);
 
 405   yy_delete_buffer (YY_CURRENT_BUFFER);
 
 410 /*------------------------------------------------------------------------.
 
 411 | Implementation of the public interface as documented in "scan-code.h".  |
 
 412 `------------------------------------------------------------------------*/
 
 415 code_props_none_init (code_props *self)
 
 417   *self = code_props_none;
 
 420 code_props const code_props_none = CODE_PROPS_NONE_INIT;
 
 423 code_props_plain_init (code_props *self, char const *code, location code_loc)
 
 425   self->kind = CODE_PROPS_PLAIN;
 
 427   self->location = code_loc;
 
 428   self->is_value_used = false;
 
 433 code_props_symbol_action_init (code_props *self, char const *code,
 
 436   self->kind = CODE_PROPS_SYMBOL_ACTION;
 
 438   self->location = code_loc;
 
 439   self->is_value_used = false;
 
 444 code_props_rule_action_init (code_props *self, char const *code,
 
 445                              location code_loc, symbol_list *rule)
 
 447   self->kind = CODE_PROPS_RULE_ACTION;
 
 449   self->location = code_loc;
 
 450   self->is_value_used = false;
 
 455 code_props_translate_code (code_props *self)
 
 459       case CODE_PROPS_NONE:
 
 461       case CODE_PROPS_PLAIN:
 
 462         self->code = translate_action (self, INITIAL);
 
 464       case CODE_PROPS_SYMBOL_ACTION:
 
 465         self->code = translate_action (self, SC_SYMBOL_ACTION);
 
 467       case CODE_PROPS_RULE_ACTION:
 
 468         self->code = translate_action (self, SC_RULE_ACTION);
 
 474 code_scanner_last_string_free (void)
 
 480 code_scanner_free (void)
 
 482   obstack_free (&obstack_for_string, 0);
 
 483   /* Reclaim Flex's buffers.  */