bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Add %language declaration


From: Paolo Bonzini
Subject: [PATCH] Add %language declaration
Date: Mon, 09 Oct 2006 11:30:14 +0200
User-agent: Thunderbird 1.5.0.7 (Macintosh/20060909)

This patch adds the %language declaration. While Akim was skeptical, I hope he likes this design more.

Currently, C is "special cased" by Bison in that the choice of which skeleton to use is hard-coded in output.c. With this patch, all the choice of skeletons is brought out of the C code, in files named c-skel.m4, c++-skel.m4, and in the (near) future java-skel.m4. Small changes will be needed when push.c and yacc.c are merged, please contact me if you need help.

Additionally, I already added the necessary code to support Java, where the default output file name for "foo.y" will be "foo.java" rather than "foo.tab.java" (the Java compiler is picky about the filenames for the source code). This is the main reason why %language is not, IMHO, an optional feature, but a necessity -- I don't want to teach "if you use Java parsers, you are forced to use the -o option or everything breaks horribly".

Two %skeleton or two %language directives are invalid, and likewise for two -S/-L options. However, any of -S or %skeleton may override -L or %language (to ease development). This is also different from the previous version, where the two options overrode each other in interesting ways.

With this patch, I document %skeleton too and I can document it the same as -S:

   @item -S @var{file}
   @itemx address@hidden
   Specify the skeleton to use.  You probably don't need this option unless
   you are developing Bison.


BTW, with this patch in place, the changes to src for Java support amount to exactly *one* line.

Paolo
Index: data/c++-skel.m4
===================================================================
RCS file: data/c++-skel.m4
diff -N data/c++-skel.m4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ data/c++-skel.m4    9 Oct 2006 07:28:28 -0000
@@ -0,0 +1,29 @@
+m4_divert(-1)                                               -*- Autoconf -*-
+
+# C++ skeleton dispatching for Bison.
+# Copyright (C) 2006 Free Software Foundation, Inc.
+
+# 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
+
+b4_glr_if(             [m4_define([b4_used_skeleton], 
[b4_pkgdatadir/[glr.cc]])])
+b4_nondeterministic_if([m4_define([b4_used_skeleton], 
[b4_pkgdatadir/[glr.cc]])])
+
+b4_push_if([m4_fatal([%push-parser is not supported by C++])])
+
+m4_define_default([b4_used_skeleton], [b4_pkgdatadir/[lalr1.cc]])
+m4_define_default([b4_skeleton], ["b4_basename(b4_used_skeleton)"])
+
+m4_include(b4_used_skeleton)
Index: data/c-skel.m4
===================================================================
RCS file: data/c-skel.m4
diff -N data/c-skel.m4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ data/c-skel.m4      9 Oct 2006 07:28:28 -0000
@@ -0,0 +1,28 @@
+m4_divert(-1)                                               -*- Autoconf -*-
+
+# C skeleton dispatching for Bison.
+# Copyright (C) 2006 Free Software Foundation, Inc.
+
+# 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
+
+b4_glr_if(             [m4_define([b4_used_skeleton], 
[b4_pkgdatadir/[glr.c]])])
+b4_nondeterministic_if([m4_define([b4_used_skeleton], 
[b4_pkgdatadir/[glr.c]])])
+b4_push_if(            [m4_define([b4_used_skeleton], 
[b4_pkgdatadir/[push.c]])])
+
+m4_define_default([b4_used_skeleton], [b4_pkgdatadir/[yacc.c]])
+m4_define_default([b4_skeleton], ["b4_basename(b4_used_skeleton)"])
+
+m4_include(b4_used_skeleton)
Index: data/push.c
===================================================================
RCS file: /sources/bison/bison/data/push.c,v
retrieving revision 1.3
diff -u -r1.3 push.c
--- data/push.c 21 Sep 2006 17:45:21 -0000      1.3
+++ data/push.c 9 Oct 2006 07:28:31 -0000
@@ -22,6 +22,13 @@
 
 m4_include(b4_pkgdatadir/[c.m4])
 
+b4_glr_if([
+m4_fatal([GLR and %push-parser are not yet compatible])])
+
+b4_nondeterministic_if([
+m4_fatal(b4_skeleton[GLR and %push-parser are not yet compatible])])
+
+
 ## ---------------- ##
 ## Default values.  ##
 ## ---------------- ##
