]> git.saurik.com Git - bison.git/blobdiff - src/scan-gram.l
* NEWS: Bison now warns if it finds a stray `$' or `@' in an action.
[bison.git] / src / scan-gram.l
index 849b72e15fece6fd555cbc5a261b7667c002699a..3c7d37c484d5932102804351b097cce301058175 100644 (file)
@@ -1,6 +1,6 @@
 /* Bison Grammar Scanner                             -*- C -*-
 
-   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307  USA
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301  USA
 */
 
 %option debug nodefault nounput noyywrap never-interactive
 %option prefix="gram_" outfile="lex.yy.c"
 
 %{
+/* Work around a bug in flex 2.5.31.  See Debian bug 333231
+   <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>.  */
+#undef gram_wrap
+#define gram_wrap() 1
+
 #include "system.h"
 
 #include <mbswidth.h>
@@ -34,6 +39,7 @@
 #include "files.h"
 #include "getargs.h"
 #include "gram.h"
+#include "quotearg.h"
 #include "reader.h"
 #include "uniqstr.h"
 
     }                                                  \
   while (0)
 
+/* Pacify "gcc -Wmissing-prototypes" when flex 2.5.31 is used.  */
+int gram_get_lineno (void);
+FILE *gram_get_in (void);
+FILE *gram_get_out (void);
+int gram_get_leng (void);
+char *gram_get_text (void);
+void gram_set_lineno (int);
+void gram_set_in (FILE *);
+void gram_set_out (FILE *);
+int gram_get_debug (void);
+void gram_set_debug (int);
+int gram_lex_destroy (void);
+
 /* Location of scanner cursor.  */
 boundary scanner_cursor;
 
@@ -104,6 +123,7 @@ static void handle_syncline (char *args);
 static unsigned long int scan_integer (char const *p, int base, location loc);
 static int convert_ucn_to_byte (char const *hex_text);
 static void unexpected_eof (boundary, char const *);
+static void unexpected_newline (boundary, char const *);
 
 %}
 %x SC_COMMENT SC_LINE_COMMENT SC_YACC_COMMENT
@@ -157,10 +177,9 @@ splice      (\\[ \f\t\v]*\n)*
 
 <INITIAL,SC_AFTER_IDENTIFIER,SC_PRE_CODE>
 {
-  [ \f\n\t\v]  ;
+  /* Comments and white space.  */
   ","         warn_at (*loc, _("stray `,' treated as white space"));
-
-  /* Comments. */
+  [ \f\n\t\v]  |
   "//".*       ;
   "/*" {
     token_start = loc->start;
@@ -190,6 +209,7 @@ splice       (\\[ \f\t\v]*\n)*
   "%dprec"               return PERCENT_DPREC;
   "%error"[-_]"verbose"   return PERCENT_ERROR_VERBOSE;
   "%expect"               return PERCENT_EXPECT;
+  "%expect"[-_]"rr"      return PERCENT_EXPECT_RR;
   "%file-prefix"          return PERCENT_FILE_PREFIX;
   "%fixed"[-_]"output"[-_]"files"   return PERCENT_YACC;
   "%initial-action"       token_type = PERCENT_INITIAL_ACTION; BEGIN SC_PRE_CODE;
@@ -209,6 +229,7 @@ splice       (\\[ \f\t\v]*\n)*
   "%prec"                 rule_length--; return PERCENT_PREC;
   "%printer"              token_type = PERCENT_PRINTER; BEGIN SC_PRE_CODE;
   "%pure"[-_]"parser"     return PERCENT_PURE_PARSER;
+  "%require"              return PERCENT_REQUIRE;
   "%right"                return PERCENT_RIGHT;
   "%skeleton"             return PERCENT_SKELETON;
   "%start"                return PERCENT_START;
@@ -248,7 +269,7 @@ splice       (\\[ \f\t\v]*\n)*
   "'"        STRING_GROW; token_start = loc->start; BEGIN SC_ESCAPED_CHARACTER;
 
   /* Strings. */
-  "\""       STRING_GROW; token_start = loc->start; BEGIN SC_ESCAPED_STRING;
+  "\""       token_start = loc->start; BEGIN SC_ESCAPED_STRING;
 
   /* Prologue. */
   "%{"        code_start = loc->start; BEGIN SC_PROLOGUE;
@@ -351,15 +372,14 @@ splice     (\\[ \f\t\v]*\n)*
 }
 
 
-  /*----------------------------------------------------------------.
-  | Scanning a C string, including its escapes.  The initial `"' is |
-  | already eaten.                                                  |
-  `----------------------------------------------------------------*/
+  /*------------------------------------------------.
+  | Scanning a Bison string, including its escapes. |
+  | The initial quote is already eaten.             |
+  `------------------------------------------------*/
 
 <SC_ESCAPED_STRING>
 {
   "\"" {
-    STRING_GROW;
     STRING_FINISH;
     loc->start = token_start;
     val->chars = last_string;
@@ -367,16 +387,14 @@ splice     (\\[ \f\t\v]*\n)*
     BEGIN INITIAL;
     return STRING;
   }
-
-  \0       complain_at (*loc, _("invalid null character"));
-  .|\n     STRING_GROW;
-  <<EOF>>   unexpected_eof (token_start, "\""); BEGIN INITIAL;
+  \n           unexpected_newline (token_start, "\""); BEGIN INITIAL;
+  <<EOF>>      unexpected_eof (token_start, "\"");     BEGIN INITIAL;
 }
 
-  /*---------------------------------------------------------------.
-  | Scanning a C character, decoding its escapes.  The initial "'" |
-  | is already eaten.                                              |
-  `---------------------------------------------------------------*/
+  /*----------------------------------------------------------.
+  | Scanning a Bison character literal, decoding its escapes. |
+  | The initial quote is already eaten.                              |
+  `----------------------------------------------------------*/
 
 <SC_ESCAPED_CHARACTER>
 {
@@ -385,7 +403,9 @@ splice       (\\[ \f\t\v]*\n)*
     STRING_GROW;
     STRING_FINISH;
     loc->start = token_start;
-    val->symbol = symbol_get (last_string, *loc);
+    val->symbol = symbol_get (quotearg_style (escape_quoting_style,
+                                             last_string),
+                             *loc);
     symbol_class_set (val->symbol, token_sym, *loc);
     last_string_1 = last_string[1];
     symbol_user_token_number_set (val->symbol, last_string_1, *loc);
@@ -394,10 +414,13 @@ splice     (\\[ \f\t\v]*\n)*
     BEGIN INITIAL;
     return ID;
   }
+  \n           unexpected_newline (token_start, "'");  BEGIN INITIAL;
+  <<EOF>>      unexpected_eof (token_start, "'");      BEGIN INITIAL;
+}
 
