]> git.saurik.com Git - bison.git/blobdiff - src/scan-gram.l
diagnostics: avoid useless caret stuttering
[bison.git] / src / scan-gram.l
index 98124556872b6251aa7ce8a6d44feb6639744520..2ed6d2fd654fec62cfdbeb676a91115c52a714be 100644 (file)
@@ -1,6 +1,6 @@
 /* Bison Grammar Scanner                             -*- C -*-
 
-   Copyright (C) 2002-2012 Free Software Foundation, Inc.
+   Copyright (C) 2002-2013 Free Software Foundation, Inc.
 
    This file is part of Bison, the GNU Compiler Compiler.
 
@@ -77,9 +77,7 @@ static size_t no_cr_read (FILE *, char *, size_t);
 #define DEPRECATED(Msg)                                         \
   do {                                                          \
     size_t i;                                                   \
-    complain (loc, Wdeprecated,                                 \
-              _("deprecated directive: %s, use %s"),            \
-              quote (yytext), quote_n (1, Msg));                \
+    deprecated_directive (loc, yytext, Msg);                    \
     scanner_cursor.column -= mbsnwidth (Msg, strlen (Msg), 0);  \
     for (i = strlen (Msg); i != 0; --i)                         \
       unput (Msg[i - 1]);                                       \
@@ -131,8 +129,8 @@ static void unexpected_newline (boundary, char const *);
 %x SC_BRACKETED_ID SC_RETURN_BRACKETED_ID
 
 letter    [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
+notletter [^.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]{-}[%\{]
 id        {letter}({letter}|[-0-9])*
-directive %{id}
 int       [0-9]+
 
 /* POSIX says that a tag must be both an id and a C union member, but
@@ -184,7 +182,7 @@ eqopt    ([[:space:]]*=)?
      complain (loc, Wother, _("stray ',' treated as white space"));
   }
   [ \f\n\t\v]  |
-  "//".*       ;
+  "//".*       continue;
   "/*" {
     token_start = loc->start;
     context_state = YY_START;
@@ -193,7 +191,7 @@ eqopt    ([[:space:]]*=)?
 
   /* #line directives are not documented, and may be withdrawn or
      modified in future versions of Bison.  */
-  ^"#line "{int}" \"".*"\"\n" {
+  ^"#line "{int}(" \"".*"\"")?"\n" {
     handle_syncline (yytext + sizeof "#line " - 1, *loc);
   }
 }
@@ -269,7 +267,7 @@ eqopt    ([[:space:]]*=)?
   "%pure"[-_]"parser"               DEPRECATED("%pure-parser");
   "%token"[-_]"table"               DEPRECATED("%token-table");
 
-  {directive} {
+  "%"{id}|"%"{notletter}([[:graph:]])+ {
     complain (loc, complaint, _("invalid directive: %s"), quote (yytext));
   }
 
@@ -353,8 +351,9 @@ eqopt    ([[:space:]]*=)?
     BEGIN SC_BRACKETED_ID;
   }
 