Index: doc/bison.texinfo
===================================================================
RCS file: /sources/bison/bison/doc/bison.texinfo,v
retrieving revision 1.205
diff -u -r1.205 bison.texinfo
--- doc/bison.texinfo   11 Sep 2006 18:56:58 -0000      1.205
+++ doc/bison.texinfo   9 Oct 2006 07:28:46 -0000
@@ -7158,14 +7158,24 @@
 
 @node C++ Bison Interface
 @subsection C++ Bison Interface
address@hidden - %skeleton "lalr1.cc"
address@hidden - %language "C++"
 @c - Always pure
 @c - initial action
 
-The C++ parser @acronym{LALR}(1) skeleton is named @file{lalr1.cc}.  To
-select it, you may either pass the option @option{--skeleton=lalr1.cc}
+The C++ parser @acronym{LALR}(1) skeleton is selected using a
+language directive, @samp{%language "C++"}, or the synonymous
+command-line option @address@hidden both
+  the grammar directive and the command-line option, the
+ language name is case-insensitive}.  These were introduced
+in Bison 2.3; for compatibility with earlier versions, you
+you may also pass the option @option{--skeleton=lalr1.cc}
 to Bison, or include the directive @samp{%skeleton "lalr1.cc"} in the
-grammar preamble.  When run, @command{bison} will create several
+grammar preamble.  Specifying the language is however preferred,
+because it is clearer and because it will automatically choose the
+correct skeleton for GLR parsers (the C++ GLR skeleton is still
+under development).
+
+When run, @command{bison} will create several
 entities in the @samp{yy} namespace.  Use the @samp{%name-prefix}
 directive to change the namespace name, see @ref{Decl Summary}.  The
 various classes are generated in the following files:
@@ -7553,8 +7563,8 @@
 
 @comment file: calc++-parser.yy
 @example
-%skeleton "lalr1.cc"                          /*  -*- C++ -*- */
-%require "2.1a"
+%language "C++"                          /*  -*- C++ -*- */
+%require "2.3a+"
 %defines
 %define "parser_class_name" "calcxx_parser"
 @end example
Index: src/files.c
===================================================================
RCS file: /sources/bison/bison/src/files.c,v
retrieving revision 1.96
diff -u -r1.96 files.c
--- src/files.c 9 Jul 2006 03:44:51 -0000       1.96
+++ src/files.c 9 Oct 2006 07:28:47 -0000
@@ -157,10 +157,18 @@
 static void
 compute_exts_from_gf (const char *ext)
 {
-  src_extension = tr (ext, 'y', 'c');
-  src_extension = tr (src_extension, 'Y', 'C');
-  header_extension = tr (ext, 'y', 'h');
-  header_extension = tr (header_extension, 'Y', 'H');
+  if (!strcmp (ext, ".y"))
+    {
+      src_extension = language->src_extension;
+      header_extension = language->header_extension;
+    }
+  else
+    {
+      src_extension = tr (ext, 'y', 'c');
+      src_extension = tr (src_extension, 'Y', 'C');
+      header_extension = tr (ext, 'y', 'h');
+      header_extension = tr (header_extension, 'Y', 'H');
+    }
 }
 
 /* Compute extensions from the given c source file extension.  */
@@ -282,7 +290,10 @@
            xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0)));
        }
 
-      all_but_ext = concat2 (all_but_tab_ext, TAB_EXT);
+      if (!language || language->add_tab)
+        all_but_ext = concat2 (all_but_tab_ext, TAB_EXT);
+      else
+        all_but_ext = all_but_tab_ext;
 
       /* Compute the extensions from the grammar file name.  */
       if (ext && !yacc_flag)
Index: src/getargs.c
===================================================================
RCS file: /sources/bison/bison/src/getargs.c,v
retrieving revision 1.80
diff -u -r1.80 getargs.c
--- src/getargs.c       20 Sep 2006 20:04:28 -0000      1.80
+++ src/getargs.c       9 Oct 2006 07:28:47 -0000
@@ -66,11 +66,18 @@
 int trace_flag = trace_none;
 int warnings_flag = warnings_none;
 
+static const struct bison_language valid_languages[] = {
+  { "c", "c-skel.m4", ".c", ".h", true },
+  { "c++", "c++-skel.m4", ".cc", ".hh", true },
+  { NULL, NULL, NULL, NULL, false }
+};
+
+static int skeleton_prio = 2;
 const char *skeleton = NULL;