+<SC_ESCAPED_CHARACTER,SC_ESCAPED_STRING>
+{
   \0       complain_at (*loc, _("invalid null character"));
-  .|\n     STRING_GROW;
-  <<EOF>>   unexpected_eof (token_start, "'"); BEGIN INITIAL;
 }
 
 
@@ -411,7 +434,7 @@ splice       (\\[ \f\t\v]*\n)*
     unsigned long int c = strtoul (yytext + 1, 0, 8);
     if (UCHAR_MAX < c)
       complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
-    else if (! c) 
+    else if (! c)
       complain_at (*loc, _("invalid null character: %s"), quote (yytext));
     else
       obstack_1grow (&obstack_for_string, c);
@@ -455,33 +478,27 @@ splice     (\\[ \f\t\v]*\n)*
   }
 }
 
+  /*--------------------------------------------.
+  | Scanning user-code characters and strings.  |
+  `--------------------------------------------*/
 
-  /*----------------------------------------------------------.
-  | Scanning a C character without decoding its escapes.  The |
-  | initial "'" is already eaten.                             |
-  `----------------------------------------------------------*/
+<SC_CHARACTER,SC_STRING>
+{
+  {splice}|\\{splice}[^\n$@\[\]]       STRING_GROW;
+}
 
 <SC_CHARACTER>
 {
-  "'"                  STRING_GROW; BEGIN context_state;
-  \\{splice}[^$@\[\]]  STRING_GROW;
-  <<EOF>>              unexpected_eof (token_start, "'"); BEGIN context_state;
+  "'"          STRING_GROW; BEGIN context_state;
+  \n           unexpected_newline (token_start, "'"); BEGIN context_state;
+  <<EOF>>      unexpected_eof (token_start, "'"); BEGIN context_state;
 }
 
-
-  /*----------------------------------------------------------------.
-  | Scanning a C string, without decoding its escapes.  The initial |
-  | `"' is already eaten.                                           |
-  `----------------------------------------------------------------*/
-
 <SC_STRING>
 {
-  "\""                 STRING_GROW; BEGIN context_state;
-  \\{splice}[^$@\[\]]  STRING_GROW;
-  <<EOF>> {
-    unexpected_eof (token_start, "\"");
-    BEGIN context_state;
-  }
+  "\""         STRING_GROW; BEGIN context_state;
+  \n           unexpected_newline (token_start, "\""); BEGIN context_state;
+  <<EOF>>      unexpected_eof (token_start, "\""); BEGIN context_state;
 }
 
 
