]> git.saurik.com Git - bison.git/commitdiff
Add comparison operators for C++ location classes. Discussed at
authorJoel E. Denny <jdenny@ces.clemson.edu>
Thu, 22 Jun 2006 19:46:05 +0000 (19:46 +0000)
committerJoel E. Denny <jdenny@ces.clemson.edu>
Thu, 22 Jun 2006 19:46:05 +0000 (19:46 +0000)
<http://lists.gnu.org/archive/html/bison-patches/2006-06/msg00092.html>.
* data/c++.m4 (b4_define_location_comparison): New boolean %define
declaration indicating whether filename_type has an operator==.  If
filename_type is `std::string', it defaults to `1', `0' otherwise.
* data/location.cc: Iff b4_define_location_comparison is `1', add
operator== and operator!= for class position and for class location.

Some minor fixes.
* src/scan-action.l: Remove unused file.
* src/symtab.c (symbol_printer_set): Use printer_location not
destructor_location.
* src/symtab.h (struct symbol): Replace incorrect source comment for
printer members.
* tests/input.at (Incompatible Aliases): Update output with correct
printer location.

ChangeLog
data/c++.m4
data/location.cc
src/scan-action.l [deleted file]
src/symtab.c
src/symtab.h
tests/input.at

index 43a14168da1340742442bdadfedfc503181c5bde..4c12eeffeaa0fb56825157c39e1907d727fba3ef 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2006-06-22  Joel E. Denny  <jdenny@ces.clemson.edu>
+
+       Add comparison operators for C++ location classes.  Discussed at
+       <http://lists.gnu.org/archive/html/bison-patches/2006-06/msg00092.html>.
+       * data/c++.m4 (b4_define_location_comparison): New boolean %define
+       declaration indicating whether filename_type has an operator==.  If
+       filename_type is `std::string', it defaults to `1', `0' otherwise.
+       * data/location.cc: Iff b4_define_location_comparison is `1', add
+       operator== and operator!= for class position and for class location.
+
+       Some minor fixes.
+       * src/scan-action.l: Remove unused file.
+       * src/symtab.c (symbol_printer_set): Use printer_location not
+       destructor_location.
+       * src/symtab.h (struct symbol): Replace incorrect source comment for
+       printer members.
+       * tests/input.at (Incompatible Aliases): Update output with correct
+       printer location.
+
 2006-06-20  Joel E. Denny  <jdenny@ces.clemson.edu>
 
        Don't put the pre-prologue in the header file.  For the yacc.c code
index 57aee0ceb05a01db7f4b5e3501bb52628a2ab4f6..c8c220c27ef2f0df48d6a122b104191772f5ea06 100644 (file)
@@ -30,6 +30,8 @@ m4_define_default([b4_parser_class_name], [parser])
 m4_define_default([b4_location_type], [location])
 m4_define_default([b4_filename_type], [std::string])
 m4_define_default([b4_namespace], m4_defn([b4_prefix]))
+m4_define_default([b4_define_location_comparison],
+                 m4_if(b4_filename_type, [std::string], [1], [0]))
 
 
 # b4_token_enums(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