+static int language_prio = 2;
+const struct bison_language *language = &valid_languages[0];
 const char *include = NULL;
 
-extern char *program_name;
-
 
 /** Decode an option's set of keys.
  *
@@ -321,12 +328,87 @@
 }
 
 
+/*-------------------------------------.
+| --skeleton and --language handling.  |
+`--------------------------------------*/
+
+void
+skeleton_arg (char *arg, int prio, location *loc)
+{
+  if (skeleton_prio < prio)
+    return;
+  if (skeleton_prio == prio)
+    {
+      const char *msg =
+       _("multiple skeleton declarations are invalid");
+      if (loc)
+       {
+         complain_at (*loc, msg);
+          return;
+       }
+      else
+       {
+         error (0, 0, msg);
+         usage (EXIT_FAILURE);
+       }
+    }
+
+  skeleton_prio = prio;
+  skeleton = arg;
+}
+
+void
+language_argmatch (char *args, int prio, location *loc)
+{
+  int i;
+  if (language_prio < prio)
+    return;
+  if (language_prio == prio)
+    {
+      const char *msg =
+       _("multiple language declarations are invalid");
+      if (loc)
+       {
+         complain_at (*loc, msg);
+          return;
+       }
+      else
+       {
+         error (0, 0, msg);
+         usage (EXIT_FAILURE);
+       }
+    }
+
+  for (i = 0; valid_languages[i].language; i++)
+    if (!strcasecmp (args, valid_languages[i].language))
+      {
+       language_prio = prio;
+       language = &valid_languages[i];
+       break;
+      }
+
+  if (!language)
+    {
+      const char *msg = _("invalid language `%s'");
+      if (loc)
+       {
+         complain_at (*loc, msg, args);
+          return;
+       }
+      else
+       {
+         error (0, 0, msg, args);
+         usage (EXIT_FAILURE);
+       }
+    }
+}
+
 /*----------------------.
 | Process the options.  |
 `----------------------*/
 
 /* Shorts options.  */
-static char const short_options[] = "yvegdhr:ltknVo:b:p:S:T::W";
+static char const short_options[] = "yvegdhr:L:ltknVo:b:p:S:T::W";
 
 /* Values for long options that do not have single-letter equivalents.  */
 enum
@@ -372,6 +454,7 @@
   { "no-parser",      no_argument,               0,   'n' },
   { "raw",            no_argument,               0,     0 },
   { "skeleton",       required_argument,         0,   'S' },
+  { "language",       required_argument,         0,   'L' },
   { "token-table",    no_argument,               0,   'k' },
 
   {0, 0, 0, 0}
@@ -412,8 +495,12 @@
       case 'h':
        usage (EXIT_SUCCESS);
 
+      case 'L':
+       language_argmatch (optarg, 0, NULL);
+       break;
+
       case 'S':
-       skeleton = AS_FILE_NAME (optarg);
+       skeleton_arg (AS_FILE_NAME (optarg), 0, NULL);
        break;
 
       case 'I':
Index: src/getargs.h
===================================================================
RCS file: /sources/bison/bison/src/getargs.h,v
retrieving revision 1.34
diff -u -r1.34 getargs.h
--- src/getargs.h       15 Sep 2006 15:56:26 -0000      1.34
+++ src/getargs.h       9 Oct 2006 07:28:47 -0000
@@ -22,6 +22,10 @@
 #ifndef GETARGS_H_
 # define GETARGS_H_
 
+#include "location.h"
+
+extern char *program_name;
+
 /* flags set by % directives */
 
 /* for -S */
@@ -65,6 +69,18 @@
 extern bool nondeterministic_parser;
 
 
+/* --language.  */
+struct bison_language
+{
+  const char *language;
+  const char *skeleton;
+  const char *src_extension;
+  const char *header_extension;
+  bool add_tab;
+};
+
+extern const struct bison_language *language;
+
 /*-----------.
 | --report.  |
 `-----------*/
@@ -125,4 +141,8 @@
  */
 void getargs (int argc, char *argv[]);
 
+/* Used by parse-gram.y.  */
+void language_argmatch (char *arg, int prio, location *loc);
+void skeleton_arg (char *arg, int prio, location *loc);
+
 #endif /* !GETARGS_H_ */