-  . {
-    complain (loc, complaint, _("invalid character: %s"),
+  [^\[%A-Za-z0-9_<>{}\"\'*;|=/, \f\n\t\v]+|. {
+    complain (loc, complaint, "%s: %s",
+              ngettext ("invalid character", "invalid characters", yyleng),
               quote_mem (yytext, yyleng));
   }
 
@@ -449,10 +448,14 @@ eqopt    ([[:space:]]*=)?
     else
       complain (loc, complaint, _("an identifier expected"));
   }
-  . {
-    complain (loc, complaint, _("invalid character in bracketed name: %s"),
+
+  [^\].A-Za-z0-9_/ \f\n\t\v]+|. {
+    complain (loc, complaint, "%s: %s",
+              ngettext ("invalid character in bracketed name",
+                        "invalid characters in bracketed name", yyleng),
               quote_mem (yytext, yyleng));
   }
+
   <<EOF>> {
     BEGIN bracketed_id_context_state;
     unexpected_eof (bracketed_id_start, "]");
@@ -479,7 +482,7 @@ eqopt    ([[:space:]]*=)?
 <SC_YACC_COMMENT>
 {
   "*/"     BEGIN context_state;
-  .|\n     ;
+  .|\n     continue;
   <<EOF>>  unexpected_eof (token_start, "*/"); BEGIN context_state;
 }
 
@@ -514,23 +517,15 @@ eqopt    ([[:space:]]*=)?
 
 <SC_ESCAPED_STRING>
 {
-  "\""|"\n" {
-    if (yytext[0] == '\n')
-      unexpected_newline (token_start, "\"");
-    STRING_FINISH;
-    loc->start = token_start;
-    val->chars = last_string;
-    BEGIN INITIAL;
-    return STRING;
-  }
-  <<EOF>> {
-    unexpected_eof (token_start, "\"");
+  "\"" {
     STRING_FINISH;
     loc->start = token_start;
     val->chars = last_string;
     BEGIN INITIAL;
     return STRING;
   }
+  <<EOF>>   unexpected_eof (token_start, "\"");
+  "\n"      unexpected_newline (token_start, "\"");
 }
 
   /*----------------------------------------------------------.
@@ -540,49 +535,27 @@ eqopt    ([[:space:]]*=)?
 
 <SC_ESCAPED_CHARACTER>
 {
-  "'"|"\n" {
-    STRING_FINISH;
-    loc->start = token_start;
-    val->character = last_string[0];
-    {
-      /* FIXME: Eventually, make these errors.  */
-      if (last_string[0] == '\0')
-        {
-          complain (loc, Wother, _("empty character literal"));
-          /* '\0' seems dangerous even if we are about to complain.  */
-          val->character = '\'';
-        }
-      else if (last_string[1] != '\0')
-        complain (loc, Wother,
-                  _("extra characters in character literal"));
-    }
-    if (yytext[0] == '\n')
-      unexpected_newline (token_start, "'");
-    STRING_FREE;
-    BEGIN INITIAL;
-    return CHAR;
-  }
-  <<EOF>> {
+  "'" {
     STRING_FINISH;
     loc->start = token_start;
     val->character = last_string[0];
+
+    /* FIXME: Eventually, make these errors.  */
+    if (last_string[0] == '\0')
     {
-      /* FIXME: Eventually, make these errors.  */
-      if (last_string[0] == '\0')
-        {
-          complain (loc, Wother, _("empty character literal"));
-          /* '\0' seems dangerous even if we are about to complain.  */
-          val->character = '\'';
-        }
-      else if (last_string[1] != '\0')
-        complain (loc, Wother,
-                  _("extra characters in character literal"));
+      complain (loc, Wother, _("empty character literal"));
+      /* '\0' seems dangerous even if we are about to complain.  */
+      val->character = '\'';
     }
-    unexpected_eof (token_start, "'");
+    else if (last_string[1] != '\0')
+      complain (loc, Wother,
+                _("extra characters in character literal"));
     STRING_FREE;
     BEGIN INITIAL;
     return CHAR;
   }
+  "\n"      unexpected_newline (token_start, "'");
+  <<EOF>>   unexpected_eof (token_start, "'");
 }
 
   /*-----------------------------------------------------------.
@@ -609,15 +582,7 @@ eqopt    ([[:space:]]*=)?
   [^<>]+ STRING_GROW;
   "<"+   STRING_GROW; nesting += yyleng;
 
-  <<EOF>> {
-    unexpected_eof (token_start, ">");
-    STRING_FINISH;
-    loc->start = token_start;
-    val->uniqstr = uniqstr_new (last_string);
-    STRING_FREE;
-    BEGIN INITIAL;
-    return TAG;
-  }
+  <<EOF>>   unexpected_eof (token_start, ">");
 }
 
   /*----------------------------.
@@ -688,15 +653,15 @@ eqopt    ([[:space:]]*=)?
 <SC_CHARACTER>
 {
   "'"           STRING_GROW; BEGIN context_state;
-  \n            unexpected_newline (token_start, "'"); BEGIN context_state;
-  <<EOF>>       unexpected_eof (token_start, "'"); BEGIN context_state;
+  \n            unexpected_newline (token_start, "'");
+  <<EOF>>       unexpected_eof (token_start, "'");
 }
 
 <SC_STRING>
 {
   "\""          STRING_GROW; BEGIN context_state;
-  \n            unexpected_newline (token_start, "\""); BEGIN context_state;
-  <<EOF>>       unexpected_eof (token_start, "\""); BEGIN context_state;
+  \n            unexpected_newline (token_start, "\"");
+  <<EOF>>       unexpected_eof (token_start, "\"");
 }
 
 
@@ -747,15 +712,7 @@ eqopt    ([[:space:]]*=)?
      (as '<' '<%').  */
   "<"{splice}"<"  STRING_GROW;
 
-  <<EOF>> {
-    int token = (YY_START == SC_BRACED_CODE) ? BRACED_CODE : BRACED_PREDICATE;
-    unexpected_eof (code_start, "}");
-    STRING_FINISH;
-    loc->start = code_start;
-    val->code = last_string;
-    BEGIN INITIAL;
-    return token;
-  }
+  <<EOF>>   unexpected_eof (code_start, "}");
 }
 
 <SC_BRACED_CODE>
@@ -806,14 +763,7 @@ eqopt    ([[:space:]]*=)?
     return PROLOGUE;
   }
 
-  <<EOF>> {
-    unexpected_eof (code_start, "%}");
-    STRING_FINISH;
-    loc->start = code_start;
-    val->chars = last_string;
-    BEGIN INITIAL;
-    return PROLOGUE;
-  }
+  <<EOF>>   unexpected_eof (code_start, "%}");
 }
 
 