index 869320e799a8d97667445ba2444293292f6c3664..156115ca29bf2c55cc4fa53671a95ceaa54ec6ec 100644 (file)
@@ -119,7 +119,24 @@ namespace ]b4_namespace[
   {
     return begin + -width;
   }
+]m4_if(b4_define_location_comparison, [1], [[
+  /// Compare two position objects.
+  inline bool
+  operator== (const position& pos1, const position& pos2)
+  {
+    return
+      (pos1.filename == pos2.filename
+       || pos1.filename && pos2.filename && *pos1.filename == *pos2.filename)
+      && pos1.line == pos2.line && pos1.column == pos2.column;
+  }
 
+  /// Compare two position objects.
+  inline bool
+  operator!= (const position& pos1, const position& pos2)
+  {
+    return !(pos1 == pos2);
+  }
+]])[
   /** \brief Intercept output stream redirection.
    ** \param ostr the destination output stream
    ** \param pos a reference to the position to redirect
@@ -224,7 +241,21 @@ namespace ]b4_namespace[
     res.columns (width);
     return res;
   }
+]m4_if(b4_define_location_comparison, [1], [[
+  /// Compare two location objects.
+  inline bool
+  operator== (const location& loc1, const location& loc2)
+  {
+    return loc1.begin == loc2.begin && loc1.end == loc2.end;
+  }
 
+  /// Compare two location objects.
+  inline bool
+  operator!= (const location& loc1, const location& loc2)
+  {
+    return !(loc1 == loc2);
+  }
+]])[
   /** \brief Intercept output stream redirection.
    ** \param ostr the destination output stream
    ** \param loc a reference to the location to redirect
diff --git a/src/scan-action.l b/src/scan-action.l
deleted file mode 100644 (file)
index f8dbf67..0000000
+++ /dev/null
@@ -1,866 +0,0 @@
-/* Bison Grammar Scanner                             -*- C -*-
-
-   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
-
-   This file is part of Bison, the GNU Compiler Compiler.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   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., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301  USA
-*/
-
-%option debug nodefault nounput noyywrap never-interactive
-%option prefix="gram_" outfile="lex.yy.c"
-
-%{
-#include "system.h"
-
-#include <mbswidth.h>
-#include <get-errno.h>
-#include <quote.h>
-
-#include "complain.h"
-#include "files.h"
-#include "getargs.h"
-#include "gram.h"
-#include "quotearg.h"
-#include "reader.h"
-#include "uniqstr.h"
-
-#define YY_USER_INIT                                   \
-  do                                                   \
-    {                                                  \
-      scanner_cursor.file = current_file;              \
-      scanner_cursor.line = 1;                         \
-      scanner_cursor.column = 1;                       \
-      code_start = scanner_cursor;                     \
-    }                                                  \
-  while (0)
-
-/* Location of scanner cursor.  */
-boundary scanner_cursor;
-
-static void adjust_location (location *, char const *, size_t);
-#define YY_USER_ACTION  adjust_location (loc, yytext, yyleng);
-
-static size_t no_cr_read (FILE *, char *, size_t);
-#define YY_INPUT(buf, result, size) ((result) = no_cr_read (yyin, buf, size))
-
-/* Within well-formed rules, RULE_LENGTH is the number of values in
-   the current rule so far, which says where to find `$0' with respect
-   to the top of the stack.  It is not the same as the rule->length in
-   the case of mid rule actions.
-
-   Outside of well-formed rules, RULE_LENGTH has an undefined value.  */
-int rule_length;
-
-static void handle_dollar (int token_type, char *cp, location loc);
-static void handle_at (int token_type, char *cp, location loc);
-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
-%x SC_STRING SC_CHARACTER
-%x SC_ESCAPED_STRING SC_ESCAPED_CHARACTER
-%x SC_PRE_CODE SC_BRACED_CODE SC_PROLOGUE SC_EPILOGUE
-
-letter   [.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]
-id       {letter}({letter}|[0-9])*
-directive %{letter}({letter}|[0-9]|-)*
-int      [0-9]+
-
-/* POSIX says that a tag must be both an id and a C union member, but
-   historically almost any character is allowed in a tag.  We disallow
-   NUL and newline, as this simplifies our implementation.  */
-tag     [^\0\n>]+
-
-/* Zero or more instances of backslash-newline.  Following GCC, allow
-   white space between the backslash and the newline.  */
-splice  (\\[ \f\t\v]*\n)*
-
-%%
-%{
-  /* Nesting level of the current code in braces.  */
-  int braces_level IF_LINT (= 0);
-
-  /* Parent context state, when applicable.  */
-  int context_state IF_LINT (= 0);
-
-  /* Token type to return, when applicable.  */
-  int token_type IF_LINT (= 0);
-
-  /* Where containing code started, when applicable.  Its initial
-     value is relevant only when yylex is invoked in the SC_EPILOGUE
-     start condition.  */
-  boundary code_start = scanner_cursor;
-
-  /* Where containing comment or string or character literal started,
-     when applicable.  */
-  boundary token_start IF_LINT (= scanner_cursor);
-%}
-
-
-  /*-----------------------.
-  | Scanning white space.  |
-  `-----------------------*/
-
-<INITIAL>
-{
-  /* Comments and white space.  */
-  ","         warn_at (*loc, _("stray `,' treated as white space"));
-  [ \f\n\t\v]  |
-  "//".*       ;
-  "/*" {
-    token_start = loc->start;
-    context_state = YY_START;
-    BEGIN SC_YACC_COMMENT;
-  }
-
-  /* #line directives are not documented, and may be withdrawn or
-     modified in future versions of Bison.  */
-  ^"#line "{int}" \"".*"\"\n" {
-    handle_syncline (yytext + sizeof "#line " - 1);
-  }
-}
-
-
-  /*----------------------------.
-  | Scanning Bison directives.  |
-  `----------------------------*/
-<INITIAL>
-{
-
-  /* Code in between braces.  */
-  "{" {
-    STRING_GROW;
-    token_type = BRACED_CODE;
-    braces_level = 0;
-    code_start = loc->start;
-    BEGIN SC_BRACED_CODE;
-  }
-
-}
-
-
-  /*------------------------------------------------------------.
-  | Scanning a C comment.  The initial `/ *' is already eaten.  |
-  `------------------------------------------------------------*/
-
-<SC_COMMENT>
-{
-  "*"{splice}"/"  STRING_GROW; BEGIN context_state;
-  <<EOF>>        unexpected_eof (token_start, "*/"); BEGIN context_state;
-}
-
-
-  /*--------------------------------------------------------------.
-  | Scanning a line comment.  The initial `//' is already eaten.  |
-  `--------------------------------------------------------------*/
-
-<SC_LINE_COMMENT>
-{
-  "\n"          STRING_GROW; BEGIN context_state;
-  {splice}      STRING_GROW;
-  <<EOF>>       BEGIN context_state;
-}
-
-
-  /*------------------------------------------------.
-  | Scanning a Bison string, including its escapes. |
-  | The initial quote is already eaten.             |
-  `------------------------------------------------*/
-
-<SC_ESCAPED_STRING>
-{
-  "\"" {
-    STRING_FINISH;
-    loc->start = token_start;
-    val->chars = last_string;
-    rule_length++;
-    BEGIN INITIAL;
-    return STRING;
-  }
-  \n           unexpected_newline (token_start, "\""); BEGIN INITIAL;
-  <<EOF>>      unexpected_eof (token_start, "\"");     BEGIN INITIAL;
-}
-
-  /*----------------------------------------------------------.
-  | Scanning a Bison character literal, decoding its escapes. |
-  | The initial quote is already eaten.                              |
-  `----------------------------------------------------------*/
-
-<SC_ESCAPED_CHARACTER>
-{
-  "'" {
-    unsigned char last_string_1;
-    STRING_GROW;
-    STRING_FINISH;
-    loc->start = token_start;
-    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);
-    STRING_FREE;
-    rule_length++;
-    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"));
-}
-
-
-  /*----------------------------.
-  | Decode escaped characters.  |
-  `----------------------------*/
-
-<SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>
-{
-  \\[0-7]{1,3} {
-    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)
-      complain_at (*loc, _("invalid null character: %s"), quote (yytext));
-    else
-      obstack_1grow (&obstack_for_string, c);
-  }
-
-  \\x[0-9abcdefABCDEF]+ {
-    unsigned long int c;
-    set_errno (0);
-    c = strtoul (yytext + 2, 0, 16);
-    if (UCHAR_MAX < c || get_errno ())
-      complain_at (*loc, _("invalid escape sequence: %s"), quote (yytext));
-    else if (! c)
-      complain_at (*loc, _("invalid null character: %s"), quote (yytext));
-    else
-      obstack_1grow (&obstack_for_string, c);
-  }
-
-  \\a  obstack_1grow (&obstack_for_string, '\a');
-  \\b  obstack_1grow (&obstack_for_string, '\b');
-  \\f  obstack_1grow (&obstack_for_string, '\f');
-  \\n  obstack_1grow (&obstack_for_string, '\n');
-  \\r  obstack_1grow (&obstack_for_string, '\r');
-  \\t  obstack_1grow (&obstack_for_string, '\t');
-  \\v  obstack_1grow (&obstack_for_string, '\v');
-
-  /* \\[\"\'?\\] would be shorter, but it confuses xgettext.  */
-  \\("\""|"'"|"?"|"\\")  obstack_1grow (&obstack_for_string, yytext[1]);
-
-  \\(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));
-    else
-      obstack_1grow (&obstack_for_string, c);
-  }
-  \\(.|\n)     {
-    complain_at (*loc, _("unrecognized escape sequence: %s"), quote (yytext));
-    STRING_GROW;
-  }
-}
-
-  /*--------------------------------------------.
-  | Scanning user-code characters and strings.  |
-  `--------------------------------------------*/
-
-<SC_CHARACTER,SC_STRING>
-{
-  {splice}|\\{splice}[^\n$@\[\]]       STRING_GROW;
-}
-
-<SC_CHARACTER>
-{
-  "'"          STRING_GROW; BEGIN context_state;
-  \n           unexpected_newline (token_start, "'"); BEGIN context_state;
-  <<EOF>>      unexpected_eof (token_start, "'"); BEGIN context_state;
-}
-
-<SC_STRING>
-{
-  "\""         STRING_GROW; BEGIN context_state;
-  \n           unexpected_newline (token_start, "\""); BEGIN context_state;
-  <<EOF>>      unexpected_eof (token_start, "\""); BEGIN context_state;
-}
-
-
-  /*---------------------------------------------------.
-  | Strings, comments etc. can be found in user code.  |
-  `---------------------------------------------------*/
-
-<INITIAL>
-{
-  "'" {
-    STRING_GROW;
-    context_state = YY_START;
-    token_start = loc->start;
-    BEGIN SC_CHARACTER;
-  }
-  "\"" {
-    STRING_GROW;
-    context_state = YY_START;
-    token_start = loc->start;
-    BEGIN SC_STRING;
-  }
-  "/"{splice}"*" {
-    STRING_GROW;
-    context_state = YY_START;
-    token_start = loc->start;
-    BEGIN SC_COMMENT;
-  }
-  "/"{splice}"/" {
-    STRING_GROW;
-    context_state = YY_START;
-    BEGIN SC_LINE_COMMENT;
-  }
-}
-
-
-  /*---------------------------------------------------------------.
-  | Scanning some code in braces (%union and actions). The initial |
-  | "{" is already eaten.                                          |
-  `---------------------------------------------------------------*/
-
-<INITIAL>
-{
-  "{"|"<"{splice}"%"  STRING_GROW; braces_level++;
-  "%"{splice}">"      STRING_GROW; braces_level--;
-  "}" {
-    bool outer_brace = --braces_level < 0;
-
-    /* As an undocumented Bison extension, append `;' before the last
-       brace in braced code, so that the user code can omit trailing
-       `;'.  But do not append `;' if emulating Yacc, since Yacc does
-       not append one.
-
-       FIXME: Bison should warn if a semicolon seems to be necessary
-       here, and should omit the semicolon if it seems unnecessary
-       (e.g., after ';', '{', or '}', each followed by comments or
-       white space).  Such a warning shouldn't depend on --yacc; it
-       should depend on a new --pedantic option, which would cause
-       Bison to warn if it detects an extension to POSIX.  --pedantic
-       should also diagnose other Bison extensions like %yacc.
-       Perhaps there should also be a GCC-style --pedantic-errors
-       option, so that such warnings are diagnosed as errors.  */
-    if (outer_brace && token_type == BRACED_CODE && ! yacc_flag)
-      obstack_1grow (&obstack_for_string, ';');
-
-    obstack_1grow (&obstack_for_string, '}');
-
-    if (outer_brace)
-      {
-       STRING_FINISH;
-       rule_length++;
-       loc->start = code_start;
-       val->chars = last_string;
-       BEGIN INITIAL;
-       return token_type;
-      }
-  }
-
-  /* Tokenize `<<%' correctly (as `<<' `%') rather than incorrrectly
-     (as `<' `<%').  */
-  "<"{splice}"<"  STRING_GROW;
-
-  "$"("<"{tag}">")?(-?[0-9]+|"$")  handle_dollar (token_type, yytext, *loc);
-  "@"(-?[0-9]+|"$")               handle_at (token_type, yytext, *loc);
-
-  <<EOF>>  unexpected_eof (code_start, "}"); BEGIN INITIAL;
-}
-
-
-  /*--------------------------------------------------------------.
-  | Scanning some prologue: from "%{" (already scanned) to "%}".  |
-  `--------------------------------------------------------------*/
-
-<SC_PROLOGUE>
-{
-  "%}" {
-    STRING_FINISH;
-    loc->start = code_start;
-    val->chars = last_string;
-    BEGIN INITIAL;
-    return PROLOGUE;
-  }
-
-  <<EOF>>  unexpected_eof (code_start, "%}"); BEGIN INITIAL;
-}
-
-
-  /*---------------------------------------------------------------.
-  | Scanning the epilogue (everything after the second "%%", which |
-  | has already been eaten).                                       |
-  `---------------------------------------------------------------*/
-
-<SC_EPILOGUE>
-{
-  <<EOF>> {
-    STRING_FINISH;
-    loc->start = code_start;
-    val->chars = last_string;
-    BEGIN INITIAL;
-    return EPILOGUE;
-  }
-}
-
-
-  /*-----------------------------------------.
-  | Escape M4 quoting characters in C code.  |
-  `-----------------------------------------*/
-
-<SC_COMMENT,SC_LINE_COMMENT,SC_STRING,SC_CHARACTER,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
-{
-  \$   obstack_sgrow (&obstack_for_string, "$][");
-  \@   obstack_sgrow (&obstack_for_string, "@@");
-  \[   obstack_sgrow (&obstack_for_string, "@{");
-  \]   obstack_sgrow (&obstack_for_string, "@}");
-}
-
-
-  /*-----------------------------------------------------.
-  | 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
-   a handle (those referenced by $0, $-1, etc.) are required by the
-   semantic actions of this grammar. */
-int max_left_semantic_context = 0;
-
-/* Set *LOC and adjust scanner cursor to account for token TOKEN of
-   size SIZE.  */
-
-static void
-adjust_location (location *loc, char const *token, size_t size)
-{
-  int line = scanner_cursor.line;
-  int column = scanner_cursor.column;
-  char const *p0 = token;
-  char const *p = token;
-  char const *lim = token + size;
-
-  loc->start = scanner_cursor;
-
-  for (p = token; p < lim; p++)
-    switch (*p)
-      {
-      case '\n':
-       line++;
-       column = 1;
-       p0 = p + 1;
-       break;
-
-      case '\t':
-       column += mbsnwidth (p0, p - p0, 0);
-       column += 8 - ((column - 1) & 7);
-       p0 = p + 1;
-       break;
-      }
-
-  scanner_cursor.line = line;
-  scanner_cursor.column = column + mbsnwidth (p0, p - p0, 0);
-
-  loc->end = scanner_cursor;
-}
-
-
-/* Read bytes from FP into buffer BUF of size SIZE.  Return the
-   number of bytes read.  Remove '\r' from input, treating \r\n
-   and isolated \r as \n.  */
-
-static size_t
-no_cr_read (FILE *fp, char *buf, size_t size)
-{
-  size_t bytes_read = fread (buf, 1, size, fp);
-  if (bytes_read)
-    {
-      char *w = memchr (buf, '\r', bytes_read);
-      if (w)
-       {
-         char const *r = ++w;
-         char const *lim = buf + bytes_read;
-
-         for (;;)
-           {
-             /* Found an '\r'.  Treat it like '\n', but ignore any
-                '\n' that immediately follows.  */
-             w[-1] = '\n';
-             if (r == lim)
-               {
-                 int ch = getc (fp);
-                 if (ch != '\n' && ungetc (ch, fp) != ch)
-                   break;
-               }
-             else if (*r == '\n')
-               r++;
-
-             /* Copy until the next '\r'.  */
-             do
-               {
-                 if (r == lim)
-                   return w - buf;
-               }
-             while ((*w++ = *r++) != '\r');
-           }
-
-         return w - buf;
-       }
-    }
-
-  return bytes_read;
-}
-
-
-/*------------------------------------------------------------------.
-| TEXT is pointing to a wannabee semantic value (i.e., a `$').      |
-|                                                                   |
-| Possible inputs: $[<TYPENAME>]($|integer)                         |
-|                                                                   |
-| Output to OBSTACK_FOR_STRING a reference to this semantic value.  |
-`------------------------------------------------------------------*/
-
-static inline bool
-handle_action_dollar (char *text, location loc)
-{
-  const char *type_name = NULL;
-  char *cp = text + 1;
-
-  if (! current_rule)
-    return false;
-
-  /* Get the type name if explicit. */
-  if (*cp == '<')
-    {
-      type_name = ++cp;
-      while (*cp != '>')
-       ++cp;
-      *cp = '\0';
-      ++cp;
-    }
-
-  if (*cp == '$')
-    {
-      if (!type_name)
-       type_name = symbol_list_n_type_name_get (current_rule, loc, 0);
-      if (!type_name && typed)
-       complain_at (loc, _("$$ of `%s' has no declared type"),
-                    current_rule->sym->tag);
-      if (!type_name)
-       type_name = "";
-      obstack_fgrow1 (&obstack_for_string,
-                     "]b4_lhs_value([%s])[", type_name);
-    }
-  else
-    {
-      long int num;
-      set_errno (0);
-      num = strtol (cp, 0, 10);
-
-      if (INT_MIN <= num && num <= rule_length && ! get_errno ())
-       {
-         int n = num;
-         if (1-n > max_left_semantic_context)
-           max_left_semantic_context = 1-n;
-         if (!type_name && n > 0)
-           type_name = symbol_list_n_type_name_get (current_rule, loc, n);
-         if (!type_name && typed)
-           complain_at (loc, _("$%d of `%s' has no declared type"),
-                        n, current_rule->sym->tag);
-         if (!type_name)
-           type_name = "";
-         obstack_fgrow3 (&obstack_for_string,
-                         "]b4_rhs_value(%d, %d, [%s])[",
-                         rule_length, n, type_name);
-       }
-      else
-       complain_at (loc, _("integer out of range: %s"), quote (text));
-    }
-
-  return true;
-}
-
-
-/*----------------------------------------------------------------.
-| Map `$?' onto the proper M4 symbol, depending on its TOKEN_TYPE |
-| (are we in an action?).                                         |
-`----------------------------------------------------------------*/
-
-static void
-handle_dollar (int token_type, char *text, location loc)
-{
-  switch (token_type)
-    {
-    case BRACED_CODE:
-      if (handle_action_dollar (text, loc))
-       return;
-      break;
-
-    case PERCENT_DESTRUCTOR:
-    case PERCENT_INITIAL_ACTION:
-    case PERCENT_PRINTER:
-      if (text[1] == '$')
-       {
-         obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar[");
-         return;
-       }
-      break;
-
-    default:
-      break;
-    }
-
-  complain_at (loc, _("invalid value: %s"), quote (text));
-}
-
-
-/*------------------------------------------------------.
-| TEXT is a location token (i.e., a `@...').  Output to |
-| OBSTACK_FOR_STRING a reference to this location.      |
-`------------------------------------------------------*/
-
-static inline bool
-handle_action_at (char *text, location loc)
-{
-  char *cp = text + 1;
-  locations_flag = true;
-
-  if (! current_rule)
-    return false;
-
-  if (*cp == '$')
-    obstack_sgrow (&obstack_for_string, "]b4_lhs_location[");
-  else
-    {
-      long int num;
-      set_errno (0);
-      num = strtol (cp, 0, 10);
-
-      if (INT_MIN <= num && num <= rule_length && ! get_errno ())
-       {
-         int n = num;
-         obstack_fgrow2 (&obstack_for_string, "]b4_rhs_location(%d, %d)[",
-                         rule_length, n);
-       }
-      else
-       complain_at (loc, _("integer out of range: %s"), quote (text));
-    }
-
-  return true;
-}
-
-
-/*----------------------------------------------------------------.
-| Map `@?' onto the proper M4 symbol, depending on its TOKEN_TYPE |
-| (are we in an action?).                                         |
-`----------------------------------------------------------------*/
-
-static void
-handle_at (int token_type, char *text, location loc)
-{
-  switch (token_type)
-    {
-    case BRACED_CODE:
-      handle_action_at (text, loc);
-      return;
-
-    case PERCENT_INITIAL_ACTION:
-    case PERCENT_DESTRUCTOR:
-    case PERCENT_PRINTER:
-      if (text[1] == '$')
-       {
-         obstack_sgrow (&obstack_for_string, "]b4_at_dollar[");
-         return;
-       }
-      break;
-
-    default:
-      break;
-    }
-
-  complain_at (loc, _("invalid value: %s"), quote (text));
-}
-
-
-/*------------------------------------------------------.
-| Scan NUMBER for a base-BASE integer at location LOC.  |
-`------------------------------------------------------*/
-
-static unsigned long int
-scan_integer (char const *number, int base, location loc)
-{
-  unsigned long int num;
-  set_errno (0);
-  num = strtoul (number, 0, base);
-  if (INT_MAX < num || get_errno ())
-    {
-      complain_at (loc, _("integer out of range: %s"), quote (number));
-      num = INT_MAX;
-    }
-  return num;
-}
-
-
-/*------------------------------------------------------------------.
-| Convert universal character name UCN to a single-byte character,  |
-| and return that character.  Return -1 if UCN does not correspond  |
-| to a single-byte character.                                      |
-`------------------------------------------------------------------*/
-
-static int
-convert_ucn_to_byte (char const *ucn)
-{
-  unsigned long int code = strtoul (ucn + 2, 0, 16);
-
-  /* FIXME: Currently we assume Unicode-compatible unibyte characters
-     on ASCII hosts (i.e., Latin-1 on hosts with 8-bit bytes).  On
-     non-ASCII hosts we support only the portable C character set.
-     These limitations should be removed once we add support for
-     multibyte characters.  */
-
-  if (UCHAR_MAX < code)
-    return -1;
-
-#if ! ('$' == 0x24 && '@' == 0x40 && '`' == 0x60 && '~' == 0x7e)
-  {
-    /* A non-ASCII host.  Use CODE to index into a table of the C
-       basic execution character set, which is guaranteed to exist on
-       all Standard C platforms.  This table also includes '$', '@',
-       and '`', which are not in the basic execution character set but
-       which are unibyte characters on all the platforms that we know
-       about.  */
-    static signed char const table[] =
-      {
-       '\0',   -1,   -1,   -1,   -1,   -1,   -1, '\a',
-       '\b', '\t', '\n', '\v', '\f', '\r',   -1,   -1,
-         -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-         -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
-        ' ',  '!',  '"',  '#',  '$',  '%',  '&', '\'',
-        '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
-        '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
-        '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
-        '@',  'A',  'B',  'C',  'D',  'E',  'F',  'G',
-        'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
-        'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
-        'X',  'Y',  'Z',  '[', '\\',  ']',  '^',  '_',
-        '`',  'a',  'b',  'c',  'd',  'e',  'f',  'g',
-        'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
-        'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
-        'x',  'y',  'z',  '{',  '|',  '}',  '~'
-      };
-
-    code = code < sizeof table ? table[code] : -1;
-  }
-#endif
-
-  return code;
-}
-
-
-/*----------------------------------------------------------------.
-| Handle `#line INT "FILE"'.  ARGS has already skipped `#line '.  |
-`----------------------------------------------------------------*/
-
-static void
-handle_syncline (char *args)
-{
-  int lineno = strtol (args, &args, 10);
-  const char *file = NULL;
-  file = strchr (args, '"') + 1;
-  *strchr (file, '"') = 0;
-  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.  |
-`------------------------------------------------------------------------*/
-
-static void
-unexpected_eof (boundary start, char const *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);
-}
-
-
-/*-------------------------.
-| Initialize the scanner.  |
-`-------------------------*/
-
-void
-scanner_initialize (void)
-{
-  obstack_init (&obstack_for_string);
-}
-
-
-/*-----------------------------------------------.
-| Free all the memory allocated to the scanner.  |
-`-----------------------------------------------*/
-
-void
-scanner_free (void)
-{
-  obstack_free (&obstack_for_string, 0);
-  /* Reclaim Flex's buffers.  */
-  yy_delete_buffer (YY_CURRENT_BUFFER);
-}
index a90d00b331f263d2a70151085bc9e9016e6b70bf..ae0993ee7dce3553e8dc2709d90ff1657fb11a74 100644 (file)
@@ -158,7 +158,7 @@ symbol_printer_set (symbol *sym, const char *printer, location loc)
   if (printer)
     {
       if (sym->printer)
-       redeclaration (sym, "%printer", sym->destructor_location, loc);
+       redeclaration (sym, "%printer", sym->printer_location, loc);
       sym->printer = printer;
       sym->printer_location = loc;
     }
index 13eb1437ed9d1076d665bb696d9795d3b743ee45..f80674cce68ea2b2f0464d40e4a89b26ddf8ad72 100644 (file)
@@ -64,7 +64,7 @@ struct symbol
   const char *destructor;
   location destructor_location;
 
-  /* Does not own the memory. */
+  /* Printer. */
   const char *printer;
   location printer_location;
 
index 973cfee125f442ad1ba92e827fc4ba6d2fdca90f..4b66d32e800de187fff78c723c1df95114b44e24 100644 (file)
@@ -163,7 +163,7 @@ input.y:3.7-11: first declaration
 input.y:10.13-17: %destructor redeclaration for foo
 input.y:5.13-17: first declaration
 input.y:9.10-14: %printer redeclaration for foo
-input.y:10.13-17: first declaration
+input.y:4.10-14: first declaration
 input.y:11.1-5: %left redeclaration for foo
 input.y:6.1-5: first declaration
 ]])