]> git.saurik.com Git - bison.git/blobdiff - src/scan-gram.l
tests: syntax-check
[bison.git] / src / scan-gram.l
index 55ca3ac64572e2534e4bb7d1c3da7b1a03c2e770..ad061cc6f86159ba93da4023e60fa326111f8b86 100644 (file)
@@ -1,7 +1,6 @@
 /* Bison Grammar Scanner                             -*- C -*-
 
 /* Bison Grammar Scanner                             -*- C -*-
 
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free
-   Software Foundation, Inc.
+   Copyright (C) 2002-2012 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
 
    This file is part of Bison, the GNU Compiler Compiler.
 
@@ -37,6 +36,7 @@
 #include "reader.h"
 #include "uniqstr.h"
 
 #include "reader.h"
 #include "uniqstr.h"
 
+#include <c-ctype.h>
 #include <mbswidth.h>
 #include <quote.h>
 
 #include <mbswidth.h>
 #include <quote.h>
 
@@ -88,11 +88,11 @@ static void unexpected_newline (boundary, char const *);
  /* Strings and characters in directives/rules. */
 %x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
  /* A identifier was just read in directives/rules.  Special state
  /* Strings and characters in directives/rules. */
 %x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
  /* A identifier was just read in directives/rules.  Special state
-    to capture the sequence `identifier :'. */
+    to capture the sequence 'identifier :'. */
 %x SC_AFTER_IDENTIFIER
 
  /* Three types of user code:
 %x SC_AFTER_IDENTIFIER
 
  /* Three types of user code:
-    - prologue (code between `%{' `%}' in the first section, before %%);
+    - prologue (code between '%{' '%}' in the first section, before %%);
     - actions, printers, union, etc, (between braced in the middle section);
     - epilogue (everything after the second %%). */
 %x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE
     - actions, printers, union, etc, (between braced in the middle section);
     - epilogue (everything after the second %%). */
 %x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE
@@ -103,8 +103,8 @@ static void unexpected_newline (boundary, char const *);
  /* Bracketed identifiers support. */
 %x SC_BRACKETED_ID SC_RETURN_BRACKETED_ID
 
  /* Bracketed identifiers support. */
 %x SC_BRACKETED_ID SC_RETURN_BRACKETED_ID
 
