Rewrite to simplify the logic.
(language_argmatch): Likewise.
* doc/bison.texinfo (Decl Summary, Bison Options): Don't claim
Java is supported.
* src/complain.c (program_name): Remove decl; no longer needed.
* src/main.c (program_name): Remove; now belongs to getargs.
2006-12-18 Paolo Bonzini <bonzini@gnu.org>
* NEWS: Document %language.
* data/Makefile.am (dist_pkgdata_DATA): Add c-skel.m4, c++-skel.m4.
* data/c-skel.m4, data/c++-skel.m4: New files.
* data/glr.c: Complain on push parsers.
* doc/bison.texinfo (C++ Parser Interface): Prefer %language
over %skeleton.
(Directives): Document %language and %skeleton.
(Command line): Document -L.
* examples/extexi: Rewrite %require directive.
* examples/calc++/Makefile.am: Pass VERSION to extexi.
* src/files.c (compute_exts_from_gc): Look in language structure
for .y extension.
(compute_file_name_parts): Check whether .tab should be added.
* src/getargs.c (valid_languages, skeleton_prio, language_prio):
(language, skeleton_arg, language_argmatch): New.
(long_options): Add --language.
(getargs): Use skeleton_arg, add -L/--language.
* src/getargs.h: Include location.h.
(struct bison_language, language, skeleton_arg, language_argmatch): New.
* src/output.c (prepare): Pick default skeleton from struct language.
Don't dispatch C skeletons here.
* src/parse-gram.y (PERCENT_LANGUAGE): New.
(prologue_declaration): Add "%language" rule, use skeleton_arg.
* src/scan-gram.l ("%language"): New rule.
* tests/calc.at: Test %skeleton and %language.
* tests/local.at (AT_SKEL_CC_IF): Look for %language.
(AT_GLR_IF): Look for %skeleton "glr.cc".
(AT_LALR1_CC_IF, AT_GLR_CC_IF): Rewrite.
(AT_YACC_IF): Reject %language.
2006-12-18 Paul Eggert <eggert@cs.ucla.edu>
+2006-12-18 Paul Eggert <eggert@cs.ucla.edu>
+
+ * src/getargs.c (skeleton_arg): Last arg is now location const *.
+ Rewrite to simplify the logic.
+ (language_argmatch): Likewise.
+
+ * doc/bison.texinfo (Decl Summary, Bison Options): Don't claim
+ Java is supported.
+ * src/complain.c (program_name): Remove decl; no longer needed.
+ * src/main.c (program_name): Remove; now belongs to getargs.
+
+2006-12-18 Paolo Bonzini <bonzini@gnu.org>
+
+ * NEWS: Document %language.
+
+ * data/Makefile.am (dist_pkgdata_DATA): Add c-skel.m4, c++-skel.m4.
+
+ * data/c-skel.m4, data/c++-skel.m4: New files.
+ * data/glr.c: Complain on push parsers.
+
+ * doc/bison.texinfo (C++ Parser Interface): Prefer %language
+ over %skeleton.
+ (Directives): Document %language and %skeleton.
+ (Command line): Document -L.
+
+ * examples/extexi: Rewrite %require directive.
+ * examples/calc++/Makefile.am: Pass VERSION to extexi.
+
+ * src/files.c (compute_exts_from_gc): Look in language structure
+ for .y extension.
+ (compute_file_name_parts): Check whether .tab should be added.
+ * src/getargs.c (valid_languages, skeleton_prio, language_prio):
+ (language, skeleton_arg, language_argmatch): New.
+ (long_options): Add --language.
+ (getargs): Use skeleton_arg, add -L/--language.
+ * src/getargs.h: Include location.h.
+ (struct bison_language, language, skeleton_arg, language_argmatch): New.
+ * src/output.c (prepare): Pick default skeleton from struct language.
+ Don't dispatch C skeletons here.
+ * src/parse-gram.y (PERCENT_LANGUAGE): New.
+ (prologue_declaration): Add "%language" rule, use skeleton_arg.
+ * src/scan-gram.l ("%language"): New rule.
+
+ * tests/calc.at: Test %skeleton and %language.
+ * tests/local.at (AT_SKEL_CC_IF): Look for %language.
+ (AT_GLR_IF): Look for %skeleton "glr.cc".
+ (AT_LALR1_CC_IF, AT_GLR_CC_IF): Rewrite.
+ (AT_YACC_IF): Reject %language.
+
2006-12-18 Paul Eggert <eggert@cs.ucla.edu>
* src/symtab.h (struct semantic_type): Remove the tag 'semantic_type',
* The -g and --graph options now output graphs in Graphviz DOT format,
not VCG format.
+* An experimental directive %language specifies the language of the
+ generated parser, which can be C (the default) or C++. This
+ directive affects the skeleton used, and the names of the generated
+ files if the grammar file's name ends in ".y".
+
* The grammar file may now specify the name of the parser header file using
%defines. For example:
- `%start-header {CODE}', which only Bison 2.3a supported.
3. %provides {CODE}
-
+
This is the right place to write additional definitions you would like
Bison to expose externally. That is, this directive inserts your CODE
both into the parser header file and into the parser code file after
## 02110-1301 USA
dist_pkgdata_DATA = README bison.m4 \
- c.m4 yacc.c glr.c push.c \
- c++.m4 location.cc lalr1.cc glr.cc
+ c-skel.m4 c.m4 yacc.c glr.c push.c \
+ c++-skel.m4 c++.m4 location.cc lalr1.cc glr.cc
m4sugardir = $(pkgdatadir)/m4sugar
dist_m4sugar_DATA = m4sugar/m4sugar.m4
--- /dev/null
+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)
--- /dev/null
+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_push_if( [m4_define([b4_used_skeleton], [b4_pkgdatadir/[push.c]])])
+b4_glr_if( [m4_define([b4_used_skeleton], [b4_pkgdatadir/[glr.c]])])
+b4_nondeterministic_if([m4_define([b4_used_skeleton], [b4_pkgdatadir/[glr.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)
m4_include(b4_pkgdatadir/[c.m4])
+b4_push_if([
+m4_fatal([Non-deterministic push parsers are not yet supported])])
+
## ---------------- ##
## Default values. ##
## ---------------- ##
chosen as if the input file were named @file{@var{prefix}.y}.
@end deffn
+@deffn {Directive} %language="@var{language}"
+Specify the programming language for the generated parser. Currently
+supported languages include C and C++.
+@end deffn
+
@deffn {Directive} %locations
Generate the code processing the locations (@pxref{Action Features,
,Special Features for Use in Actions}). This mode is enabled as soon as
Require a Version of Bison}.
@end deffn
+@deffn {Directive} %skeleton "@var{file}"
+Specify the skeleton to use. You probably don't need this option unless
+you are developing Bison.
+@end deffn
+
@deffn {Directive} %token-table
Generate an array of token names in the parser file. The name of the
array is @code{yytname}; @code{yytname[@var{i}]} is the name of the
@table @option
@item -S @var{file}
@itemx --skeleton=@var{file}
-Specify the skeleton to use. You probably don't need this option unless
-you are developing Bison.
+Specify the skeleton to use, as if @code{%skeleton} was specified
+(@pxref{Decl Summary, , Bison Declaration Summary}). You probably
+don't need this option unless you are developing Bison.
@item -t
@itemx --debug
already defined, so that the debugging facilities are compiled.
@xref{Tracing, ,Tracing Your Parser}.
+@item -L @var{language}
+@itemx --language=@var{language}
+Specify the programming language for the generated parser, as if
+@code{%language} was specified (@pxref{Decl Summary, , Bison Declaration
+Summary}). Currently supported languages include C and C++.
+
@item --locations
Pretend that @code{%locations} was specified. @xref{Decl Summary}.
@node C++ Bison Interface
@subsection C++ Bison Interface
-@c - %skeleton "lalr1.cc"
+@c - %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}
-to Bison, or include the directive @samp{%skeleton "lalr1.cc"} in the
-grammar preamble. When run, @command{bison} will create several
+The C++ parser @acronym{LALR}(1) skeleton is selected using a
+language directive, @samp{%language "C++"}, or the synonymous
+command-line option @option{--language=c++}@footnote{For both
+the grammar directive and the command-line option, the
+language name is case-insensitive}. These were introduced
+in Bison 2.3b; for compatibility with earlier versions, you
+may also pass the option @option{--skeleton=lalr1.cc} to Bison
+or include the directive @samp{%skeleton "lalr1.cc"} in the
+grammar preamble. Specifying the language is however preferred,
+because it is clearer and because it will automatically choose the
+correct skeleton for @acronym{GLR} parsers (the C++ @acronym{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:
@comment file: calc++-parser.yy
@example
-%skeleton "lalr1.cc" /* -*- C++ -*- */
-%require "2.1a"
+%language "C++" /* -*- C++ -*- */
+%require "2.3b"
%defines
%define "parser_class_name" "calcxx_parser"
@end example
# Extract in src.
$(calc_extracted): $(doc) $(extexi)
cd $(srcdir) && \
- $(AWK) -f ../extexi ../../doc/bison.texinfo -- \
- calc++-parser.yy \
+ $(AWK) -f ../extexi -v VERSION="@VERSION@" \
+ ../../doc/bison.texinfo -- calc++-parser.yy \
calc++-scanner.ll calc++.cc calc++-driver.hh calc++-driver.cc
else
line = "";
+ gsub (/^%require "[^"]*"$/, "%require \"" VERSION "\"", line);
gsub (/^@result\{\}/, "", line);
gsub (/^@error\{\}/, "", line);
gsub ("@[{]", "{", line);
#include "files.h"
#include "getargs.h"
-/* The calling program should define program_name and set it to the
- name of the executing program. */
-extern char *program_name;
-
bool complaint_issued;
\f
static void
compute_exts_from_gf (const char *ext)
{
- src_extension = xstrdup (ext);
- header_extension = xstrdup (ext);
- tr (src_extension, 'y', 'c');
- tr (src_extension, 'Y', 'C');
- tr (header_extension, 'y', 'h');
- tr (header_extension, 'Y', 'H');
+ if (strcmp (ext, ".y") == 0)
+ {
+ src_extension = xstrdup (language->src_extension);
+ header_extension = xstrdup (language->header_extension);
+ }
+ else
+ {
+ src_extension = xstrdup (ext);
+ header_extension = xstrdup (ext);
+ tr (src_extension, 'y', 'c');
+ tr (src_extension, 'Y', 'C');
+ tr (header_extension, 'y', 'h');
+ tr (header_extension, 'Y', 'H');
+ }
}
/* Compute extensions from the given c source file extension. */
xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0)));
}
- all_but_ext = concat2 (all_but_tab_ext, TAB_EXT);
+ if (language->add_tab)
+ all_but_ext = concat2 (all_but_tab_ext, TAB_EXT);
+ else
+ all_but_ext = xstrdup (all_but_tab_ext);
/* Compute the extensions from the grammar file name. */
if (ext && !yacc_flag)
int trace_flag = trace_none;
int warnings_flag = warnings_none;
+static struct bison_language const valid_languages[] = {
+ { "c", "c-skel.m4", ".c", ".h", true },
+ { "c++", "c++-skel.m4", ".cc", ".hh", true },
+ { "", "", "", "", false }
+};
+
+static int skeleton_prio = 2;
const char *skeleton = NULL;
+static int language_prio = 2;
+struct bison_language const *language = &valid_languages[0];
const char *include = NULL;
-extern char *program_name;
+char *program_name;
/** Decode an option's set of keys.
}
+/*-------------------------------------.
+| --skeleton and --language handling. |
+`--------------------------------------*/
+
+void
+skeleton_arg (char const *arg, int prio, location const *loc)
+{
+ if (prio < skeleton_prio)
+ {
+ skeleton_prio = prio;
+ skeleton = arg;
+ }
+ else if (prio == skeleton_prio)
+ {
+ char const *msg =
+ _("multiple skeleton declarations are invalid");
+ if (loc)
+ complain_at (*loc, msg);
+ else
+ complain (msg);
+ }
+}
+
+void
+language_argmatch (char const *arg, int prio, location const *loc)
+{
+ char const *msg;
+
+ if (prio < language_prio)
+ {
+ int i;
+ for (i = 0; valid_languages[i].language[0]; i++)
+ if (strcasecmp (arg, valid_languages[i].language) == 0)
+ {
+ language_prio = prio;
+ language = &valid_languages[i];
+ return;
+ }
+ msg = _("invalid language `%s'");
+ }
+ else if (language_prio == prio)
+ msg = _("multiple language declarations are invalid");
+ else
+ return;
+
+ if (loc)
+ complain_at (*loc, msg, arg);
+ else
+ complain (msg, arg);
+}
+
/*----------------------.
| 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
{ "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}
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':
#ifndef GETARGS_H_
# define GETARGS_H_
+#include "location.h"
+
+extern char *program_name;
+
/* flags set by % directives */
/* for -S */
extern bool nondeterministic_parser;
+/* --language. */
+struct bison_language
+{
+ char language[sizeof "c++"];
+ char skeleton[sizeof "c++-skel.m4"];
+ char src_extension[sizeof ".cc"];
+ char header_extension[sizeof ".hh"];
+ bool add_tab;
+};
+
+extern struct bison_language const *language;
+
/*-----------.
| --report. |
`-----------*/
*/
void getargs (int argc, char *argv[]);
+/* Used by parse-gram.y. */
+void language_argmatch (char const *arg, int prio, location const *loc);
+void skeleton_arg (const char *arg, int prio, location const *loc);
+
#endif /* !GETARGS_H_ */
#include "tables.h"
#include "uniqstr.h"
-/* The name this program was run with, for messages. */
-char *program_name;
-
int
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");
/* b4_pkgdatadir is used inside m4_include in the skeletons, so digraphs
his Bison installation path. */
MUSCLE_INSERT_STRING_RAW ("pkgdatadir",
pkgdatadir ? pkgdatadir : PKGDATADIR);
- MUSCLE_INSERT_C_STRING ("skeleton", skeleton);
}
}
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"
{
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 = $2; }
| "%pure-parser" { pure_parser = true; }
| "%push-parser" { push_parser = true; pure_parser = true; }
| "%require" STRING { version_check (&@2, $2); }
-| "%skeleton" STRING { skeleton = $2; }
+| "%skeleton" STRING { skeleton_arg ($2, 1, &@1); }
| "%token-table" { token_table_flag = true; }
| "%verbose" { report_flag = report_states; }
| "%yacc" { yacc_flag = true; }
"%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;
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])
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])
m4_define([_AT_BISON_OPTION_PUSHDEFS],
[m4_if([$1$2], $[1]$[2], [],
[m4_fatal([$0: Invalid arguments: $@])])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],