Index: src/output.c
===================================================================
RCS file: /sources/bison/bison/src/output.c,v
retrieving revision 1.257
diff -u -r1.257 output.c
--- src/output.c        8 Oct 2006 11:07:02 -0000       1.257
+++ src/output.c        9 Oct 2006 07:28:49 -0000
@@ -612,6 +612,7 @@
   DEFINE (spec_name_prefix);
   DEFINE (spec_outfile);
   DEFINE (spec_verbose_file);
+  DEFINE (program_name);
 #undef DEFINE
 
   /* User Code.  */
@@ -620,20 +621,16 @@
   muscle_insert ("pre_prologue", obstack_finish (&pre_prologue_obstack));
   muscle_insert ("post_prologue", obstack_finish (&post_prologue_obstack));
 
-  /* Find the right skeleton file.  */
-  if (!skeleton)
-    {
-      if (glr_parser || nondeterministic_parser)
-       skeleton = "glr.c";
-      else
-       skeleton = "yacc.c";
-    }
+  /* Find the right skeleton file, and add muscles about the skeletons  */
+  if (skeleton)
+    MUSCLE_INSERT_C_STRING ("skeleton", skeleton);
+  else
+    skeleton = language->skeleton;
 
-  /* About the skeletons. */
+  /* About the skeletons.  */
   {
     char const *pkgdatadir = getenv ("BISON_PKGDATADIR");
     MUSCLE_INSERT_STRING ("pkgdatadir", pkgdatadir ? pkgdatadir : PKGDATADIR);
-    MUSCLE_INSERT_C_STRING ("skeleton", skeleton);
   }
 }
 
Index: src/parse-gram.y
===================================================================
RCS file: /sources/bison/bison/src/parse-gram.y,v
retrieving revision 1.92
diff -u -r1.92 parse-gram.y
--- src/parse-gram.y    15 Sep 2006 16:34:48 -0000      1.92
+++ src/parse-gram.y    9 Oct 2006 07:28:53 -0000
@@ -146,6 +146,7 @@
   PERCENT_FILE_PREFIX     "%file-prefix"
   PERCENT_GLR_PARSER      "%glr-parser"
   PERCENT_INITIAL_ACTION  "%initial-action"
+  PERCENT_LANGUAGE        "%language"
   PERCENT_LEX_PARAM       "%lex-param"
   PERCENT_LOCATIONS       "%locations"
   PERCENT_NAME_PREFIX     "%name-prefix"
@@ -241,6 +242,7 @@
     {
       muscle_code_grow ("initial_action", translate_symbol_action ($2, @2), 
@2);
     }
+| "%language" STRING           { language_argmatch ($2, 1, &@1); }
 | "%lex-param" "{...}"         { add_param ("lex_param", $2, @2); }
 | "%locations"                  { locations_flag = true; }
 | "%name-prefix" "=" STRING     { spec_name_prefix = $3; }
@@ -251,7 +253,7 @@
 | "%pure-parser"                { pure_parser = true; }
 | "%push-parser"                { push_parser = true; }
 | "%require" STRING             { version_check (&@2, $2); }
-| "%skeleton" STRING            { skeleton = $2; }
+| "%skeleton" STRING            { skeleton_arg ($2, 1, &@1); }
 | "%start-header" braceless     { muscle_code_grow ("start_header", $2, @2); }
 | "%token-table"                { token_table_flag = true; }
 | "%verbose"                    { report_flag = report_states; }
Index: src/scan-gram.l
===================================================================
RCS file: /sources/bison/bison/src/scan-gram.l,v
retrieving revision 1.103
diff -u -r1.103 scan-gram.l
--- src/scan-gram.l     15 Sep 2006 15:56:26 -0000      1.103
+++ src/scan-gram.l     9 Oct 2006 07:28:56 -0000
@@ -173,6 +173,7 @@
   "%fixed"[-_]"output"[-_]"files"   return PERCENT_YACC;
   "%initial-action"                return PERCENT_INITIAL_ACTION;
   "%glr-parser"                    return PERCENT_GLR_PARSER;
+  "%language"                      return PERCENT_LANGUAGE;
   "%left"                          return PERCENT_LEFT;
   "%lex-param"                     return PERCENT_LEX_PARAM;
   "%locations"                     return PERCENT_LOCATIONS;
