]> git.saurik.com Git - bison.git/blobdiff - src/scan-gram.l
* src/main.c (main): Free `infile'.
[bison.git] / src / scan-gram.l
index e86206467765fc7f2c171788bcf9e1fa6354ec69..9670687305f20b31adbd8dea2dc6e5caddb01638 100644 (file)
@@ -163,7 +163,6 @@ scanner_last_string_free (void)
 }
 
 
-static int braces_level = 0;
 static int percent_percent_count = 0;
 
 /* Within well-formed rules, RULE_LENGTH is the number of values in
@@ -178,6 +177,7 @@ static void handle_dollar (braced_code_t code_kind,
                           char *cp, location_t location);
 static void handle_at (braced_code_t code_kind,
                       char *cp, location_t location);
+static void handle_syncline (char *args, location_t *location);
 static int convert_ucn_to_byte (char const *hex_text);
 
 %}
@@ -202,6 +202,8 @@ splice       (\\[ \f\t\v]*\n)*
 
 %%
 %{
+  int braces_level IF_LINT (= 0);
+
   /* At each yylex invocation, mark the current position as the
      start of the next token.  */
   YY_STEP;
@@ -253,6 +255,8 @@ splice       (\\[ \f\t\v]*\n)*
     YY_STEP;
   }
 
+  ^"#line "{int}" \""[^\"]*"\"\n"   handle_syncline (yytext + strlen ("#line "), yylloc); YY_STEP;
+
   "="                     return EQUAL;
   ":"                     rule_length = 0; return COLON;
   "|"                     rule_length = 0; return PIPE;
@@ -273,7 +277,7 @@ splice       (\\[ \f\t\v]*\n)*
     num = strtoul (yytext, 0, 10);
     if (INT_MAX < num || errno)
       {
-       complain_at (*yylloc, _("invalid value: %s"), quote (yytext));
+       complain_at (*yylloc, _("integer out of range: %s"), quote (yytext));
        num = INT_MAX;
       }
     yylval->integer = num;
@@ -294,7 +298,7 @@ splice       (\\[ \f\t\v]*\n)*
   "%{"        yy_push_state (SC_PROLOGUE);
 
   /* Code in between braces.  */
-  "{"         YY_OBS_GROW; ++braces_level; yy_push_state (SC_BRACED_CODE);
+  "{"         YY_OBS_GROW; braces_level = 0; yy_push_state (SC_BRACED_CODE);
 
   /* A type. */
   "<"{tag}">" {
@@ -434,7 +438,7 @@ splice       (\\[ \f\t\v]*\n)*
   [^\'\\]+  YY_OBS_GROW;
 
   <<EOF>> {
-    complain_at (*yylloc, _("unexpected end of file in a character"));
+    complain_at (*yylloc, _("unexpected end of file in a character literal"));
     assert (yy_top_state () == INITIAL);
     YY_OBS_FINISH;
     yylval->string = last_string;
@@ -454,7 +458,8 @@ splice       (\\[ \f\t\v]*\n)*
     unsigned long c = strtoul (yytext + 1, 0, 8);
     if (UCHAR_MAX < c)
       {
-       complain_at (*yylloc, _("invalid escape: %s"), quote (yytext));
+       complain_at (*yylloc, _("invalid escape sequence: %s"),
+                    quote (yytext));
        YY_STEP;
       }
     else
@@ -467,7 +472,8 @@ splice       (\\[ \f\t\v]*\n)*
     c = strtoul (yytext + 2, 0, 16);
     if (UCHAR_MAX < c || errno)
       {
-       complain_at (*yylloc, _("invalid escape: %s"), quote (yytext));
+       complain_at (*yylloc, _("invalid escape sequence: %s"),
+                    quote (yytext));
        YY_STEP;
       }
     else
@@ -486,14 +492,16 @@ splice     (\\[ \f\t\v]*\n)*
     int c = convert_ucn_to_byte (yytext);
     if (c < 0)
       {
-       complain_at (*yylloc, _("invalid escape: %s"), quote (yytext));
+       complain_at (*yylloc, _("invalid escape sequence: %s"),
+                    quote (yytext));
        YY_STEP;
       }
     else
       obstack_1grow (&string_obstack, c);
   }
   \\(.|\n)     {
-    complain_at (*yylloc, _("unrecognized escape: %s"), quote (yytext));
+    complain_at (*yylloc, _("unrecognized escape sequence: %s"),
+                quote (yytext));
     YY_OBS_GROW;
   }
   /* FLex wants this rule, in case of a `\<<EOF>>'. */