@@ -969,31 +919,35 @@ convert_ucn_to_byte (char const *ucn)
 }
 
 
-/*----------------------------------------------------------------.
-| Handle '#line INT "FILE"'.  ARGS has already skipped '#line '.  |
-`----------------------------------------------------------------*/
+/*---------------------------------------------------------------------.
+| Handle '#line INT( "FILE")?\n'.  ARGS has already skipped '#line '.  |
+`---------------------------------------------------------------------*/
 
 static void
 handle_syncline (char *args, location loc)
 {
-  char *after_num;
-  unsigned long int lineno = strtoul (args, &after_num, 10);
-  char *file = strchr (after_num, '"') + 1;
-  *strchr (file, '"') = '\0';
+  char *file;
+  unsigned long int lineno = strtoul (args, &file, 10);
   if (INT_MAX <= lineno)
     {
       complain (&loc, Wother, _("line number overflow"));
       lineno = INT_MAX;
     }
-  current_file = uniqstr_new (file);
+
+  file = strchr (file, '"');
+  if (file)
+    {
+      *strchr (file + 1, '"') = '\0';
+      current_file = uniqstr_new (file + 1);
+    }
   boundary_set (&scanner_cursor, current_file, lineno, 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.                                         |
+| which should say that an end marker was found before the        |
+| expected TOKEN_END. Then, pretend that TOKEN_END was found.     |
 `----------------------------------------------------------------*/
 
 static void
@@ -1002,8 +956,17 @@ unexpected_end (boundary start, char const *msgid, char const *token_end)
   location loc;
   loc.start = start;
   loc.end = scanner_cursor;
+  size_t i = strlen (token_end);
+
+/* Adjust scanner cursor so that any later message does not count
+     the characters about to be inserted.  */
+  scanner_cursor.column -= i;
+
+  while (i != 0)
+    unput (token_end[--i]);
+
   token_end = quote (token_end);
-  // Instead of '\'', display "'".
+  /* Instead of '\'', display "'".  */
   if (STREQ (token_end, "'\\''"))
     token_end = "\"'\"";
   complain (&loc, complaint, _(msgid), token_end);
@@ -1013,6 +976,7 @@ unexpected_end (boundary start, char const *msgid, char const *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.  |
+| After reporting the problem, pretend that TOKEN_END was found.          |
 `------------------------------------------------------------------------*/
 
 static void