Index: tests/calc.at
===================================================================
RCS file: /sources/bison/bison/tests/calc.at,v
retrieving revision 1.92
diff -u -r1.92 calc.at
--- tests/calc.at       15 Sep 2006 15:56:26 -0000      1.92
+++ tests/calc.at       9 Oct 2006 07:28:56 -0000
@@ -617,12 +617,15 @@
 
 AT_BANNER([[Simple LALR(1) C++ Calculator.]])
 
+# First let's try using %skeleton
+AT_CHECK_CALC([%skeleton "lalr1.cc" %defines %locations])
+
 # AT_CHECK_CALC_LALR1_CC([BISON-OPTIONS])
 # ---------------------------------------
 # Start a testing chunk which compiles `calc' grammar with
 # the C++ skeleton, and performs several tests over the parser.
 m4_define([AT_CHECK_CALC_LALR1_CC],
-[AT_CHECK_CALC([%skeleton "lalr1.cc" %defines %locations] $@)])
+[AT_CHECK_CALC([%language "C++" %defines %locations] $@)])
 
 AT_CHECK_CALC_LALR1_CC([])
 AT_CHECK_CALC_LALR1_CC([%error-verbose %name-prefix="calc" %verbose %yacc])
@@ -641,12 +644,15 @@
 
 AT_BANNER([[Simple GLR C++ Calculator.]])
 
+# Again, we try also using %skeleton.
+AT_CHECK_CALC([%skeleton "glr.cc" %defines %locations])
+
 # AT_CHECK_CALC_GLR_CC([BISON-OPTIONS])
 # -------------------------------------
 # Start a testing chunk which compiles `calc' grammar with
 # the GLR C++ skeleton, and performs several tests over the parser.
 m4_define([AT_CHECK_CALC_GLR_CC],
-[AT_CHECK_CALC([%skeleton "glr.cc" %defines %locations] $@)])
+[AT_CHECK_CALC([%language "C++" %glr-parser %defines %locations] $@)])
 
 AT_CHECK_CALC_GLR_CC([])
 AT_CHECK_CALC_GLR_CC([%error-verbose %name-prefix="calc" %verbose %yacc])
Index: tests/local.at
===================================================================
RCS file: /sources/bison/bison/tests/local.at,v
retrieving revision 1.16
diff -u -r1.16 local.at
--- tests/local.at      12 Mar 2006 15:26:05 -0000      1.16
+++ tests/local.at      9 Oct 2006 07:28:56 -0000
@@ -41,17 +41,17 @@
 m4_define([_AT_BISON_OPTION_PUSHDEFS],
 [m4_if([$1$2], $[1]$[2], [],
        [m4_fatal([$0: Invalid arguments: address@hidden)])dnl
-m4_pushdef([AT_LALR1_CC_IF],
-[m4_bmatch([$3], ["lalr1.cc"], [$1], [$2])])
-m4_pushdef([AT_GLR_CC_IF],
-[m4_bmatch([$3], ["glr.cc"], [$1], [$2])])
 m4_pushdef([AT_SKEL_CC_IF],
-[m4_bmatch([$3], ["\(glr\|lalr1\).cc"], [$1], [$2])])
+[m4_bmatch([$3], [%language "[Cc]\+\+"\|%skeleton "[a-z0-9]+\.cc"], [$1], 
[$2])])
 m4_pushdef([AT_GLR_IF],
-[m4_bmatch([$3], [%glr-parser], [$1], [$2])])
+[m4_bmatch([$3], [%glr-parser\|%skeleton "glr\.], [$1], [$2])])
+m4_pushdef([AT_LALR1_CC_IF],
+[AT_SKEL_CC_IF([AT_GLR_IF([$2], [$1])], [$2])])
+m4_pushdef([AT_GLR_CC_IF],
+[AT_SKEL_CC_IF([AT_GLR_IF([$1], [$2])], [$2])])
 # Using yacc.c?
 m4_pushdef([AT_YACC_IF],
-[m4_bmatch([$3], [%glr-parser\|%skeleton], [$2], [$1])])
+[m4_bmatch([$3], [%language\|%glr-parser\|%skeleton], [$2], [$1])])
 m4_pushdef([AT_PARAM_IF],
 [m4_bmatch([$3], [%parse-param], [$1], [$2])])
 m4_pushdef([AT_LOCATION_IF],

reply via email to

[Prev in Thread] Current Thread [Next in Thread]