@@ -521,7 +529,7 @@ splice       (\\[ \f\t\v]*\n)*
   \\                   YY_OBS_GROW;
 
   <<EOF>> {
-    complain_at (*yylloc, _("unexpected end of file in a character"));
+    complain_at (*yylloc, _("unexpected end of file in a character literal"));
     assert (yy_top_state () != INITIAL);
     yy_pop_state ();
   }
@@ -583,9 +591,12 @@ splice      (\\[ \f\t\v]*\n)*
 
 <SC_BRACED_CODE>
 {
+  "{"|"<"{splice}"%"  YY_OBS_GROW; braces_level++;
+  "%"{splice}">"      YY_OBS_GROW; braces_level--;
   "}" {
     YY_OBS_GROW;
-    if (--braces_level == 0)
+    braces_level--;
+    if (braces_level < 0)
       {
        yy_pop_state ();
        YY_OBS_FINISH;
@@ -595,20 +606,17 @@ splice     (\\[ \f\t\v]*\n)*
       }
   }
 
-  "{"                  YY_OBS_GROW; braces_level++;
-
   "$"("<"{tag}">")?(-?[0-9]+|"$") { handle_dollar (current_braced_code,
                                                   yytext, *yylloc); }
   "@"(-?[0-9]+|"$")               { handle_at (current_braced_code,
                                               yytext, *yylloc); }
 
-  [^$@\[\]/\'\"\{\}]+  YY_OBS_GROW;
-
-  /* A stray $, or /, or etc. */
-  .             YY_OBS_GROW;
+  /* `"<"{splice}"<"' tokenizes `<<%' correctly (as `<<' `%') rather
+     than incorrrectly (as `<' `<%').  */
+  [^\"$%\'/<@\[\]\{\}]+|[$%/<@]|"<"{splice}"<"  YY_OBS_GROW;
 
   <<EOF>> {
-    complain_at (*yylloc, _("unexpected end of file in a braced code"));
+    complain_at (*yylloc, _("unexpected end of file in `{ ... }'"));
     yy_pop_state ();
     YY_OBS_FINISH;
     yylval->string = last_string;
@@ -635,7 +643,7 @@ splice       (\\[ \f\t\v]*\n)*
   "%"                YY_OBS_GROW;
 
   <<EOF>> {
-    complain_at (*yylloc, _("unexpected end of file in a prologue"));
+    complain_at (*yylloc, _("unexpected end of file in `%%{ ... %%}'"));
     yy_pop_state ();
     YY_OBS_FINISH;
     yylval->string = last_string;
@@ -722,7 +730,7 @@ handle_action_dollar (char *text, location_t location)
                          rule_length, n, type_name);
        }
       else
-       complain_at (location, _("invalid value: %s"), quote (text));
+       complain_at (location, _("integer out of range: %s"), quote (text));
     }
 }
 
@@ -794,7 +802,7 @@ handle_action_at (char *text, location_t location)
                          rule_length, n);
        }
       else
-       complain_at (location, _("invalid value: %s"), quote (text));
+       complain_at (location, _("integer out of range: %s"), quote (text));
     }
 }
 
@@ -894,6 +902,24 @@ convert_ucn_to_byte (char const *ucn)
 }
 
 
+/*----------------------------------------------------------------.
+| Handle `#line INT "FILE"'.  ARGS has already skipped `#line '.  |
+`----------------------------------------------------------------*/
+
+static void
+handle_syncline (char *args, location_t *location)
+{
+  int lineno = strtol (args, &args, 10);
+  const char *file = NULL;
+  file = strchr (args, '"') + 1;
+  *strchr (file, '"') = 0;
+  /* FIXME: Leaking...  Can't free, as some locations are still
+     pointing to the old file name.  */
+  infile = xstrdup (file);
+  location->file = infile;
+  location->last_line = lineno;
+}
+
 /*-------------------------.
 | Initialize the scanner.  |
 `-------------------------*/