-letter   [-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
-id       {letter}({letter}|[0-9])*
+letter   [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
+id       {letter}({letter}|[-0-9])*
 directive %{id}
 int      [0-9]+
 
 directive %{id}
 int      [0-9]+
 
@@ -120,13 +120,13 @@ splice     (\\[ \f\t\v]*\n)*
 %%
 %{
   /* Nesting level of the current code in braces.  */
 %%
 %{
   /* Nesting level of the current code in braces.  */
-  int braces_level IF_LINT (= 0);
+  int braces_level PACIFY_CC (= 0);
 
   /* Parent context state, when applicable.  */
 
   /* Parent context state, when applicable.  */
-  int context_state IF_LINT (= 0);
+  int context_state PACIFY_CC (= 0);
 
   /* Location of most recent identifier, when applicable.  */
 
   /* Location of most recent identifier, when applicable.  */
-  location id_loc IF_LINT (= empty_location);
+  location id_loc PACIFY_CC (= empty_location);
 
   /* Where containing code started, when applicable.  Its initial
      value is relevant only when yylex is invoked in the SC_EPILOGUE
 
   /* Where containing code started, when applicable.  Its initial
      value is relevant only when yylex is invoked in the SC_EPILOGUE
@@ -135,7 +135,7 @@ splice       (\\[ \f\t\v]*\n)*
 
   /* Where containing comment or string or character literal started,
      when applicable.  */
 
   /* Where containing comment or string or character literal started,
      when applicable.  */
-  boundary token_start IF_LINT (= scanner_cursor);
+  boundary token_start PACIFY_CC (= scanner_cursor);
 %}
 
 
 %}
 
 
@@ -146,7 +146,7 @@ splice       (\\[ \f\t\v]*\n)*
 <INITIAL,SC_AFTER_IDENTIFIER,SC_BRACKETED_ID,SC_RETURN_BRACKETED_ID>
 {
   /* Comments and white space.  */
 <INITIAL,SC_AFTER_IDENTIFIER,SC_BRACKETED_ID,SC_RETURN_BRACKETED_ID>
 {
   /* Comments and white space.  */
-  ","         warn_at (*loc, _("stray `,' treated as white space"));
+  ","          warn_at (*loc, _("stray ',' treated as white space"));
   [ \f\n\t\v]  |
   "//".*       ;
   "/*" {
   [ \f\n\t\v]  |
   "//".*       ;
   "/*" {
@@ -251,7 +251,7 @@ splice       (\\[ \f\t\v]*\n)*
   }
 
   /* Characters.  */
   }
 
   /* Characters.  */
-  "'"        STRING_GROW; token_start = loc->start; BEGIN SC_ESCAPED_CHARACTER;
+  "'"        token_start = loc->start; BEGIN SC_ESCAPED_CHARACTER;
 
   /* Strings. */
   "\""       token_start = loc->start; BEGIN SC_ESCAPED_STRING;
 
   /* Strings. */
   "\""       token_start = loc->start; BEGIN SC_ESCAPED_STRING;
@@ -291,7 +291,7 @@ splice       (\\[ \f\t\v]*\n)*
   }
 
   . {
   }
 
   . {
-    complain_at (*loc, _("invalid character: %s"), quote (yytext));
+    complain_at (*loc, _("invalid character: %s"), quote_mem (yytext, yyleng));
   }
 
   <<EOF>> {
   }
 
   <<EOF>> {
@@ -375,7 +375,7 @@ splice       (\\[ \f\t\v]*\n)*
   }
   . {
     complain_at (*loc, _("invalid character in bracketed name: %s"),
   }
   . {
     complain_at (*loc, _("invalid character in bracketed name: %s"),
-                quote (yytext));
+                quote_mem (yytext, yyleng));
   }
   <<EOF>> {
     BEGIN bracketed_id_context_state;
   }
   <<EOF>> {
     BEGIN bracketed_id_context_state;
@@ -397,7 +397,7 @@ splice       (\\[ \f\t\v]*\n)*
 
 
   /*---------------------------------------------------------------.
 
 
   /*---------------------------------------------------------------.
-  | Scanning a Yacc comment.  The initial `/ *' is already eaten.  |
+  | Scanning a Yacc comment.  The initial '/ *' is already eaten.  |
   `---------------------------------------------------------------*/
 
 <SC_YACC_COMMENT>
   `---------------------------------------------------------------*/
 
 <SC_YACC_COMMENT>
@@ -409,7 +409,7 @@ splice       (\\[ \f\t\v]*\n)*
 
 
   /*------------------------------------------------------------.
 
 
   /*------------------------------------------------------------.
-  | Scanning a C comment.  The initial `/ *' is already eaten.  |
+  | Scanning a C comment.  The initial '/ *' is already eaten.  |
   `------------------------------------------------------------*/
 
 <SC_COMMENT>
   `------------------------------------------------------------*/
 
 <SC_COMMENT>
@@ -420,7 +420,7 @@ splice       (\\[ \f\t\v]*\n)*
 
 
   /*--------------------------------------------------------------.
 
 
   /*--------------------------------------------------------------.
-  | Scanning a line comment.  The initial `//' is already eaten.  |
+  | Scanning a line comment.  The initial '//' is already eaten.  |
   `--------------------------------------------------------------*/
 
 <SC_LINE_COMMENT>
   `--------------------------------------------------------------*/
 
 <SC_LINE_COMMENT>
@@ -465,16 +465,18 @@ splice     (\\[ \f\t\v]*\n)*
 <SC_ESCAPED_CHARACTER>
 {
   "'"|"\n" {
 <SC_ESCAPED_CHARACTER>
 {
   "'"|"\n" {
-    STRING_GROW;
     STRING_FINISH;
     loc->start = token_start;
     STRING_FINISH;
     loc->start = token_start;
-    val->character = last_string[1];
+    val->character = last_string[0];
     {
       /* FIXME: Eventually, make these errors.  */
     {
       /* FIXME: Eventually, make these errors.  */
-      size_t length = strlen (last_string);
-      if (length < 3)
-        warn_at (*loc, _("empty character literal"));
-      else if (length > 3)
+      if (last_string[0] == '\0')
+        {
+          warn_at (*loc, _("empty character literal"));
+          /* '\0' seems dangerous even if we are about to complain.  */
+          val->character = '\'';
+        }
+      else if (last_string[1] != '\0')
         warn_at (*loc, _("extra characters in character literal"));
     }
     if (yytext[0] == '\n')
         warn_at (*loc, _("extra characters in character literal"));
     }
     if (yytext[0] == '\n')
@@ -486,17 +488,17 @@ splice     (\\[ \f\t\v]*\n)*
   <<EOF>> {
     STRING_FINISH;
     loc->start = token_start;
   <<EOF>> {
     STRING_FINISH;
     loc->start = token_start;
+    val->character = last_string[0];
     {
     {
-      size_t length = strlen (last_string);
       /* FIXME: Eventually, make these errors.  */
       /* FIXME: Eventually, make these errors.  */
-      if (length < 2)
-        warn_at (*loc, _("empty character literal"));
-      else if (length > 2)
+      if (last_string[0] == '\0')
+        {
+          warn_at (*loc, _("empty character literal"));
+          /* '\0' seems dangerous even if we are about to complain.  */
+          val->character = '\'';
+        }
+      else if (last_string[1] != '\0')
         warn_at (*loc, _("extra characters in character literal"));
         warn_at (*loc, _("extra characters in character literal"));
-      if (length > 1)
-        val->character = last_string[1];
-      else
-        val->character = last_string[0];
     }
     unexpected_eof (token_start, "'");
     STRING_FREE;
     }
     unexpected_eof (token_start, "'");
     STRING_FREE;
@@ -519,10 +521,9 @@ splice      (\\[ \f\t\v]*\n)*
 {
   \\[0-7]{1,3} {
     unsigned long int c = strtoul (yytext + 1, NULL, 8);
 {
   \\[0-7]{1,3} {
     unsigned long int c = strtoul (yytext + 1, NULL, 8);
-    if (UCHAR_MAX < c)
-      complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
-    else if (! c)
-      complain_at (*loc, _("invalid null character: %s"), quote (yytext));
+    if (!c || UCHAR_MAX < c)
+      complain_at (*loc, _("invalid number after \\-escape: %s"),
+                   yytext+1);
     else
       obstack_1grow (&obstack_for_string, c);
   }
     else
       obstack_1grow (&obstack_for_string, c);
   }
@@ -530,10 +531,9 @@ splice      (\\[ \f\t\v]*\n)*
   \\x[0-9abcdefABCDEF]+ {
     verify (UCHAR_MAX < ULONG_MAX);
     unsigned long int c = strtoul (yytext + 2, NULL, 16);
   \\x[0-9abcdefABCDEF]+ {
     verify (UCHAR_MAX < ULONG_MAX);
     unsigned long int c = strtoul (yytext + 2, NULL, 16);
-    if (UCHAR_MAX < c)
-      complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
-    else if (! c)
-      complain_at (*loc, _("invalid null character: %s"), quote (yytext));
+    if (!c || UCHAR_MAX < c)
+      complain_at (*loc, _("invalid number after \\-escape: %s"),
+                   yytext+1);
     else
       obstack_1grow (&obstack_for_string, c);
   }
     else
       obstack_1grow (&obstack_for_string, c);
   }
@@ -551,16 +551,20 @@ splice     (\\[ \f\t\v]*\n)*
 
   \\(u|U[0-9abcdefABCDEF]{4})[0-9abcdefABCDEF]{4} {
     int c = convert_ucn_to_byte (yytext);
 
   \\(u|U[0-9abcdefABCDEF]{4})[0-9abcdefABCDEF]{4} {
     int c = convert_ucn_to_byte (yytext);
-    if (c < 0)
-      complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
-    else if (! c)
-      complain_at (*loc, _("invalid null character: %s"), quote (yytext));
+    if (c <= 0)
+      complain_at (*loc, _("invalid number after \\-escape: %s"),
+                   yytext+1);
     else
       obstack_1grow (&obstack_for_string, c);
   }
   \\(.|\n)     {
     else
       obstack_1grow (&obstack_for_string, c);
   }
   \\(.|\n)     {
-    complain_at (*loc, _("unrecognized escape sequence: %s"), quote (yytext));
-    STRING_GROW;
+    char const *p = yytext + 1;
+    /* Quote only if escaping won't make the character visible.  */
+    if (c_isspace ((unsigned char) *p) && c_isprint ((unsigned char) *p))
+      p = quote (p);
+    else
+      p = quotearg_style_mem (escape_quoting_style, p, 1);
+    complain_at (*loc, _("invalid character after \\-escape: %s"), p);
   }
 }
 
   }
 }
 
@@ -644,8 +648,8 @@ splice       (\\[ \f\t\v]*\n)*
       }
   }
 
       }
   }
 
-  /* Tokenize `<<%' correctly (as `<<' `%') rather than incorrrectly
-     (as `<' `<%').  */
+  /* Tokenize '<<%' correctly (as '<<' '%') rather than incorrrectly
+     (as '<' '<%').  */
   "<"{splice}"<"  STRING_GROW;
 
   <<EOF>> {
   "<"{splice}"<"  STRING_GROW;
 
   <<EOF>> {
@@ -836,7 +840,7 @@ convert_ucn_to_byte (char const *ucn)
 
 
 /*----------------------------------------------------------------.
 
 
 /*----------------------------------------------------------------.
-| Handle `#line INT "FILE"'.  ARGS has already skipped `#line '.  |
+| Handle '#line INT "FILE"'.  ARGS has already skipped '#line '.  |
 `----------------------------------------------------------------*/
 
 static void
 `----------------------------------------------------------------*/
 
 static void
@@ -844,8 +848,8 @@ handle_syncline (char *args, location loc)
 {
   char *after_num;
   unsigned long int lineno = strtoul (args, &after_num, 10);
 {
   char *after_num;
   unsigned long int lineno = strtoul (args, &after_num, 10);
-  char *file = strchr (after_num, '"') + 1;
-  *strchr (file, '"') = '\0';
+  char *file = mbschr (after_num, '"') + 1;
+  *mbschr (file, '"') = '\0';
   if (INT_MAX <= lineno)
     {
       warn_at (loc, _("line number overflow"));
   if (INT_MAX <= lineno)
     {
       warn_at (loc, _("line number overflow"));
@@ -868,6 +872,10 @@ unexpected_end (boundary start, char const *msgid, char const *token_end)
   location loc;
   loc.start = start;
   loc.end = scanner_cursor;
   location loc;
   loc.start = start;
   loc.end = scanner_cursor;
+  token_end = quote (token_end);
+  // Instead of '\'', display "'".
+  if (!strcmp (token_end, "'\\''"))
+    token_end = "\"'\"";
   complain_at (loc, _(msgid), token_end);
 }
 
   complain_at (loc, _(msgid), token_end);
 }
 
@@ -880,7 +888,7 @@ unexpected_end (boundary start, char const *msgid, char const *token_end)
 static void
 unexpected_eof (boundary start, char const *token_end)
 {
 static void
 unexpected_eof (boundary start, char const *token_end)
 {
-  unexpected_end (start, N_("missing `%s' at end of file"), token_end);
+  unexpected_end (start, N_("missing %s at end of file"), token_end);
 }
 
 
 }
 
 
@@ -891,7 +899,7 @@ unexpected_eof (boundary start, char const *token_end)
 static void
 unexpected_newline (boundary start, char const *token_end)
 {
 static void
 unexpected_newline (boundary start, char const *token_end)
 {
-  unexpected_end (start, N_("missing `%s' at end of line"), token_end);
+  unexpected_end (start, N_("missing %s at end of line"), token_end);
 }
 
 
 }