@@ -538,7 +555,7 @@ splice       (\\[ \f\t\v]*\n)*
       }
     else
       {
-       complain_at (*loc, _("missing `{' in `%s'"),
+       complain_at (*loc, _("missing `{' in %s"),
                     token_name (token_type));
        obstack_sgrow (&obstack_for_string, "{}");
        STRING_FINISH;
@@ -601,6 +618,15 @@ splice      (\\[ \f\t\v]*\n)*
   "$"("<"{tag}">")?(-?[0-9]+|"$")  handle_dollar (token_type, yytext, *loc);
   "@"(-?[0-9]+|"$")               handle_at (token_type, yytext, *loc);
 
+  "$"  {
+    warn_at (*loc, _("stray `$'"));
+    obstack_sgrow (&obstack_for_string, "$][");
+  }
+  "@"  {
+    warn_at (*loc, _("stray `@'"));
+    obstack_sgrow (&obstack_for_string, "@@");
+  }
+
   <<EOF>>  unexpected_eof (code_start, "}"); BEGIN INITIAL;
 }
 
@@ -640,10 +666,9 @@ splice      (\\[ \f\t\v]*\n)*
 }
 
 
-  /*----------------------------------------------------------------.
-  | By default, grow the string obstack with the input, escaping M4 |
-  | quoting characters.                                                    |
-  `----------------------------------------------------------------*/
+  /*-----------------------------------------.
+  | Escape M4 quoting characters in C code.  |
+  `-----------------------------------------*/
 
 <SC_COMMENT,SC_LINE_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
 {
@@ -651,10 +676,16 @@ splice     (\\[ \f\t\v]*\n)*
   \@   obstack_sgrow (&obstack_for_string, "@@");
   \[   obstack_sgrow (&obstack_for_string, "@{");
   \]   obstack_sgrow (&obstack_for_string, "@}");
-  .|\n  STRING_GROW;
 }
 
 
+  /*-----------------------------------------------------.
+  | By default, grow the string obstack with the input.  |
+  `-----------------------------------------------------*/
+
+<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE,SC_STRING,SC_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>.     |
+<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>\n  STRING_GROW;
+
 %%
 
 /* Keeps track of the maximum number of semantic values to the left of
@@ -804,7 +835,7 @@ handle_action_dollar (char *text, location loc)
          if (!type_name)
            type_name = "";
          obstack_fgrow3 (&obstack_for_string,
-                         "]b4_rhs_value([%d], [%d], [%s])[",
+                         "]b4_rhs_value(%d, %d, [%s])[",
                          rule_length, n, type_name);
        }
       else
@@ -873,7 +904,7 @@ handle_action_at (char *text, location loc)
       if (INT_MIN <= num && num <= rule_length && ! get_errno ())
        {
          int n = num;
-         obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location([%d], [%d])[",
+         obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
                          rule_length, n);
        }
       else
@@ -1002,12 +1033,28 @@ handle_syncline (char *args)
   const char *file = NULL;
   file = strchr (args, '"') + 1;
   *strchr (file, '"') = 0;
-  scanner_cursor.file = current_file = xstrdup (file);
+  scanner_cursor.file = current_file = uniqstr_new (file);
   scanner_cursor.line = lineno;
   scanner_cursor.column = 1;
 }
 
 
+/*----------------------------------------------------------------.
+| For a token or comment starting at START, report message MSGID, |
+| which should say that an end marker was found before           |
+| the expected TOKEN_END.                                        |
+`----------------------------------------------------------------*/
+
+static void
+unexpected_end (boundary start, char const *msgid, char const *token_end)
+{
+  location loc;
+  loc.start = start;
+  loc.end = scanner_cursor;
+  complain_at (loc, _(msgid), token_end);
+}
+
+
 /*------------------------------------------------------------------------.
 | Report an unexpected EOF in a token or comment starting at START.       |
 | An end of file was encountered and the expected TOKEN_END was missing.  |
@@ -1016,10 +1063,18 @@ handle_syncline (char *args)
 static void
 unexpected_eof (boundary start, char const *token_end)
 {
-  location loc;
-  loc.start = start;
-  loc.end = scanner_cursor;
-  complain_at (loc, _("missing `%s' at end of file"), token_end);
+  unexpected_end (start, N_("missing `%s' at end of file"), token_end);
+}
+
+
+/*----------------------------------------.
+| Likewise, but for unexpected newlines.  |
+`----------------------------------------*/
+
+static void
+unexpected_newline (boundary start, char const *token_end)
+{
+  unexpected_end (start, N_("missing `%s' at end of line"), token_end);
 }