* Noteworthy changes in release ?.? (????-??-??) [?]
+** Warnings about undeclared symbols
+
+ Bison used to raise an error for %printer and %destructor directives for
+ undefined symbols.
+
+ %printer {} symbol1
+ %destructor {} symbol2
+ %%
+ exp: "a";
+
+ This is now only a warning.
+
+** Additional yylex/yyparse arguments
+
+ The new directive %param declares additional arguments to both yylex and
+ yyparse. The %lex-param, %parse-param, and %param directives support one
+ or more arguments. Instead of
+
+ %lex-param {arg1_type *arg1}
+ %lex-param {arg2_type *arg2}
+ %parse-param {arg1_type *arg1}
+ %parse-param {arg2_type *arg2}
+
+ one may now declare
+
+ %param {arg1_type *arg1} {arg2_type *arg2}
+
+** Java skeleton improvements
+
+ The constants for token names were moved to the Lexer interface.
+ Also, it is possible to add code to the parser's constructors using
+ "%code init" and "%define init_throws".
+
+** C++ skeleton improvements
+
+ The C++ parser features a syntax_error exception, which can be
+ thrown from the scanner or from user rules to raise syntax errors.
+ This facilitates reporting errors caught in sub-functions (e.g.,
+ rejecting too large integral literals from a conversion function
+ used by the scanner, or rejecting invalid combinations from a
+ factory invoked by the user actions).
+
+** Variable api.tokens.prefix
+
+ The variable api.tokens.prefix changes the way tokens are identified in
+ the generated files. This is especially useful to avoid collisions
+ with identifiers in the target language. For instance
+
+ %token FILE for ERROR
+ %define api.tokens.prefix "TOK_"
+ %%
+ start: FILE for ERROR;
+
+ will generate the definition of the symbols TOK_FILE, TOK_for, and
+ TOK_ERROR in the generated sources. In particular, the scanner must
+ use these prefixed token names, although the grammar itself still
+ uses the short names (as in the sample rule given above).
+
+** Variable api.namespace
+
+ The "namespace" variable is renamed "api.namespace". Backward
+ compatibility is ensured, but upgrading is recommended.
+
+** Variable parse.error
+
+ The variable error controls the verbosity of error messages. The
+ use of the %error-verbose directive is deprecated in favor of
+ %define parse.error "verbose".
+
+** Semantic predicates
+
+ The new, experimental, semantic-predicate feature allows actions of
+ the form %?{ BOOLEAN-EXPRESSION }, which cause syntax errors (as for
+ YYERROR) if the expression evaluates to 0, and are evaluated immediately
+ in GLR parsers, rather than being deferred. The result is that they
+ allow the programmer to prune possible parses based on the values of
+ runtime expressions.
+
+* Noteworthy changes in release ?.? (????-??-??) [?]
+
** Future changes:
The next major release will drop support for generating parsers in K&R C,
- and remove the definition of yystype (removal announced since Bison
- 1.875).
+ and remove the definitions of yystype and yyltype (removal announced since
+ Bison 1.875). YYPARSE_PARAM and YYLEX_PARAM, which were deprecated in
+ favor of %parse-param and %lex-param (introduced in Bison 1.875 too), will
+ no longer be supported.
** The generated header is included (yacc.c)
The header files such as "parser.hh", "location.hh", etc. used a constant
name for preprocessor guards, for instance:
- #ifndef BISON_LOCATION_HH
- # define BISON_LOCATION_HH
- ...
- #endif // !BISON_LOCATION_HH
+ #ifndef BISON_LOCATION_HH
+ # define BISON_LOCATION_HH
+ ...
+ #endif // !BISON_LOCATION_HH
The inclusion guard is now computed from "PREFIX/FILE-NAME", where lower
case characters are converted to upper case, and series of
With "bison -o lang++/parser.cc", "location.hh" would now include:
- #ifndef YY_LANG_LOCATION_HH
- # define YY_LANG_LOCATION_HH
- ...
- #endif // !YY_LANG_LOCATION_HH
+ #ifndef YY_LANG_LOCATION_HH
+ # define YY_LANG_LOCATION_HH
+ ...
+ #endif // !YY_LANG_LOCATION_HH
*** C++ locations:
to use it. If, for instance, your location structure has "first"
and "last" members, instead of
- # define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (N) \
- { \
- (Current).first = (Rhs)[1].location.first; \
- (Current).last = (Rhs)[N].location.last; \
- } \
- else \
- { \
- (Current).first = (Current).last = (Rhs)[0].location.last; \
- } \
- while (false)
+ # define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (N) \
+ { \
+ (Current).first = (Rhs)[1].location.first; \
+ (Current).last = (Rhs)[N].location.last; \
+ } \
+ else \
+ { \
+ (Current).first = (Current).last = (Rhs)[0].location.last; \
+ } \
+ while (false)
use:
- # define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (N) \
- { \
- (Current).first = YYRHSLOC (Rhs, 1).first; \
- (Current).last = YYRHSLOC (Rhs, N).last; \
- } \
- else \
- { \
- (Current).first = (Current).last = YYRHSLOC (Rhs, 0).last; \
- } \
- while (false)
+ # define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (N) \
+ { \
+ (Current).first = YYRHSLOC (Rhs, 1).first; \
+ (Current).last = YYRHSLOC (Rhs, N).last; \
+ } \
+ else \
+ { \
+ (Current).first = (Current).last = YYRHSLOC (Rhs, 0).last; \
+ } \
+ while (false)
** YYLLOC_DEFAULT in C++:
- "parsing stack overflow..." -> "parser stack overflow"
GLR parsers now report "parser stack overflow" as per the Bison manual.
+ ** %parse-param and %lex-param
+ The macros YYPARSE_PARAM and YYLEX_PARAM provide a means to pass
+ additional context to yyparse and yylex. They suffer from several
+ shortcomings:
+
+ - a single argument only can be added,
+ - their types are weak (void *),
+ - this context is not passed to anciliary functions such as yyerror,
+ - only yacc.c parsers support them.
+
+ The new %parse-param/%lex-param directives provide a more precise control.
+ For instance:
+
+ %parse-param {int *nastiness}
+ %lex-param {int *nastiness}
+ %parse-param {int *randomness}
+
+ results in the following signatures:
+
+ int yylex (int *nastiness);
+ int yyparse (int *nastiness, int *randomness);
+
+ or, if both %pure-parser and %locations are used:
+
+ int yylex (YYSTYPE *lvalp, YYLTYPE *llocp, int *nastiness);
+ int yyparse (int *nastiness, int *randomness);
+
** Bison now warns if it detects conflicting outputs to the same file,
e.g., it generates a warning for "bison -d -o foo.h foo.y" since
that command outputs both code and header to foo.h.
** Incorrect "Token not used"
On a grammar such as
- %token useless useful
- %%
- exp: '0' %prec useful;
+ %token useless useful
+ %%
+ exp: '0' %prec useful;
where a token was used to set the precedence of the last rule,
bison reported both "useful" and "useless" as useless tokens.
the user symbol is used in the reports, the graphs, and the verbose
error messages instead of "$end", which remains being the default.
For instance
- %token MYEOF 0
+ %token MYEOF 0
or
- %token MYEOF 0 "end of file"
+ %token MYEOF 0 "end of file"
** Semantic parser
This old option, which has been broken for ages, is removed.
Previous versions don't complain when there is a type clash on
the default action if the rule has a mid-rule action, such as in:
- %type <foo> bar
- %%
- bar: '0' {} '0';
+ %type <foo> bar
+ %%
+ bar: '0' {} '0';
This is fixed.
## Identification. ##
## ---------------- ##
-# b4_comment(TEXT)
-# ----------------
-m4_define([b4_comment], [/* m4_bpatsubst([$1], [
-], [
- ]) */])
+# b4_comment_(TEXT, OPEN, CONTINUE, END)
+# -------------------------------------
+# Put TEXT in comment. Avoid trailing spaces: don't indent empty lines.
+# Avoid adding indentation to the first line, as the indentation comes
+# from OPEN. That's why we don't patsubst([$1], [^\(.\)], [ \1]).
+#
+# Prefix all the output lines with PREFIX.
+m4_define([b4_comment_], [$2[]m4_bpatsubst([$1], [
+\(.\)], [
+$3\1])$4])
+
+
+# b4_c_comment(TEXT, [PREFIX])
+# ----------------------------
+# Put TEXT in comment. Avoid trailing spaces: don't indent empty lines.
+# Avoid adding indentation to the first line, as the indentation comes
+# from "/*". That's why we don't patsubst([$1], [^\(.\)], [ \1]).
+#
+# Prefix all the output lines with PREFIX.
+m4_define([b4_c_comment],
+[b4_comment_([$1], [$2/* ], [$2 ], [$2 */])])
+
+
+# b4_comment(TEXT, [PREFIX])
+# --------------------------
+# By default, C comments.
+m4_define([b4_comment], [b4_c_comment($@)])
+
# b4_identification
# -----------------
#define YYPULL ]b4_pull_flag])[
/* Using locations. */
-#define YYLSP_NEEDED ]b4_locations_flag[
+#define YYLSP_NEEDED ]b4_locations_if([1], [0])[
]])
m4_popdef([$1])dnl
])])
-# b4_parse_param_use
-# ------------------
-# `YYUSE' all the parse-params.
+# b4_parse_param_use([VAL], [LOC])
+# --------------------------------
+# `YYUSE' VAL, LOC if locations are enabled, and all the parse-params.
m4_define([b4_parse_param_use],
-[b4_parse_param_for([Decl], [Formal], [ YYUSE (Formal);
+[m4_ifvaln([$1], [ YYUSE([$1]);])dnl
+b4_locations_if([m4_ifvaln([$2], [ YYUSE ([$2]);])])dnl
+b4_parse_param_for([Decl], [Formal], [ YYUSE (Formal);
])dnl
])
m4_eval([0 <= $1]), [1], [unsigned int],
- [int])])
+ [int])])
# b4_int_type_for(NAME)
# Return a null pointer constant.
m4_define([b4_null], [YY_NULL])
+# b4_integral_parser_table_define(TABLE-NAME, CONTENT, COMMENT)
+# -------------------------------------------------------------
+# Define "yy<TABLE-NAME>" which contents is CONTENT.
+m4_define([b4_integral_parser_table_define],
+[m4_ifvaln([$3], [b4_c_comment([$3], [ ])])dnl
+static const b4_int_type_for([$2]) yy$1[[]] =
+{
+ $2
+};dnl
+])
## ------------------------- ##
# -----------------------------------------
# Output the definition of this token as #define.
m4_define([b4_token_define],
-[#define $1 $2
+[#define b4_percent_define_get([api.tokens.prefix])$1 $2
])
# ---------------------------------------
# Output the definition of this token as an enum.
m4_define([b4_token_enum],
-[$1 = $2])
+[b4_percent_define_get([api.tokens.prefix])$1 = $2])
# b4_token_enums(LIST-OF-PAIRS-TOKEN-NAME-TOKEN-NUMBER)
enum yytokentype {
m4_map_sep([ b4_token_enum], [,
],
- [$@])
+ [$@])
};
#endif
])])
])
+## ----------------- ##
+## Semantic Values. ##
+## ----------------- ##
+
+
+# b4_symbol_value(VAL, [TYPE])
+# ----------------------------
+# Given a semantic value VAL ($$, $1 etc.), extract its value of type
+# TYPE if TYPE is given, otherwise just return VAL. The result can be
+# used safetly, it is put in parens to avoid nasty precedence issues.
+# TYPE is *not* put in braces, provide some if needed.
+m4_define([b4_symbol_value],
+[($1[]m4_ifval([$2], [.$2]))])
+
+
## --------------------------------------------- ##
## Defining C functions in both K&R and ANSI-C. ##
m4_define([b4_c_ansi_formals],
[m4_if([$#], [0], [void],
[$#$1], [1], [void],
- [m4_map_sep([b4_c_ansi_formal], [, ], [$@])])])
+ [m4_map_sep([b4_c_ansi_formal], [, ], [$@])])])
m4_define([b4_c_ansi_formal],
[$1])
# Output the K&R argument declarations.
m4_define([b4_c_knr_formal_decls],
[m4_map_sep([b4_c_knr_formal_decl],
- [
+ [
],
- [$@])])
+ [$@])])
m4_define([b4_c_knr_formal_decl],
[ $1;])
# -----------------------------------------------------------
# Declare the function NAME.
m4_define([b4_c_function_decl],
-[#if defined __STDC__ || defined __cplusplus
+[#if b4_c_modern
b4_c_ansi_function_decl($@)
#else
$2 $1 ();
m4_define([b4_case],
[ case $1:
$2
+b4_syncline([@oline@], [@ofile@])
break;])
-# b4_symbol_actions(FILENAME, LINENO,
-# SYMBOL-TAG, SYMBOL-NUM,
-# SYMBOL-ACTION, SYMBOL-TYPENAME)
-# -------------------------------------------------
-m4_define([b4_symbol_actions],
-[m4_pushdef([b4_dollar_dollar],
- [m4_ifval([$6], [(yyvaluep->$6)], [(*yyvaluep)])])dnl
-m4_pushdef([b4_at_dollar], [(*yylocationp)])dnl
- case $4: /* $3 */
-b4_syncline([$2], [$1])
- $5;
+
+# b4_predicate_case(LABEL, CONDITIONS)
+# ------------------------------------
+m4_define([b4_predicate_case],
+[ case $1:
+ if (! ($2)) YYERROR;
b4_syncline([@oline@], [@ofile@])
- break;
-m4_popdef([b4_at_dollar])dnl
-m4_popdef([b4_dollar_dollar])dnl
-])
+ break;])
# b4_yydestruct_generate(FUNCTION-DECLARATOR)
b4_locations_if( [, [[YYLTYPE *yylocationp], [yylocationp]]])[]dnl
m4_ifset([b4_parse_param], [, b4_parse_param]))[
{
- YYUSE (yyvaluep);
-]b4_locations_if([ YYUSE (yylocationp);
-])dnl
-b4_parse_param_use[]dnl
-[
- if (!yymsg)
+]b4_parse_param_use([yyvaluep], [yylocationp])dnl
+[ if (!yymsg)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
switch (yytype)
{
-]m4_map([b4_symbol_actions], m4_defn([b4_symbol_destructors]))[
- default:
- break;
+]b4_symbol_foreach([b4_symbol_destructor])dnl
+[ default:
+ break;
}
}]dnl
])
/*ARGSUSED*/
]$1([yy_symbol_value_print],
[static void],
- [[FILE *yyoutput], [yyoutput]],
- [[int yytype], [yytype]],
- [[YYSTYPE const * const yyvaluep], [yyvaluep]][]dnl
+ [[FILE *yyoutput], [yyoutput]],
+ [[int yytype], [yytype]],
+ [[YYSTYPE const * const yyvaluep], [yyvaluep]][]dnl
b4_locations_if([, [[YYLTYPE const * const yylocationp], [yylocationp]]])[]dnl
m4_ifset([b4_parse_param], [, b4_parse_param]))[
{
FILE *yyo = yyoutput;
- YYUSE (yyo);
- if (!yyvaluep)
- return;
-]b4_locations_if([ YYUSE (yylocationp);
-])dnl
-b4_parse_param_use[]dnl
-[# ifdef YYPRINT
+]b4_parse_param_use([yyo], [yylocationp])dnl
+[ if (!yyvaluep)
+ return;]
+dnl glr.c does not feature yytoknum.
+m4_if(b4_skeleton, ["yacc.c"],
+[[# ifdef YYPRINT
if (yytype < YYNTOKENS)
YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
- YYUSE (yyoutput);
# endif
- switch (yytype)
+]])dnl
+[ switch (yytype)
{
-]m4_map([b4_symbol_actions], m4_defn([b4_symbol_printers]))dnl
+]b4_symbol_foreach([b4_symbol_printer])dnl
[ default:
- break;
+ break;
}
}
]$1([yy_symbol_print],
[static void],
- [[FILE *yyoutput], [yyoutput]],
- [[int yytype], [yytype]],
- [[YYSTYPE const * const yyvaluep], [yyvaluep]][]dnl
+ [[FILE *yyoutput], [yyoutput]],
+ [[int yytype], [yytype]],
+ [[YYSTYPE const * const yyvaluep], [yyvaluep]][]dnl
b4_locations_if([, [[YYLTYPE const * const yylocationp], [yylocationp]]])[]dnl
m4_ifset([b4_parse_param], [, b4_parse_param]))[
{
# b4_declare_yylstype
# ------------------
- # Declaration that might either go into the header (if --defines)
- # or open coded in the parser body. Declare YYSTYPE and YYLTYPE.
+ # Declarations that might either go into the header (if --defines) or
+ # in the parser body. Declare YYSTYPE/YYLTYPE, and yylval/yylloc.
m4_define([b4_declare_yylstype],
[[#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
]m4_ifdef([b4_stype],
# define YYLTYPE_IS_DECLARED 1
# define YYLTYPE_IS_TRIVIAL 1
#endif]])
+
+ b4_pure_if([], [[extern YYSTYPE ]b4_prefix[lval;
+ ]b4_locations_if([[extern YYLTYPE ]b4_prefix[lloc;]])])[]dnl
])
# b4_declare_yydebug
m4_define([b4_declare_yydebug],
[[/* Enabling traces. */
#ifndef YYDEBUG
-# define YYDEBUG ]b4_debug_flag[
+# define YYDEBUG ]b4_parse_trace_if([1], [0])[
#endif
#if YYDEBUG
extern int ]b4_prefix[debug;
# --------------------
# Expansion of $<TYPE>$.
m4_define([b4_lhs_value],
-[((*yyvalp)[]m4_ifval([$1], [.$1]))])
+[b4_symbol_value([(*yyvalp)], [$1])])
+
+
+# b4_rhs_data(RULE-LENGTH, NUM)
+# -----------------------------
+# Expand to the semantic stack place that contains value and location
+# of symbol number NUM in a rule of length RULE-LENGTH.
+m4_define([b4_rhs_data],
+[((yyGLRStackItem const *)yyvsp)@{YYFILL (b4_subtract([$2], [$1]))@}.yystate])
# b4_rhs_value(RULE-LENGTH, NUM, [TYPE])
# Expansion of $<TYPE>NUM, where the current rule has RULE-LENGTH
# symbols on RHS.
m4_define([b4_rhs_value],
-[(((yyGLRStackItem const *)yyvsp)@{YYFILL (($2) - ($1))@}.yystate.yysemantics.yysval[]m4_ifval([$3], [.$3]))])
+[b4_symbol_value([b4_rhs_data([$1], [$2]).yysemantics.yysval], [$3])])
# Expansion of @NUM, where the current rule has RULE-LENGTH symbols
# on RHS.
m4_define([b4_rhs_location],
-[(((yyGLRStackItem const *)yyvsp)@{YYFILL (($2) - ($1))@}.yystate.yyloc)])
+[(b4_rhs_data([$1], [$2]).yyloc)])
## -------------- ##
]b4_identification
- b4_percent_code_get([[top]])[]dnl
- m4_if(b4_prefix, [yy], [],
- [/* Substitute the variable and function names. */
- #define yyparse b4_prefix[]parse
- #define yylex b4_prefix[]lex
- #define yyerror b4_prefix[]error
- #define yylval b4_prefix[]lval
- #define yychar b4_prefix[]char
- #define yydebug b4_prefix[]debug
- #define yynerrs b4_prefix[]nerrs
- #define yylloc b4_prefix[]lloc])[
+ b4_percent_code_get([[top]])[
+ ]m4_if(b4_prefix, [yy], [],
+ [[/* Substitute the variable and function names. */
+ #define yyparse ]b4_prefix[parse
+ #define yylex ]b4_prefix[lex
+ #define yyerror ]b4_prefix[error
+ #define yylval ]b4_prefix[lval
+ #define yychar ]b4_prefix[char
+ #define yydebug ]b4_prefix[debug
+ #define yynerrs ]b4_prefix[nerrs]b4_locations_if([[
+ #define yylloc ]b4_prefix[lloc]])])[
/* Copy the first part of user declarations. */
]b4_user_pre_prologue[
]b4_null_define[
]b4_defines_if([[#include "@basename(]b4_spec_defines_file[@)"]],
- [b4_shared_declarations])[
+ [b4_shared_declarations])[
/* Enabling verbose error messages. */
#ifdef YYERROR_VERBOSE
# undef YYERROR_VERBOSE
# define YYERROR_VERBOSE 1
#else
-# define YYERROR_VERBOSE ]b4_error_verbose_flag[
+# define YYERROR_VERBOSE ]b4_error_verbose_if([1], [0])[
#endif
/* Enabling the token table. */
};
#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const ]b4_int_type_for([b4_prhs])[ yyprhs[] =
-{
- ]b4_prhs[
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const ]b4_int_type_for([b4_rhs])[ yyrhs[] =
-{
- ]b4_rhs[
-};
-
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const ]b4_int_type_for([b4_rline])[ yyrline[] =
{
};
#endif
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const ]b4_int_type_for([b4_r1])[ yyr1[] =
-{
- ]b4_r1[
-};
+#define YYPACT_NINF ]b4_pact_ninf[
+#define YYTABLE_NINF ]b4_table_ninf[
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const ]b4_int_type_for([b4_r2])[ yyr2[] =
-{
- ]b4_r2[
-};
+]b4_parser_tables_define[
/* YYDPREC[RULE-NUM] -- Dynamic precedence of rule #RULE-NUM (0 if none). */
static const ]b4_int_type_for([b4_dprec])[ yydprec[] =
]b4_merger[
};
-/* YYDEFACT[S] -- default reduction number in state S. Performed when
- YYTABLE doesn't specify something else to do. Zero means the default
- is an error. */
-static const ]b4_int_type_for([b4_defact])[ yydefact[] =
+/* YYIMMEDIATE[RULE-NUM] -- True iff rule #RULE-NUM is not to be deferred, as
+ in the case of predicates. */
+static const yybool yyimmediate[] =
{
- ]b4_defact[
-};
-
-/* YYPDEFGOTO[NTERM-NUM]. */
-static const ]b4_int_type_for([b4_defgoto])[ yydefgoto[] =
-{
- ]b4_defgoto[
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF ]b4_pact_ninf[
-static const ]b4_int_type_for([b4_pact])[ yypact[] =
-{
- ]b4_pact[
-};
-
-/* YYPGOTO[NTERM-NUM]. */
-static const ]b4_int_type_for([b4_pgoto])[ yypgoto[] =
-{
- ]b4_pgoto[
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF ]b4_table_ninf[
-static const ]b4_int_type_for([b4_table])[ yytable[] =
-{
- ]b4_table[
+ ]b4_immediate[
};
/* YYCONFLP[YYPACT[STATE-NUM]] -- Pointer into YYCONFL of start of
{
]b4_conflicting_rules[
};
-
-static const ]b4_int_type_for([b4_check])[ yycheck[] =
-{
- ]b4_check[
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const ]b4_int_type_for([b4_stos])[ yystos[] =
-{
- ]b4_stos[
-};
-
\f
/* Error token number */
#define YYTERROR 1
typedef enum { yyok, yyaccept, yyabort, yyerr } YYRESULTTAG;
-#define YYCHK(YYE) \
- do { YYRESULTTAG yyflag = YYE; if (yyflag != yyok) return yyflag; } \
- while (YYID (0))
+#define YYCHK(YYE) \
+ do { \
+ YYRESULTTAG yychk_flag = YYE; \
+ if (yychk_flag != yyok) \
+ return yychk_flag; \
+ } while (YYID (0))
#if YYDEBUG
# endif
# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
-} while (YYID (0))
+ do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+ } while (YYID (0))
]b4_yy_symbol_print_generate([b4_c_ansi_function_def])[
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yy_symbol_print (stderr, Type, Value]b4_locuser_args([Location])[); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (YYID (0))
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+ do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, Type, Value]b4_locuser_args([Location])[); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+ } while (YYID (0))
/* Nonzero means print parse trace. It is left uninitialized so that
multiple parsers can coexist. */
#define YYHEADROOM 2
#ifndef YYSTACKEXPANDABLE
-# if (! defined __cplusplus \
- || (]b4_locations_if([[defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
- && ]])[defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))
# define YYSTACKEXPANDABLE 1
-# else
-# define YYSTACKEXPANDABLE 0
-# endif
#endif
#if YYSTACKEXPANDABLE
typedef int yyRuleNum;
/** Grammar symbol */
-typedef short int yySymbol;
+typedef int yySymbol;
/** Item references, as in LALR(1) machine */
typedef short int yyItemNum;
yyStateNum yylrState;
/** Preceding state in this stack */
yyGLRState* yypred;
- /** Source position of the first token produced by my symbol */
+ /** Source position of the last token produced by my symbol */
size_t yyposn;
union {
/** First in a chain of alternative reductions producing the
yyGLRState *s = yyvsp[yylow0].yystate.yypred;
for (i = yylow0-1; i >= yylow1; i -= 1)
{
- YYASSERT (s->yyresolved);
- yyvsp[i].yystate.yyresolved = yytrue;
- yyvsp[i].yystate.yysemantics.yysval = s->yysemantics.yysval;]b4_locations_if([[
+#if YYDEBUG
+ yyvsp[i].yystate.yylrState = s->yylrState;
+#endif
+ yyvsp[i].yystate.yyresolved = s->yyresolved;
+ if (s->yyresolved)
+ yyvsp[i].yystate.yysemantics.yysval = s->yysemantics.yysval;
+ else
+ /* The effect of using yysval or yyloc (in an immediate rule) is
+ * undefined. */
+ yyvsp[i].yystate.yysemantics.yyfirstVal = YY_NULL;]b4_locations_if([[
yyvsp[i].yystate.yyloc = s->yyloc;]])[
s = yyvsp[i].yystate.yypred = s->yypred;
}
yybool yynormal __attribute__ ((__unused__)) =
(yystackp->yysplitPoint == YY_NULL);
int yylow;
-]b4_parse_param_use[]dnl
+]b4_parse_param_use([yyvalp], [yylocp])dnl
[# undef yyerrok
# define yyerrok (yystackp->yyerrState = 0)
# undef YYACCEPT
}
}
-/** Left-hand-side symbol for rule #RULE. */
+/** Left-hand-side symbol for rule #YYRULE. */
static inline yySymbol
yylhsNonterm (yyRuleNum yyrule)
{
#define yypact_value_is_default(yystate) \
]b4_table_value_equals([[pact]], [[yystate]], [b4_pact_ninf])[
-/** True iff LR state STATE has only a default reduction (regardless
+/** True iff LR state YYSTATE has only a default reduction (regardless
* of token). */
static inline yybool
yyisDefaultedState (yyStateNum yystate)
return yypact_value_is_default (yypact[yystate]);
}
-/** The default reduction for STATE, assuming it has one. */
+/** The default reduction for YYSTATE, assuming it has one. */
static inline yyRuleNum
yydefaultAction (yyStateNum yystate)
{
* R < 0: Reduce on rule -R.
* R = 0: Error.
* R > 0: Shift to state R.
- * Set *CONFLICTS to a pointer into yyconfl to 0-terminated list of
- * conflicting reductions.
+ * Set *YYCONFLICTS to a pointer into yyconfl to a 0-terminated list
+ * of conflicting reductions.
*/
static inline void
yygetLRActions (yyStateNum yystate, int yytoken,
static inline yyStateNum
yyLRgotoState (yyStateNum yystate, yySymbol yylhs)
{
- int yyr;
- yyr = yypgoto[yylhs - YYNTOKENS] + yystate;
+ int yyr = yypgoto[yylhs - YYNTOKENS] + yystate;
if (0 <= yyr && yyr <= YYLAST && yycheck[yyr] == yystate)
return yytable[yyr];
else
/* GLRStates */
-/** Return a fresh GLRStackItem. Callers should call
- * YY_RESERVE_GLRSTACK afterwards to make sure there is sufficient
- * headroom. */
+/** Return a fresh GLRStackItem in YYSTACKP. The item is an LR state
+ * if YYISSTATE, and otherwise a semantic option. Callers should call
+ * YY_RESERVE_GLRSTACK afterwards to make sure there is sufficient
+ * headroom. */
static inline yyGLRStackItem*
yynewGLRStackItem (yyGLRStack* yystackp, yybool yyisState)
}
/** Add a new semantic action that will execute the action for rule
- * RULENUM on the semantic values in RHS to the list of
- * alternative actions for STATE. Assumes that RHS comes from
- * stack #K of *STACKP. */
+ * YYRULE on the semantic values in YYRHS to the list of
+ * alternative actions for YYSTATE. Assumes that YYRHS comes from
+ * stack #YYK of *YYSTACKP. */
static void
yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate,
- yyGLRState* rhs, yyRuleNum yyrule)
+ yyGLRState* yyrhs, yyRuleNum yyrule)
{
yySemanticOption* yynewOption =
&yynewGLRStackItem (yystackp, yyfalse)->yyoption;
- yynewOption->yystate = rhs;
+ yynewOption->yystate = yyrhs;
yynewOption->yyrule = yyrule;
if (yystackp->yytops.yylookaheadNeeds[yyk])
{
/* GLRStacks */
-/** Initialize SET to a singleton set containing an empty stack. */
+/** Initialize YYSET to a singleton set containing an empty stack. */
static yybool
yyinitStateSet (yyGLRStateSet* yyset)
{
YYFREE (yyset->yylookaheadNeeds);
}
-/** Initialize STACK to a single empty stack, with total maximum
- * capacity for all stacks of SIZE. */
+/** Initialize *YYSTACKP to a single empty stack, with total maximum
+ * capacity for all stacks of YYSIZE. */
static yybool
yyinitGLRStack (yyGLRStack* yystackp, size_t yysize)
{
# define YYRELOC(YYFROMITEMS,YYTOITEMS,YYX,YYTYPE) \
&((YYTOITEMS) - ((YYFROMITEMS) - (yyGLRStackItem*) (YYX)))->YYTYPE
-/** If STACK is expandable, extend it. WARNING: Pointers into the
+/** If *YYSTACKP is expandable, extend it. WARNING: Pointers into the
stack from outside should be considered invalid after this call.
We always expand when there are 1 or fewer items left AFTER an
allocation, so that we can avoid having external pointers exist
yyfreeStateSet (&yystackp->yytops);
}
-/** Assuming that S is a GLRState somewhere on STACK, update the
- * splitpoint of STACK, if needed, so that it is at least as deep as
- * S. */
+/** Assuming that YYS is a GLRState somewhere on *YYSTACKP, update the
+ * splitpoint of *YYSTACKP, if needed, so that it is at least as deep as
+ * YYS. */
static inline void
yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
{
yystackp->yysplitPoint = yys;
}
-/** Invalidate stack #K in STACK. */
+/** Invalidate stack #YYK in *YYSTACKP. */
static inline void
yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk)
{
yystackp->yytops.yystates[yyk] = YY_NULL;
}
-/** Undelete the last stack that was marked as deleted. Can only be
- done once after a deletion, and only when all other stacks have
+/** Undelete the last stack in *YYSTACKP that was marked as deleted. Can
+ only be done once after a deletion, and only when all other stacks have
been deleted. */
static void
yyundeleteLastStack (yyGLRStack* yystackp)
}
}
-/** Shift to a new state on stack #K of STACK, corresponding to LR state
- * LRSTATE, at input position POSN, with (resolved) semantic value SVAL. */
+/** Shift to a new state on stack #YYK of *YYSTACKP, corresponding to LR
+ * state YYLRSTATE, at input position YYPOSN, with (resolved) semantic
+ * value *YYVALP and source location *YYLOCP. */
static inline void
yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
size_t yyposn,
YY_RESERVE_GLRSTACK (yystackp);
}
-/** Shift stack #K of YYSTACK, to a new state corresponding to LR
+/** Shift stack #YYK of *YYSTACKP, to a new state corresponding to LR
* state YYLRSTATE, at input position YYPOSN, with the (unresolved)
* semantic value of YYRHS under the action for YYRULE. */
static inline void
yyglrShiftDefer (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
- size_t yyposn, yyGLRState* rhs, yyRuleNum yyrule)
+ size_t yyposn, yyGLRState* yyrhs, yyRuleNum yyrule)
{
yyGLRState* yynewState = &yynewGLRStackItem (yystackp, yytrue)->yystate;
yystackp->yytops.yystates[yyk] = yynewState;
/* Invokes YY_RESERVE_GLRSTACK. */
- yyaddDeferredAction (yystackp, yyk, yynewState, rhs, yyrule);
+ yyaddDeferredAction (yystackp, yyk, yynewState, yyrhs, yyrule);
}
-/** Pop the symbols consumed by reduction #RULE from the top of stack
- * #K of STACK, and perform the appropriate semantic action on their
+#if !YYDEBUG
+# define YY_REDUCE_PRINT(Args)
+#else
+# define YY_REDUCE_PRINT(Args) \
+do { \
+ if (yydebug) \
+ yy_reduce_print Args; \
+} while (YYID (0))
+
+/*----------------------------------------------------------------------.
+| Report that stack #YYK of *YYSTACKP is going to be reduced by YYRULE. |
+`----------------------------------------------------------------------*/
+
+/*ARGSUSED*/ static inline void
+yy_reduce_print (int yynormal, yyGLRStackItem* yyvsp, size_t yyk,
+ yyRuleNum yyrule]b4_user_formals[)
+{
+ int yynrhs = yyrhsLength (yyrule);]b4_locations_if([
+ int yylow = 1;])[
+ int yyi;
+ YYFPRINTF (stderr, "Reducing stack %lu by rule %d (line %lu):\n",
+ (unsigned long int) yyk, yyrule - 1,
+ (unsigned long int) yyrline[yyrule]);
+ if (! yynormal)
+ yyfillin (yyvsp, 1, -yynrhs);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr,
+ yystos[yyvsp[yyi - yynrhs + 1].yystate.yylrState],
+ &yyvsp[yyi - yynrhs + 1].yystate.yysemantics.yysval
+ ]b4_locations_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
+ b4_user_args[);
+ if (!yyvsp[yyi - yynrhs + 1].yystate.yyresolved)
+ YYFPRINTF (stderr, " (unresolved)");
+ YYFPRINTF (stderr, "\n");
+ }
+}
+#endif
+
+/** Pop the symbols consumed by reduction #YYRULE from the top of stack
+ * #YYK of *YYSTACKP, and perform the appropriate semantic action on their
* semantic values. Assumes that all ambiguities in semantic values
- * have been previously resolved. Set *VALP to the resulting value,
- * and *LOCP to the computed location (if any). Return value is as
+ * have been previously resolved. Set *YYVALP to the resulting value,
+ * and *YYLOCP to the computed location (if any). Return value is as
* for userAction. */
static inline YYRESULTTAG
yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
if (yystackp->yysplitPoint == YY_NULL)
{
/* Standard special case: single stack. */
- yyGLRStackItem* rhs = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
+ yyGLRStackItem* yyrhs = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
YYASSERT (yyk == 0);
yystackp->yynextFree -= yynrhs;
yystackp->yyspaceLeft += yynrhs;
yystackp->yytops.yystates[0] = & yystackp->yynextFree[-1].yystate;
- return yyuserAction (yyrule, yynrhs, rhs, yystackp,
+ YY_REDUCE_PRINT ((1, yyrhs, yyk, yyrule]b4_user_args[));
+ return yyuserAction (yyrule, yynrhs, yyrhs, yystackp,
yyvalp]b4_locuser_args[);
}
else
{
- /* At present, doAction is never called in nondeterministic
- * mode, so this branch is never taken. It is here in
- * anticipation of a future feature that will allow immediate
- * evaluation of selected actions in nondeterministic mode. */
int yyi;
yyGLRState* yys;
yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
}
yyupdateSplit (yystackp, yys);
yystackp->yytops.yystates[yyk] = yys;
+ YY_REDUCE_PRINT ((0, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1, yyk, yyrule]b4_user_args[));
return yyuserAction (yyrule, yynrhs, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
yystackp, yyvalp]b4_locuser_args[);
}
}
-#if !YYDEBUG
-# define YY_REDUCE_PRINT(Args)
-#else
-# define YY_REDUCE_PRINT(Args) \
-do { \
- if (yydebug) \
- yy_reduce_print Args; \
-} while (YYID (0))
-
-/*----------------------------------------------------------.
-| Report that the RULE is going to be reduced on stack #K. |
-`----------------------------------------------------------*/
-
-/*ARGSUSED*/ static inline void
-yy_reduce_print (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
- YYSTYPE* yyvalp]b4_locuser_formals[)
-{
- int yynrhs = yyrhsLength (yyrule);
- yybool yynormal __attribute__ ((__unused__)) =
- (yystackp->yysplitPoint == YY_NULL);
- yyGLRStackItem* yyvsp = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
- int yylow = 1;
- int yyi;
- YYUSE (yyvalp);]b4_locations_if([
- YYUSE (yylocp);])[
-]b4_parse_param_use[]dnl
-[ YYFPRINTF (stderr, "Reducing stack %lu by rule %d (line %lu):\n",
- (unsigned long int) yyk, yyrule - 1,
- (unsigned long int) yyrline[yyrule]);
- /* The symbols being reduced. */
- for (yyi = 0; yyi < yynrhs; yyi++)
- {
- YYFPRINTF (stderr, " $%d = ", yyi + 1);
- yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
- &]b4_rhs_value(yynrhs, yyi + 1)[
- ]b4_locations_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
- b4_user_args[);
- YYFPRINTF (stderr, "\n");
- }
-}
-#endif
-
-/** Pop items off stack #K of STACK according to grammar rule RULE,
+/** Pop items off stack #YYK of *YYSTACKP according to grammar rule YYRULE,
* and push back on the resulting nonterminal symbol. Perform the
- * semantic action associated with RULE and store its value with the
- * newly pushed state, if FORCEEVAL or if STACK is currently
+ * semantic action associated with YYRULE and store its value with the
+ * newly pushed state, if YYFORCEEVAL or if *YYSTACKP is currently
* unambiguous. Otherwise, store the deferred semantic action with
* the new state. If the new state would have an identical input
* position, LR state, and predecessor to an existing state on the stack,
- * it is identified with that existing state, eliminating stack #K from
- * the STACK. In this case, the (necessarily deferred) semantic value is
+ * it is identified with that existing state, eliminating stack #YYK from
+ * *YYSTACKP. In this case, the semantic value is
* added to the options for the existing state's semantic value.
*/
static inline YYRESULTTAG
if (yyforceEval || yystackp->yysplitPoint == YY_NULL)
{
+ YYRESULTTAG yyflag;
YYSTYPE yysval;]b4_locations_if([
YYLTYPE yyloc;])[
- YY_REDUCE_PRINT ((yystackp, yyk, yyrule, &yysval]b4_locuser_args([&yyloc])[));
- YYCHK (yydoAction (yystackp, yyk, yyrule, &yysval]b4_locuser_args([&yyloc])[));
+ yyflag = yydoAction (yystackp, yyk, yyrule, &yysval]b4_locuser_args([&yyloc])[);
+ if (yyflag == yyerr && yystackp->yysplitPoint != YY_NULL)
+ {
+ YYDPRINTF ((stderr, "Parse on stack %lu rejected by rule #%d.\n",
+ (unsigned long int) yyk, yyrule - 1));
+ }
+ if (yyflag != yyok)
+ return yyflag;
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyrule], &yysval, &yyloc);
yyglrShift (yystackp, yyk,
yyLRgotoState (yystackp->yytops.yystates[yyk]->yylrState,
yyupdateSplit (yystackp, yys);
yynewLRState = yyLRgotoState (yys->yylrState, yylhsNonterm (yyrule));
YYDPRINTF ((stderr,
- "Reduced stack %lu by rule #%d; action deferred. Now in state %d.\n",
+ "Reduced stack %lu by rule #%d; action deferred. "
+ "Now in state %d.\n",
(unsigned long int) yyk, yyrule - 1, yynewLRState));
for (yyi = 0; yyi < yystackp->yytops.yysize; yyi += 1)
if (yyi != yyk && yystackp->yytops.yystates[yyi] != YY_NULL)
return yystackp->yytops.yysize-1;
}
-/** True iff Y0 and Y1 represent identical options at the top level.
+/** True iff YYY0 and YYY1 represent identical options at the top level.
* That is, they represent the same rule applied to RHS symbols
* that produce the same terminal symbols. */
static yybool
return yyfalse;
}
-/** Assuming identicalOptions (Y0,Y1), destructively merge the
- * alternative semantic values for the RHS-symbols of Y1 and Y0. */
+/** Assuming identicalOptions (YYY0,YYY1), destructively merge the
+ * alternative semantic values for the RHS-symbols of YYY1 and YYY0. */
static void
yymergeOptionSets (yySemanticOption* yyy0, yySemanticOption* yyy1)
{
yyGLRStack* yystackp]b4_user_formals[);
-/** Resolve the previous N states starting at and including state S. If result
- * != yyok, some states may have been left unresolved possibly with empty
- * semantic option chains. Regardless of whether result = yyok, each state
- * has been left with consistent data so that yydestroyGLRState can be invoked
- * if necessary. */
+/** Resolve the previous YYN states starting at and including state YYS
+ * on *YYSTACKP. If result != yyok, some states may have been left
+ * unresolved possibly with empty semantic option chains. Regardless
+ * of whether result = yyok, each state has been left with consistent
+ * data so that yydestroyGLRState can be invoked if necessary. */
static YYRESULTTAG
yyresolveStates (yyGLRState* yys, int yyn,
yyGLRStack* yystackp]b4_user_formals[)
return yyok;
}
-/** Resolve the states for the RHS of OPT, perform its user action, and return
- * the semantic value and location. Regardless of whether result = yyok, all
- * RHS states have been destroyed (assuming the user action destroys all RHS
+/** Resolve the states for the RHS of YYOPT on *YYSTACKP, perform its
+ * user action, and return the semantic value and location in *YYVALP
+ * and *YYLOCP. Regardless of whether result = yyok, all RHS states
+ * have been destroyed (assuming the user action destroys all RHS
* semantic values if invoked). */
static YYRESULTTAG
yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystackp,
{
if (yystates[yyi-1]->yyposn+1 > yystates[yyi]->yyposn)
YYFPRINTF (stderr, "%*s%s <empty>\n", yyindent+2, "",
- yytokenName (yyrhs[yyprhs[yyx->yyrule]+yyi-1]));
+ yytokenName (yystos[yystates[yyi]->yylrState]));
else
YYFPRINTF (stderr, "%*s%s <tokens %lu .. %lu>\n", yyindent+2, "",
- yytokenName (yyrhs[yyprhs[yyx->yyrule]+yyi-1]),
- (unsigned long int) (yystates[yyi - 1]->yyposn + 1),
+ yytokenName (yystos[yystates[yyi]->yylrState]),
+ (unsigned long int) (yystates[yyi-1]->yyposn + 1),
(unsigned long int) yystates[yyi]->yyposn);
}
else
return yyabort;
}]b4_locations_if([[
-/** Starting at and including state S1, resolve the location for each of the
- * previous N1 states that is unresolved. The first semantic option of a state
- * is always chosen. */
+/** Resolve the locations for each of the YYN1 states in *YYSTACKP,
+ * ending at YYS1. Has no effect on previously resolved states.
+ * The first semantic option of a state is always chosen. */
static void
yyresolveLocations (yyGLRState* yys1, int yyn1,
yyGLRStack *yystackp]b4_user_formals[)
}
}]])[
-/** Resolve the ambiguity represented in state S, perform the indicated
- * actions, and set the semantic value of S. If result != yyok, the chain of
- * semantic options in S has been cleared instead or it has been left
- * unmodified except that redundant options may have been removed. Regardless
- * of whether result = yyok, S has been left with consistent data so that
+/** Resolve the ambiguity represented in state YYS in *YYSTACKP,
+ * perform the indicated actions, and set the semantic value of YYS.
+ * If result != yyok, the chain of semantic options in YYS has been
+ * cleared instead or it has been left unmodified except that
+ * redundant options may have been removed. Regardless of whether
+ * result = yyok, YYS has been left with consistent data so that
* yydestroyGLRState can be invoked if necessary. */
static YYRESULTTAG
yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp]b4_user_formals[)
yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
size_t yyposn]b4_pure_formals[)
{
- int yyaction;
- const short int* yyconflicts;
- yyRuleNum yyrule;
-
while (yystackp->yytops.yystates[yyk] != YY_NULL)
{
yyStateNum yystate = yystackp->yytops.yystates[yyk]->yylrState;
if (yyisDefaultedState (yystate))
{
- yyrule = yydefaultAction (yystate);
+ YYRESULTTAG yyflag;
+ yyRuleNum yyrule = yydefaultAction (yystate);
if (yyrule == 0)
{
YYDPRINTF ((stderr, "Stack %lu dies.\n",
yymarkStackDeleted (yystackp, yyk);
return yyok;
}
- YYCHK (yyglrReduce (yystackp, yyk, yyrule, yyfalse]b4_user_args[));
+ yyflag = yyglrReduce (yystackp, yyk, yyrule, yyimmediate[yyrule]]b4_user_args[);
+ if (yyflag == yyerr)
+ {
+ YYDPRINTF ((stderr,
+ "Stack %lu dies "
+ "(predicate failure or explicit user error).\n",
+ (unsigned long int) yyk));
+ yymarkStackDeleted (yystackp, yyk);
+ return yyok;
+ }
+ if (yyflag != yyok)
+ return yyflag;
}
else
{
yySymbol yytoken;
+ int yyaction;
+ const short int* yyconflicts;
+
yystackp->yytops.yylookaheadNeeds[yyk] = yytrue;
if (yychar == YYEMPTY)
{
while (*yyconflicts != 0)
{
+ YYRESULTTAG yyflag;
size_t yynewStack = yysplitStack (yystackp, yyk);
YYDPRINTF ((stderr, "Splitting off stack %lu from %lu.\n",
(unsigned long int) yynewStack,
(unsigned long int) yyk));
- YYCHK (yyglrReduce (yystackp, yynewStack,
- *yyconflicts, yyfalse]b4_user_args[));
- YYCHK (yyprocessOneStack (yystackp, yynewStack,
- yyposn]b4_pure_args[));
+ yyflag = yyglrReduce (yystackp, yynewStack,
+ *yyconflicts,
+ yyimmediate[*yyconflicts]]b4_user_args[);
+ if (yyflag == yyok)
+ YYCHK (yyprocessOneStack (yystackp, yynewStack,
+ yyposn]b4_pure_args[));
+ else if (yyflag == yyerr)
+ {
+ YYDPRINTF ((stderr, "Stack %lu dies.\n",
+ (unsigned long int) yynewStack));
+ yymarkStackDeleted (yystackp, yynewStack);
+ }
+ else
+ return yyflag;
yyconflicts += 1;
}
break;
}
else
- YYCHK (yyglrReduce (yystackp, yyk, -yyaction,
- yyfalse]b4_user_args[));
+ {
+ YYRESULTTAG yyflag = yyglrReduce (yystackp, yyk, -yyaction,
+ yyimmediate[-yyaction]]b4_user_args[);
+ if (yyflag == yyerr)
+ {
+ YYDPRINTF ((stderr,
+ "Stack %lu dies "
+ "(predicate failure or explicit user error).\n",
+ (unsigned long int) yyk));
+ yymarkStackDeleted (yystackp, yyk);
+ break;
+ }
+ else if (yyflag != yyok)
+ return yyflag;
+ }
}
}
return yyok;
} \
} while (YYID (0))
-
/*----------.
| yyparse. |
`----------*/
YYFPRINTF (stderr, "\n");
}
#endif
-]
-
-b4_epilogue
+]b4_epilogue[]dnl
dnl
dnl glr.cc produces its own header.
dnl
]b4_cpp_guard_open([b4_spec_defines_file])[
]b4_shared_declarations[
- ]b4_pure_if([], [[extern YYSTYPE ]b4_prefix[lval;
- ]b4_locations_if([[extern YYLTYPE ]b4_prefix[lloc;]])])[
]b4_cpp_guard_close([b4_spec_defines_file])[
]])])
m4_divert_pop(0)
-*- C -*-
-
# Yacc compatible skeleton for Bison
# Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation,
# Inc.
+m4_pushdef([b4_copyright_years],
+ [1984, 1989-1990, 2000-2012])
+
# 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 3 of the License, or
# Expand IF-TRUE, if %pure-parser and %parse-param, IF-FALSE otherwise.
m4_define([b4_yacc_pure_if],
[b4_pure_if([m4_ifset([b4_parse_param],
- [$1], [$2])],
- [$2])])
+ [$1], [$2])],
+ [$2])])
# b4_yyerror_args
m4_eval([0 <= $1]), [1], [unsigned int],
- [int])])
+ [int])])
## ----------------- ##
# --------------------
# Expansion of $<TYPE>$.
m4_define([b4_lhs_value],
-[(yyval[]m4_ifval([$1], [.$1]))])
+[b4_symbol_value(yyval, [$1])])
# b4_rhs_value(RULE-LENGTH, NUM, [TYPE])
# Expansion of $<TYPE>NUM, where the current rule has RULE-LENGTH
# symbols on RHS.
m4_define([b4_rhs_value],
-[(yyvsp@{($2) - ($1)@}m4_ifval([$3], [.$3]))])
+ [b4_symbol_value([yyvsp@{b4_subtract([$2], [$1])@}], [$3])])
# Expansion of @NUM, where the current rule has RULE-LENGTH symbols
# on RHS.
m4_define([b4_rhs_location],
-[(yylsp@{($2) - ($1)@})])
+ [(yylsp@{b4_subtract([$2], [$1])@})])
## -------------- ##
m4_changecom()
m4_divert_push(0)dnl
@output(b4_parser_file_name@)@
-b4_copyright([Bison implementation for Yacc-like parsers in C],
- [1984, 1989-1990, 2000-2012])[
+b4_copyright([Bison implementation for Yacc-like parsers in C])[
/* C LALR(1) parser skeleton written by Richard Stallman, by
simplifying the original so-called "semantic" parser. */
#define yylval ]b4_prefix[lval
#define yychar ]b4_prefix[char
#define yydebug ]b4_prefix[debug
- #define yynerrs ]b4_prefix[nerrs
- ]b4_locations_if([[#define yylloc ]b4_prefix[lloc]])])[
+ #define yynerrs ]b4_prefix[nerrs]b4_locations_if([[
+ #define yylloc ]b4_prefix[lloc]])])[
/* Copy the first part of user declarations. */
]b4_user_pre_prologue[
# undef YYERROR_VERBOSE
# define YYERROR_VERBOSE 1
#else
-# define YYERROR_VERBOSE ]b4_error_verbose_flag[
+# define YYERROR_VERBOSE ]b4_error_verbose_if([1], [0])[
#endif
/* Enabling the token table. */
# endif
# if (defined __cplusplus && ! defined EXIT_SUCCESS \
&& ! ((defined YYMALLOC || defined malloc) \
- && (defined YYFREE || defined free)))
+ && (defined YYFREE || defined free)))
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
# ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
#if (! defined yyoverflow \
&& (! defined __cplusplus \
- || (]b4_locations_if([[defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
- && ]])[defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+ || (]b4_locations_if([[defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+ && ]])[defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
/* A type that is properly aligned for any stack member. */
union yyalloc
elements in the stack, and YYPTR gives the new location of the
stack. Advance YYPTR to a properly aligned location for the next
stack. */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
- do \
- { \
- YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
- Stack = &yyptr->Stack_alloc; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
- } \
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
while (YYID (0))
#endif
#define YYNNTS ]b4_nterms_number[
/* YYNRULES -- Number of rules. */
#define YYNRULES ]b4_rules_number[
-/* YYNRULES -- Number of states. */
+/* YYNSTATES -- Number of states. */
#define YYNSTATES ]b4_states_number[
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+ by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK ]b4_undef_token_number[
#define YYMAXUTOK ]b4_user_token_number_max[
-#define YYTRANSLATE(YYX) \
+#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, without out-of-bounds checking. */
static const ]b4_int_type_for([b4_translate])[ yytranslate[] =
{
]b4_translate[
};
#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const ]b4_int_type_for([b4_prhs])[ yyprhs[] =
-{
- ]b4_prhs[
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const ]b4_int_type_for([b4_rhs])[ yyrhs[] =
-{
- ]b4_rhs[
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const ]b4_int_type_for([b4_rline])[ yyrline[] =
-{
- ]b4_rline[
-};
+]b4_integral_parser_table_define([rline], [b4_rline],
+ [YYRLINE[YYN] -- Source line where rule number YYN was defined.])[
#endif
#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
#endif
# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+ (internal) symbol number NUM (which must be that of a token). */
static const ]b4_int_type_for([b4_toknum])[ yytoknum[] =
{
]b4_toknum[
};
# endif
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const ]b4_int_type_for([b4_r1])[ yyr1[] =
-{
- ]b4_r1[
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const ]b4_int_type_for([b4_r2])[ yyr2[] =
-{
- ]b4_r2[
-};
-
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
- Performed when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
-static const ]b4_int_type_for([b4_defact])[ yydefact[] =
-{
- ]b4_defact[
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const ]b4_int_type_for([b4_defgoto])[ yydefgoto[] =
-{
- ]b4_defgoto[
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
#define YYPACT_NINF ]b4_pact_ninf[
-static const ]b4_int_type_for([b4_pact])[ yypact[] =
-{
- ]b4_pact[
-};
-
-/* YYPGOTO[NTERM-NUM]. */
-static const ]b4_int_type_for([b4_pgoto])[ yypgoto[] =
-{
- ]b4_pgoto[
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF ]b4_table_ninf[
-static const ]b4_int_type_for([b4_table])[ yytable[] =
-{
- ]b4_table[
-};
#define yypact_value_is_default(yystate) \
]b4_table_value_equals([[pact]], [[yystate]], [b4_pact_ninf])[
+#define YYTABLE_NINF ]b4_table_ninf[
+
#define yytable_value_is_error(yytable_value) \
]b4_table_value_equals([[table]], [[yytable_value]], [b4_table_ninf])[
-static const ]b4_int_type_for([b4_check])[ yycheck[] =
-{
- ]b4_check[
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const ]b4_int_type_for([b4_stos])[ yystos[] =
-{
- ]b4_stos[
-};
+]b4_parser_tables_define[
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
/* Like YYERROR except do call yyerror. This remains here temporarily
in Bison 2.4.2's NEWS entry, where a plan to phase it out is
discussed. */
-#define YYFAIL goto yyerrlab
+#define YYFAIL goto yyerrlab
#if defined YYFAIL
/* This is here to suppress warnings from the GCC cpp's
-Wunused-macros. Normally we don't worry about that warning, but
else \
{ \
yyerror (]b4_yyerror_args[YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
+ YYERROR; \
+ } \
while (YYID (0))
-#define YYTERROR 1
-#define YYERRCODE 256
+#define YYTERROR 1
+#define YYERRCODE 256
/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
#define YYRHSLOC(Rhs, K) ((Rhs)[K])
#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- } \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
while (YYID (0))
#endif]b4_locations_if([[
#ifndef YY_LOCATION_PRINT
# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-# define YY_LOCATION_PRINT(File, Loc) \
- fprintf (File, "%d.%d-%d.%d", \
- (Loc).first_line, (Loc).first_column, \
- (Loc).last_line, (Loc).last_column)
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
# else
# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
# endif
# define YYFPRINTF fprintf
# endif
-# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
} while (YYID (0))
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yy_symbol_print (stderr, \
- Type, Value]b4_locations_if([, Location])[]b4_user_args[); \
- YYFPRINTF (stderr, "\n"); \
- } \
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value]b4_locations_if([, Location])[]b4_user_args[); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
} while (YYID (0))
]b4_yy_symbol_print_generate([b4_c_function_def])[
`------------------------------------------------------------------*/
]b4_c_function_def([yy_stack_print], [static void],
- [[yytype_int16 *yybottom], [yybottom]],
- [[yytype_int16 *yytop], [yytop]])[
+ [[yytype_int16 *yybottom], [yybottom]],
+ [[yytype_int16 *yytop], [yytop]])[
{
YYFPRINTF (stderr, "Stack now");
for (; yybottom <= yytop; yybottom++)
YYFPRINTF (stderr, "\n");
}
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
} while (YYID (0))
`------------------------------------------------*/
]b4_c_function_def([yy_reduce_print], [static void],
- [[YYSTYPE *yyvsp], [yyvsp]],
+ [[yytype_int16 *yyssp], [yyssp]],
+ [[YYSTYPE *yyvsp], [yyvsp]],
b4_locations_if([[[YYLTYPE *yylsp], [yylsp]],
- ])[[int yyrule], [yyrule]]m4_ifset([b4_parse_param], [,
- b4_parse_param]))[
+ ])[[int yyrule], [yyrule]]m4_ifset([b4_parse_param], [,
+ b4_parse_param]))[
{
+ unsigned long int yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
int yyi;
- unsigned long int yylno = yyrline[yyrule];
YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
- yyrule - 1, yylno);
+ yyrule - 1, yylno);
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
YYFPRINTF (stderr, " $%d = ", yyi + 1);
- yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
- &]b4_rhs_value(yynrhs, yyi + 1)[
- ]b4_locations_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
- b4_user_args[);
+ yy_symbol_print (stderr,
+ yystos[yyssp[yyi + 1 - yynrhs]],
+ &]b4_rhs_value(yynrhs, yyi + 1)[
+ ]b4_locations_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
+ b4_user_args[);
YYFPRINTF (stderr, "\n");
}
}
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (yyvsp, ]b4_locations_if([yylsp, ])[Rule]b4_user_args[); \
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyssp, yyvsp, ]b4_locations_if([yylsp, ])[Rule]b4_user_args[); \
} while (YYID (0))
/* Nonzero means print parse trace. It is left uninitialized so that
/* YYINITDEPTH -- initial size of the parser's stacks. */
-#ifndef YYINITDEPTH
+#ifndef YYINITDEPTH
# define YYINITDEPTH ]b4_stack_depth_init[
#endif
char const *yyp = yystr;
for (;;)
- switch (*++yyp)
- {
- case '\'':
- case ',':
- goto do_not_strip_quotes;
-
- case '\\':
- if (*++yyp != '\\')
- goto do_not_strip_quotes;
- /* Fall through. */
- default:
- if (yyres)
- yyres[yyn] = *yyp;
- yyn++;
- break;
-
- case '"':
- if (yyres)
- yyres[yyn] = '\0';
- return yyn;
- }
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
do_not_strip_quotes: ;
}
#ifdef yyoverflow
{
- /* Give user a chance to reallocate the stack. Use copies of
- these so that the &'s don't force the real ones into
- memory. */
- YYSTYPE *yyvs1 = yyvs;
- yytype_int16 *yyss1 = yyss;]b4_locations_if([
- YYLTYPE *yyls1 = yyls;])[
-
- /* Each stack pointer address is followed by the size of the
- data in use in that stack, in bytes. This used to be a
- conditional around just the two extra args, but that might
- be undefined if yyoverflow is a macro. */
- yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),]b4_locations_if([
- &yyls1, yysize * sizeof (*yylsp),])[
- &yystacksize);
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;]b4_locations_if([
+ YYLTYPE *yyls1 = yyls;])[
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),]b4_locations_if([
+ &yyls1, yysize * sizeof (*yylsp),])[
+ &yystacksize);
]b4_locations_if([
- yyls = yyls1;])[
- yyss = yyss1;
- yyvs = yyvs1;
+ yyls = yyls1;])[
+ yyss = yyss1;
+ yyvs = yyvs1;
}
#else /* no yyoverflow */
# ifndef YYSTACK_RELOCATE
# else
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
- goto yyexhaustedlab;
+ goto yyexhaustedlab;
yystacksize *= 2;
if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
+ yystacksize = YYMAXDEPTH;
{
- yytype_int16 *yyss1 = yyss;
- union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
- if (! yyptr)
- goto yyexhaustedlab;
- YYSTACK_RELOCATE (yyss_alloc, yyss);
- YYSTACK_RELOCATE (yyvs_alloc, yyvs);]b4_locations_if([
- YYSTACK_RELOCATE (yyls_alloc, yyls);])[
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);]b4_locations_if([
+ YYSTACK_RELOCATE (yyls_alloc, yyls);])[
# undef YYSTACK_RELOCATE
- if (yyss1 != yyssa)
- YYSTACK_FREE (yyss1);
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
}
# endif
#endif /* no yyoverflow */
yylsp = yyls + yysize - 1;])[
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
+ (unsigned long int) yystacksize));
if (yyss + yystacksize - 1 <= yyssp)
- YYABORT;
+ YYABORT;
}
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse lookahead token after an
- error, discard it. */
+ error, discard it. */
if (yychar <= YYEOF)
- {
- /* Return failure if at end of input. */
- if (yychar == YYEOF)
- YYABORT;
- }
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
else
- {
- yydestruct ("Error: discarding",
- yytoken, &yylval]b4_locations_if([, &yylloc])[]b4_user_args[);
- yychar = YYEMPTY;
- }
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval]b4_locations_if([, &yylloc])[]b4_user_args[);
+ yychar = YYEMPTY;
+ }
}
/* Else will try to reuse lookahead token after shifting the error
| yyerrlab1 -- common code for both syntax error and YYERROR. |
`-------------------------------------------------------------*/
yyerrlab1:
- yyerrstatus = 3; /* Each real token shifted decrements this. */
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
for (;;)
{
yyn = yypact[yystate];
if (!yypact_value_is_default (yyn))
- {
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
- {
- yyn = yytable[yyn];
- if (0 < yyn)
- break;
- }
- }
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
/* Pop the current state because it cannot handle the error token. */
if (yyssp == yyss)
- YYABORT;
+ YYABORT;
]b4_locations_if([[ yyerror_range[1] = *yylsp;]])[
yydestruct ("Error: popping",
- yystos[yystate], yyvsp]b4_locations_if([, yylsp])[]b4_user_args[);
+ yystos[yystate], yyvsp]b4_locations_if([, yylsp])[]b4_user_args[);
YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
while (yyssp != yyss)
{
yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp]b4_locations_if([, yylsp])[]b4_user_args[);
+ yystos[*yyssp], yyvsp]b4_locations_if([, yylsp])[]b4_user_args[);
YYPOPSTACK (1);
}
#ifndef yyoverflow
return YYID (yyresult);
}
-
-]b4_epilogue
+]b4_epilogue[]dnl
b4_defines_if(
[@output(b4_spec_defines_file@)@
-b4_copyright([Bison interface for Yacc-like parsers in C],
- [1984, 1989-1990, 2000-2012])[
+b4_copyright([Bison interface for Yacc-like parsers in C])[
]b4_cpp_guard_open([b4_spec_defines_file])[
]b4_shared_declarations[
- ]b4_pure_if([], [[extern YYSTYPE ]b4_prefix[lval;
- ]b4_locations_if([[extern YYLTYPE ]b4_prefix[lloc;]])])[
]b4_cpp_guard_close([b4_spec_defines_file])[
]])dnl b4_defines_if
m4_divert_pop(0)
+m4_popdef([b4_copyright_years])
* Simple GLR Parsers:: Using GLR parsers on unambiguous grammars.
* Merging GLR Parses:: Using GLR parsers to resolve ambiguities.
-* GLR Semantic Actions:: Deferred semantic actions have special concerns.
+* GLR Semantic Actions:: Considerations for semantic values and deferred actions.
+* Semantic Predicates:: Controlling a parse with arbitrary computations.
* Compiler Requirements:: GLR parsers require a modern C compiler.
Examples
Grammar Rules for @code{rpcalc}
-* Rpcalc Input::
-* Rpcalc Line::
-* Rpcalc Expr::
+* Rpcalc Input:: Explanation of the @code{input} nonterminal
+* Rpcalc Line:: Explanation of the @code{line} nonterminal
+* Rpcalc Expr:: Explanation of the @code{expr} nonterminal
Location Tracking Calculator: @code{ltcalc}
* Mfcalc Declarations:: Bison declarations for multi-function calculator.
* Mfcalc Rules:: Grammar rules for the calculator.
* Mfcalc Symbol Table:: Symbol table management subroutines.
+* Mfcalc Lexer:: The lexical analyzer.
+* Mfcalc Main:: The controlling function.
Bison Grammar Files
Operator Precedence
* Why Precedence:: An example showing why precedence is needed.
-* Using Precedence:: How to specify precedence in Bison grammars.
+* Using Precedence:: How to specify precedence and associativity.
+* Precedence Only:: How to specify precedence only.
* Precedence Examples:: How these features are used in the previous example.
* How Precedence:: How they work.
@menu
* Simple GLR Parsers:: Using GLR parsers on unambiguous grammars.
* Merging GLR Parses:: Using GLR parsers to resolve ambiguities.
-* GLR Semantic Actions:: Deferred semantic actions have special concerns.
+* GLR Semantic Actions:: Considerations for semantic values and deferred actions.
+* Semantic Predicates:: Controlling a parse with arbitrary computations.
* Compiler Requirements:: GLR parsers require a modern C compiler.
@end menu
@node GLR Semantic Actions
@subsection GLR Semantic Actions
+The nature of GLR parsing and the structure of the generated
+parsers give rise to certain restrictions on semantic values and actions.
+
+@subsubsection Deferred semantic actions
@cindex deferred semantic actions
By definition, a deferred semantic action is not performed at the same time as
the associated reduction.
to invoke @code{yyclearin} (@pxref{Action Features}) or to attempt to free
memory referenced by @code{yylval}.
+@subsubsection YYERROR
@findex YYERROR
@cindex GLR parsers and @code{YYERROR}
Another Bison feature requiring special consideration is @code{YYERROR}
initiate error recovery.
During deterministic GLR operation, the effect of @code{YYERROR} is
the same as its effect in a deterministic parser.
-In a deferred semantic action, its effect is undefined.
-@c The effect is probably a syntax error at the split point.
+The effect in a deferred action is similar, but the precise point of the
+error is undefined; instead, the parser reverts to deterministic operation,
+selecting an unspecified stack on which to continue with a syntax error.
+In a semantic predicate (see @ref{Semantic Predicates}) during nondeterministic
+parsing, @code{YYERROR} silently prunes
+the parse that invoked the test.
+
+@subsubsection Restrictions on semantic values and locations
+GLR parsers require that you use POD (Plain Old Data) types for
+semantic values and location types when using the generated parsers as
+C++ code.
+
+@node Semantic Predicates
+@subsection Controlling a Parse with Arbitrary Predicates
+@findex %?
+@cindex Semantic predicates in GLR parsers
+
+In addition to the @code{%dprec} and @code{%merge} directives,
+GLR parsers
+allow you to reject parses on the basis of arbitrary computations executed
+in user code, without having Bison treat this rejection as an error
+if there are alternative parses. (This feature is experimental and may
+evolve. We welcome user feedback.) For example,
+
+@example
+widget:
+ %?@{ new_syntax @} "widget" id new_args @{ $$ = f($3, $4); @}
+| %?@{ !new_syntax @} "widget" id old_args @{ $$ = f($3, $4); @}
+;
+@end example
+
+@noindent
+is one way to allow the same parser to handle two different syntaxes for
+widgets. The clause preceded by @code{%?} is treated like an ordinary
+action, except that its text is treated as an expression and is always
+evaluated immediately (even when in nondeterministic mode). If the
+expression yields 0 (false), the clause is treated as a syntax error,
+which, in a nondeterministic parser, causes the stack in which it is reduced
+to die. In a deterministic parser, it acts like YYERROR.
+
+As the example shows, predicates otherwise look like semantic actions, and
+therefore you must be take them into account when determining the numbers
+to use for denoting the semantic values of right-hand side symbols.
+Predicate actions, however, have no defined value, and may not be given
+labels.
+
+There is a subtle difference between semantic predicates and ordinary
+actions in nondeterministic mode, since the latter are deferred.
+For example, we could try to rewrite the previous example as
+
+@example
+widget:
+ @{ if (!new_syntax) YYERROR; @}
+ "widget" id new_args @{ $$ = f($3, $4); @}
+| @{ if (new_syntax) YYERROR; @}
+ "widget" id old_args @{ $$ = f($3, $4); @}
+;
+@end example
-Also, see @ref{Location Default Action, ,Default Action for Locations}, which
-describes a special usage of @code{YYLLOC_DEFAULT} in GLR parsers.
+@noindent
+(reversing the sense of the predicate tests to cause an error when they are
+false). However, this
+does @emph{not} have the same effect if @code{new_args} and @code{old_args}
+have overlapping syntax.
+Since the mid-rule actions testing @code{new_syntax} are deferred,
+a GLR parser first encounters the unresolved ambiguous reduction
+for cases where @code{new_args} and @code{old_args} recognize the same string
+@emph{before} performing the tests of @code{new_syntax}. It therefore
+reports an error.
+
+Finally, be careful in writing predicates: deferred actions have not been
+evaluated, so that using them in a predicate will have undefined effects.
@node Compiler Requirements
@subsection Considerations when Compiling GLR Parsers
Here are the C and Bison declarations for the reverse polish notation
calculator. As in C, comments are placed between @samp{/*@dots{}*/}.
+@comment file: rpcalc.y
@example
/* Reverse polish notation calculator. */
%@{
#define YYSTYPE double
+ #include <stdio.h>
#include <math.h>
int yylex (void);
void yyerror (char const *);
Here are the grammar rules for the reverse polish notation calculator.
+@comment file: rpcalc.y
@example
@group
input:
rule are referred to as @code{$1}, @code{$2}, and so on.
@menu
-* Rpcalc Input::
-* Rpcalc Line::
-* Rpcalc Expr::
+* Rpcalc Input:: Explanation of the @code{input} nonterminal
+* Rpcalc Line:: Explanation of the @code{line} nonterminal
+* Rpcalc Expr:: Explanation of the @code{expr} nonterminal
@end menu
@node Rpcalc Input
Here is the code for the lexical analyzer:
+@comment file: rpcalc.y
@example
@group
/* The lexical analyzer returns a double floating point
kept to the bare minimum. The only requirement is that it call
@code{yyparse} to start the process of parsing.
+@comment file: rpcalc.y
@example
@group
int
@code{yyerror} (@pxref{Interface, ,Parser C-Language Interface}), so
here is the definition we will use:
+@comment file: rpcalc.y
@example
@group
#include <stdio.h>
@example
$ @kbd{rpcalc}
@kbd{4 9 +}
-13
+@result{} 13
@kbd{3 7 + 3 4 5 *+-}
--13
+@result{} -13
@kbd{3 7 + 3 4 5 * + - n} @r{Note the unary minus, @samp{n}}
-13
+@result{} 13
@kbd{5 6 / 4 n +}
--3.166666667
+@result{} -3.166666667
@kbd{3 4 ^} @r{Exponentiation}
-81
+@result{} 81
@kbd{^D} @r{End-of-file indicator}
$
@end example
%token NUM
%left '-' '+'
%left '*' '/'
-%left NEG /* negation--unary minus */
-%right '^' /* exponentiation */
+%precedence NEG /* negation--unary minus */
+%right '^' /* exponentiation */
@end group
%% /* The grammar follows. */
types and says they are left-associative operators. The declarations
@code{%left} and @code{%right} (right associativity) take the place of
@code{%token} which is used to declare a token type name without
-associativity. (These tokens are single-character literals, which
+associativity/precedence. (These tokens are single-character literals, which
ordinarily don't need to be declared. We declare them here to specify
-the associativity.)
+the associativity/precedence.)
Operator precedence is determined by the line ordering of the
declarations; the higher the line number of the declaration (lower on
the page or screen), the higher the precedence. Hence, exponentiation
has the highest precedence, unary minus (@code{NEG}) is next, followed
-by @samp{*} and @samp{/}, and so on. @xref{Precedence, ,Operator
+by @samp{*} and @samp{/}, and so on. Unary minus is not associative,
+only precedence matters (@code{%precedence}. @xref{Precedence, ,Operator
Precedence}.
The other important new feature is the @code{%prec} in the grammar
%left '-' '+'
%left '*' '/'
-%left NEG
+%precedence NEG
%right '^'
%% /* The grammar follows. */
Here is a sample session with the multi-function calculator:
@example
+@group
$ @kbd{mfcalc}
@kbd{pi = 3.141592653589}
-3.1415926536
+@result{} 3.1415926536
+@end group
+@group
@kbd{sin(pi)}
-0.0000000000
+@result{} 0.0000000000
+@end group
@kbd{alpha = beta1 = 2.3}
-2.3000000000
+@result{} 2.3000000000
@kbd{alpha}
-2.3000000000
+@result{} 2.3000000000
@kbd{ln(alpha)}
-0.8329091229
+@result{} 0.8329091229
@kbd{exp(ln(beta1))}
-2.3000000000
+@result{} 2.3000000000
$
@end example
* Mfcalc Declarations:: Bison declarations for multi-function calculator.
* Mfcalc Rules:: Grammar rules for the calculator.
* Mfcalc Symbol Table:: Symbol table management subroutines.
+* Mfcalc Lexer:: The lexical analyzer.
+* Mfcalc Main:: The controlling function.
@end menu
@node Mfcalc Declarations
@example
@group
%@{
- #include <math.h> /* For math functions, cos(), sin(), etc. */
- #include "calc.h" /* Contains definition of `symrec'. */
+ #include <stdio.h> /* For printf, etc. */
+ #include <math.h> /* For pow, used in the grammar. */
+ #include "calc.h" /* Contains definition of `symrec'. */
int yylex (void);
void yyerror (char const *);
%@}
%right '='
%left '-' '+'
%left '*' '/'
-%left NEG /* negation--unary minus */
-%right '^' /* exponentiation */
+%precedence NEG /* negation--unary minus */
+%right '^' /* exponentiation */
@end group
@end example
@end group
@end example
-The new version of @code{main} includes a call to @code{init_table}, a
-function that initializes the symbol table. Here it is, and
-@code{init_table} as well:
+The new version of @code{main} will call @code{init_table} to initialize
+the symbol table:
@comment file: mfcalc.y: 3
@example
-#include <stdio.h>
-
-@group
-/* Called by yyparse on error. */
-void
-yyerror (char const *s)
-@{
- printf ("%s\n", s);
-@}
-@end group
-
@group
struct init
@{
@group
struct init const arith_fncts[] =
@{
- "sin", sin,
- "cos", cos,
- "atan", atan,
- "ln", log,
- "exp", exp,
- "sqrt", sqrt,
- 0, 0
+ @{ "atan", atan @},
+ @{ "cos", cos @},
+ @{ "exp", exp @},
+ @{ "ln", log @},
+ @{ "sin", sin @},
+ @{ "sqrt", sqrt @},
+ @{ 0, 0 @},
@};
@end group
@group
/* Put arithmetic functions in table. */
+static
void
init_table (void)
@{
@}
@}
@end group
-
-@group
-int
-main (void)
-@{
- init_table ();
- return yyparse ();
-@}
-@end group
@end example
By simply editing the initialization list and adding the necessary include
symrec *ptr;
for (ptr = sym_table; ptr != (symrec *) 0;
ptr = (symrec *)ptr->next)
- if (strcmp (ptr->name,sym_name) == 0)
+ if (strcmp (ptr->name, sym_name) == 0)
return ptr;
return 0;
@}
@end group
@end example
+@node Mfcalc Lexer
+@subsection The @code{mfcalc} Lexer
+
The function @code{yylex} must now recognize variables, numeric values, and
the single-character arithmetic operators. Strings of alphanumeric
characters with a leading letter are recognized as either variables or
symrec *s;
int i;
@end group
-
if (!symbuf)
symbuf = (char *) malloc (length + 1);
@end group
@end example
+@node Mfcalc Main
+@subsection The @code{mfcalc} Main
+
The error reporting function is unchanged, and the new version of
@code{main} includes a call to @code{init_table} and sets the @code{yydebug}
on user demand (@xref{Tracing, , Tracing Your Parser}, for details):
the parser, so that the function @code{yylex} (if it is in this file)
can use the name @var{name} to stand for this token type's code.
-Alternatively, you can use @code{%left}, @code{%right}, or
+Alternatively, you can use @code{%left}, @code{%right},
+@code{%precedence}, or
@code{%nonassoc} instead of @code{%token}, if you wish to specify
associativity and precedence. @xref{Precedence Decl, ,Operator
Precedence}.
@cindex declaring operator precedence
@cindex operator precedence, declaring
-Use the @code{%left}, @code{%right} or @code{%nonassoc} declaration to
+Use the @code{%left}, @code{%right}, @code{%nonassoc}, or
+@code{%precedence} declaration to
declare a token and specify its precedence and associativity, all at
once. These are called @dfn{precedence declarations}.
@xref{Precedence, ,Operator Precedence}, for general information on
means that @samp{@var{x} @var{op} @var{y} @var{op} @var{z}} is
considered a syntax error.
+@code{%precedence} gives only precedence to the @var{symbols}, and
+defines no associativity at all. Use this to define precedence only,
+and leave any potential conflict due to associativity enabled.
+
@item
The precedence of an operator determines how it nests with other operators.
All the tokens declared in a single precedence declaration have equal
including @code{yylval} and @code{yylloc}.)
Alternatively, you can generate a pure, reentrant parser. The Bison
-declaration @code{%define api.pure} says that you want the parser to be
+declaration @samp{%define api.pure} says that you want the parser to be
reentrant. It looks like this:
@example
Bison also supports both the push parser interface along with the pull parser
interface in the same generated parser. In order to get this functionality,
-you should replace the @code{%define api.push-pull push} declaration with the
-@code{%define api.push-pull both} declaration. Doing this will create all of
+you should replace the @samp{%define api.push-pull push} declaration with the
+@samp{%define api.push-pull both} declaration. Doing this will create all of
the symbols mentioned earlier along with the two extra symbols, @code{yyparse}
and @code{yypull_parse}. @code{yyparse} can be used exactly as it normally
would be used. However, the user should note that it is implemented in the
generated parser by calling @code{yypull_parse}.
This makes the @code{yyparse} function that is generated with the
-@code{%define api.push-pull both} declaration slower than the normal
+@samp{%define api.push-pull both} declaration slower than the normal
@code{yyparse} function. If the user
calls the @code{yypull_parse} function it will parse the rest of the input
stream. It is possible to @code{yypush_parse} tokens to select a subgrammar
yypstate_delete (ps);
@end example
-Adding the @code{%define api.pure} declaration does exactly the same thing to
-the generated parser with @code{%define api.push-pull both} as it did for
-@code{%define api.push-pull push}.
+Adding the @samp{%define api.pure} declaration does exactly the same thing to
+the generated parser with @samp{%define api.push-pull both} as it did for
+@samp{%define api.push-pull push}.
@node Decl Summary
@subsection Bison Declaration Summary
@end deffn
@deffn {Directive} %debug
-In the parser implementation file, define the macro @code{YYDEBUG} to
-1 if it is not already defined, so that the debugging facilities are
-compiled. @xref{Tracing, ,Tracing Your Parser}.
+Instrument the output parser for traces. Obsoleted by @samp{%define
+parse.trace}.
+@xref{Tracing, ,Tracing Your Parser}.
@end deffn
@deffn {Directive} %define @var{variable}
@code{yypstate_new} and @code{yypstate_delete} will
also be renamed. For example, if you use @samp{%name-prefix "c_"}, the
names become @code{c_parse}, @code{c_lex}, and so on.
-For C++ parsers, see the @code{%define namespace} documentation in this
+For C++ parsers, see the @samp{%define api.namespace} documentation in this
section.
@xref{Multiple Parsers, ,Multiple Parsers in the Same Program}.
@end deffn
@end deffn
@deffn {Directive} %pure-parser
-Deprecated version of @code{%define api.pure} (@pxref{%define
+Deprecated version of @samp{%define api.pure} (@pxref{%define
Summary,,api.pure}), for which Bison is more careful to warn about
unreasonable usage.
@end deffn
Unaccepted @var{variable}s produce an error.
Some of the accepted @var{variable}s are:
-@itemize @bullet
+@table @code
+@c ================================================== api.namespace
+@item api.namespace
+@findex %define api.namespace
+@itemize
+@item Languages(s): C++
+
+@item Purpose: Specify the namespace for the parser class.
+For example, if you specify:
+
+@example
+%define api.namespace "foo::bar"
+@end example
+
+Bison uses @code{foo::bar} verbatim in references such as:
+
+@example
+foo::bar::parser::semantic_type
+@end example
+
+However, to open a namespace, Bison removes any leading @code{::} and then
+splits on any remaining occurrences:
+
+@example
+namespace foo @{ namespace bar @{
+ class position;
+ class location;
+@} @}
+@end example
+
+@item Accepted Values:
+Any absolute or relative C++ namespace reference without a trailing
+@code{"::"}. For example, @code{"foo"} or @code{"::foo::bar"}.
+
+@item Default Value:
+The value specified by @code{%name-prefix}, which defaults to @code{yy}.
+This usage of @code{%name-prefix} is for backward compatibility and can
+be confusing since @code{%name-prefix} also specifies the textual prefix
+for the lexical analyzer function. Thus, if you specify
+@code{%name-prefix}, it is best to also specify @samp{%define
+api.namespace} so that @code{%name-prefix} @emph{only} affects the
+lexical analyzer function. For example, if you specify:
+
+@example
+%define api.namespace "foo"
+%name-prefix "bar::"
+@end example
+
+The parser namespace is @code{foo} and @code{yylex} is referenced as
+@code{bar::lex}.
+@end itemize
+@c namespace
+
+
+
@c ================================================== api.pure
@item api.pure
@findex %define api.pure
@item Default Value: @code{false}
@end itemize
+@c api.pure
+
+
+@c ================================================== api.push-pull
@item api.push-pull
@findex %define api.push-pull
@item Default Value: @code{pull}
@end itemize
+@c api.push-pull
+
+
+
+@c ================================================== api.tokens.prefix
+@item api.tokens.prefix
+@findex %define api.tokens.prefix
+
+@itemize
+@item Languages(s): all
+
+@item Purpose:
+Add a prefix to the token names when generating their definition in the
+target language. For instance
+
+@example
+%token FILE for ERROR
+%define api.tokens.prefix "TOK_"
+%%
+start: FILE for ERROR;
+@end example
+
+@noindent
+generates the definition of the symbols @code{TOK_FILE}, @code{TOK_for},
+and @code{TOK_ERROR} in the generated source files. In particular, the
+scanner must use these prefixed token names, while the grammar itself
+may still use the short names (as in the sample rule given above). The
+generated informational files (@file{*.output}, @file{*.xml},
+@file{*.dot}) are not modified by this prefix. See @ref{Calc++ Parser}
+and @ref{Calc++ Scanner}, for a complete example.
+
+@item Accepted Values:
+Any string. Should be a valid identifier prefix in the target language,
+in other words, it should typically be an identifier itself (sequence of
+letters, underscores, and ---not at the beginning--- digits).
+
+@item Default Value:
+empty
+@end itemize
+@c api.tokens.prefix
+
+
+@c ================================================== lex_symbol
+@item lex_symbol
+@findex %define lex_symbol
+
+@itemize @bullet
+@item Language(s):
+C++
+
+@item Purpose:
+When variant-based semantic values are enabled (@pxref{C++ Variants}),
+request that symbols be handled as a whole (type, value, and possibly
+location) in the scanner. @xref{Complete Symbols}, for details.
+
+@item Accepted Values:
+Boolean.
+
+@item Default Value:
+@code{false}
+@end itemize
+@c lex_symbol
+
@c ================================================== lr.default-reductions
@item Accepted Values: Boolean
@item Default Value: @code{false}
@end itemize
+@c lr.keep-unreachable-states
@c ================================================== lr.type
@item Default Value: @code{lalr}
@end itemize
+
+@c ================================================== namespace
@item namespace
@findex %define namespace
+Obsoleted by @code{api.namespace}
+@c namespace
-@itemize
-@item Languages(s): C++
-@item Purpose: Specify the namespace for the parser class.
-For example, if you specify:
+@c ================================================== parse.assert
+@item parse.assert
+@findex %define parse.assert
-@smallexample
-%define namespace "foo::bar"
-@end smallexample
+@itemize
+@item Languages(s): C++
-Bison uses @code{foo::bar} verbatim in references such as:
+@item Purpose: Issue runtime assertions to catch invalid uses.
+In C++, when variants are used (@pxref{C++ Variants}), symbols must be
+constructed and
+destroyed properly. This option checks these constraints.
-@smallexample
-foo::bar::parser::semantic_type
-@end smallexample
+@item Accepted Values: Boolean
-However, to open a namespace, Bison removes any leading @code{::} and then
-splits on any remaining occurrences:
+@item Default Value: @code{false}
+@end itemize
+@c parse.assert
-@smallexample
-namespace foo @{ namespace bar @{
- class position;
- class location;
-@} @}
-@end smallexample
-
-@item Accepted Values: Any absolute or relative C++ namespace reference without
-a trailing @code{"::"}.
-For example, @code{"foo"} or @code{"::foo::bar"}.
-
-@item Default Value: The value specified by @code{%name-prefix}, which defaults
-to @code{yy}.
-This usage of @code{%name-prefix} is for backward compatibility and can be
-confusing since @code{%name-prefix} also specifies the textual prefix for the
-lexical analyzer function.
-Thus, if you specify @code{%name-prefix}, it is best to also specify
-@code{%define namespace} so that @code{%name-prefix} @emph{only} affects the
-lexical analyzer function.
-For example, if you specify:
-@smallexample
-%define namespace "foo"
-%name-prefix "bar::"
-@end smallexample
+@c ================================================== parse.error
+@item parse.error
+@findex %define parse.error
+@itemize
+@item Languages(s):
+all
+@item Purpose:
+Control the kind of error messages passed to the error reporting
+function. @xref{Error Reporting, ,The Error Reporting Function
+@code{yyerror}}.
+@item Accepted Values:
+@itemize
+@item @code{simple}
+Error messages passed to @code{yyerror} are simply @w{@code{"syntax
+error"}}.
+@item @code{verbose}
+Error messages report the unexpected token, and possibly the expected ones.
+However, this report can often be incorrect when LAC is not enabled
+(@pxref{LAC}).
+@end itemize
-The parser namespace is @code{foo} and @code{yylex} is referenced as
-@code{bar::lex}.
+@item Default Value:
+@code{simple}
@end itemize
+@c parse.error
+
@c ================================================== parse.lac
@item parse.lac
@item Accepted Values: @code{none}, @code{full}
@item Default Value: @code{none}
@end itemize
+@c parse.lac
+
+@c ================================================== parse.trace
+@item parse.trace
+@findex %define parse.trace
+
+@itemize
+@item Languages(s): C, C++
+
+@item Purpose: Require parser instrumentation for tracing.
+In C/C++, define the macro @code{YYDEBUG} to 1 in the parser implementation
+file if it is not already defined, so that the debugging facilities are
+compiled. @xref{Tracing, ,Tracing Your Parser}.
+
+@item Accepted Values: Boolean
+
+@item Default Value: @code{false}
@end itemize
+@c parse.trace
+
+@c ================================================== variant
+@item variant
+@findex %define variant
+
+@itemize @bullet
+@item Language(s):
+C++
+
+@item Purpose:
+Request variant-based semantic values.
+@xref{C++ Variants}.
+
+@item Accepted Values:
+Boolean.
+
+@item Default Value:
+@code{false}
+@end itemize
+@c variant
+@end table
@node %code Summary
Not all qualifiers are accepted for all target languages. Unaccepted
qualifiers produce an error. Some of the accepted qualifiers are:
-@itemize @bullet
+@table @code
@item requires
@findex %code requires
@item Location(s): The parser Java file after any Java package directive and
before any class definitions.
@end itemize
-@end itemize
+@end table
Though we say the insertion locations are language-dependent, they are
technically skeleton-dependent. Writers of non-standard skeletons
parameter information to it in a reentrant way. To do so, use the
declaration @code{%parse-param}:
-@deffn {Directive} %parse-param @{@var{argument-declaration}@}
+@deffn {Directive} %parse-param @{@var{argument-declaration}@} @dots{}
@findex %parse-param
-Declare that an argument declared by the braced-code
-@var{argument-declaration} is an additional @code{yyparse} argument.
+Declare that one or more
+@var{argument-declaration} are additional @code{yyparse} arguments.
The @var{argument-declaration} is used when declaring
functions or prototypes. The last identifier in
@var{argument-declaration} must be the argument name.
Here's an example. Write this in the parser:
@example
-%parse-param @{int *nastiness@}
-%parse-param @{int *randomness@}
+%parse-param @{int *nastiness@} @{int *randomness@}
@end example
@noindent
More user feedback will help to stabilize it.)
You call the function @code{yypush_parse} to parse a single token. This
-function is available if either the @code{%define api.push-pull push} or
-@code{%define api.push-pull both} declaration is used.
+function is available if either the @samp{%define api.push-pull push} or
+@samp{%define api.push-pull both} declaration is used.
@xref{Push Decl, ,A Push Parser}.
@deftypefun int yypush_parse (yypstate *yyps)
More user feedback will help to stabilize it.)
You call the function @code{yypull_parse} to parse the rest of the input
-stream. This function is available if the @code{%define api.push-pull both}
+stream. This function is available if the @samp{%define api.push-pull both}
declaration is used.
@xref{Push Decl, ,A Push Parser}.
More user feedback will help to stabilize it.)
You call the function @code{yypstate_new} to create a new parser instance.
-This function is available if either the @code{%define api.push-pull push} or
-@code{%define api.push-pull both} declaration is used.
+This function is available if either the @samp{%define api.push-pull push} or
+@samp{%define api.push-pull both} declaration is used.
@xref{Push Decl, ,A Push Parser}.
@deftypefun {yypstate*} yypstate_new (void)
More user feedback will help to stabilize it.)
You call the function @code{yypstate_delete} to delete a parser instance.
-function is available if either the @code{%define api.push-pull push} or
-@code{%define api.push-pull both} declaration is used.
+function is available if either the @samp{%define api.push-pull push} or
+@samp{%define api.push-pull both} declaration is used.
@xref{Push Decl, ,A Push Parser}.
@deftypefun void yypstate_delete (yypstate *yyps)
@node Pure Calling
@subsection Calling Conventions for Pure Parsers
-When you use the Bison declaration @code{%define api.pure} to request a
+When you use the Bison declaration @samp{%define api.pure} to request a
pure, reentrant parser, the global communication variables @code{yylval}
and @code{yylloc} cannot be used. (@xref{Pure Decl, ,A Pure (Reentrant)
Parser}.) In such parsers the two global variables are replaced by
this case, omit the second argument; @code{yylex} will be called with
only one argument.
-
-If you wish to pass the additional parameter data to @code{yylex}, use
+If you wish to pass additional arguments to @code{yylex}, use
@code{%lex-param} just like @code{%parse-param} (@pxref{Parser
-Function}).
+Function}). To pass additional arguments to both @code{yylex} and
+@code{yyparse}, use @code{%param}.
-@deffn {Directive} lex-param @{@var{argument-declaration}@}
+@deffn {Directive} %lex-param @{@var{argument-declaration}@} @dots{}
@findex %lex-param
-Declare that the braced-code @var{argument-declaration} is an
-additional @code{yylex} argument declaration.
+Specify that @var{argument-declaration} are additional @code{yylex} argument
+declarations. You may pass one or more such declarations, which is
+equivalent to repeating @code{%lex-param}.
+@end deffn
+
+@deffn {Directive} %param @{@var{argument-declaration}@} @dots{}
+@findex %param
+Specify that @var{argument-declaration} are additional
+@code{yylex}/@code{yyparse} argument declaration. This is equivalent to
+@samp{%lex-param @{@var{argument-declaration}@} @dots{} %parse-param
+@{@var{argument-declaration}@} @dots{}}. You may pass one or more
+declarations, which is equivalent to repeating @code{%param}.
@end deffn
For instance:
@example
-%parse-param @{int *nastiness@}
-%lex-param @{int *nastiness@}
-%parse-param @{int *randomness@}
+%lex-param @{scanner_mode *mode@}
+%parse-param @{parser_mode *mode@}
+%param @{environment_type *env@}
@end example
@noindent
- results in the following signature:
+ results in the following signatures:
@example
-int yylex (int *nastiness);
-int yyparse (int *nastiness, int *randomness);
+int yylex (scanner_mode *mode, environment_type *env);
+int yyparse (parser_mode *mode, environment_type *env);
@end example
-If @code{%define api.pure} is added:
+If @samp{%define api.pure} is added:
@example
-int yylex (YYSTYPE *lvalp, int *nastiness);
-int yyparse (int *nastiness, int *randomness);
+int yylex (YYSTYPE *lvalp, scanner_mode *mode, environment_type *env);
+int yyparse (parser_mode *mode, environment_type *env);
@end example
@noindent
-and finally, if both @code{%define api.pure} and @code{%locations} are used:
+and finally, if both @samp{%define api.pure} and @code{%locations} are used:
@example
-int yylex (YYSTYPE *lvalp, YYLTYPE *llocp, int *nastiness);
-int yyparse (int *nastiness, int *randomness);
+int yylex (YYSTYPE *lvalp, YYLTYPE *llocp,
+ scanner_mode *mode, environment_type *env);
+int yyparse (parser_mode *mode, environment_type *env);
@end example
@node Error Reporting
@cindex parse error
@cindex syntax error
-The Bison parser detects a @dfn{syntax error} or @dfn{parse error}
+The Bison parser detects a @dfn{syntax error} (or @dfn{parse error})
whenever it reads a token which cannot satisfy any syntax rule. An
action in the grammar can also explicitly proclaim an error, using the
macro @code{YYERROR} (@pxref{Action Features, ,Special Features for Use
receives one argument. For a syntax error, the string is normally
@w{@code{"syntax error"}}.
-@findex %error-verbose
-If you invoke the directive @code{%error-verbose} in the Bison declarations
+@findex %define parse.error
+If you invoke @samp{%define parse.error verbose} in the Bison declarations
section (@pxref{Bison Declarations, ,The Bison Declarations Section}), then
Bison provides a more verbose and specific error message string instead of
just plain @w{@code{"syntax error"}}. However, that message sometimes
Finally, GLR and Yacc parsers share the same @code{yyerror} calling
convention for absolutely pure parsers, i.e., when the calling
convention of @code{yylex} @emph{and} the calling convention of
-@code{%define api.pure} are pure.
+@samp{%define api.pure} are pure.
I.e.:
@example
@menu
* Why Precedence:: An example showing why precedence is needed.
-* Using Precedence:: How to specify precedence in Bison grammars.
+* Using Precedence:: How to specify precedence and associativity.
+* Precedence Only:: How to specify precedence only.
* Precedence Examples:: How these features are used in the previous example.
* How Precedence:: How they work.
@end menu
@node Using Precedence
@subsection Specifying Operator Precedence
@findex %left
-@findex %right
@findex %nonassoc
+@findex %precedence
+@findex %right
Bison allows you to specify these choices with the operator precedence
declarations @code{%left} and @code{%right}. Each such declaration
them right-associative. A third alternative is @code{%nonassoc}, which
declares that it is a syntax error to find the same operator twice ``in a
row''.
+The last alternative, @code{%precedence}, allows to define only
+precedence and no associativity at all. As a result, any
+associativity-related conflict that remains will be reported as an
+compile-time error. The directive @code{%nonassoc} creates run-time
+error: using the operator in a associative way is a syntax error. The
+directive @code{%precedence} creates compile-time errors: an operator
+@emph{can} be involved in an associativity-related conflict, contrary to
+what expected the grammar author.
The relative precedence of different operators is controlled by the
-order in which they are declared. The first @code{%left} or
-@code{%right} declaration in the file declares the operators whose
+order in which they are declared. The first precedence/associativity
+declaration in the file declares the operators whose
precedence is lowest, the next such declaration declares the operators
whose precedence is a little higher, and so on.
+@node Precedence Only
+@subsection Specifying Precedence Only
+@findex %precedence
+
+Since POSIX Yacc defines only @code{%left}, @code{%right}, and
+@code{%nonassoc}, which all defines precedence and associativity, little
+attention is paid to the fact that precedence cannot be defined without
+defining associativity. Yet, sometimes, when trying to solve a
+conflict, precedence suffices. In such a case, using @code{%left},
+@code{%right}, or @code{%nonassoc} might hide future (associativity
+related) conflicts that would remain hidden.
+
+The dangling @code{else} ambiguity (@pxref{Shift/Reduce, , Shift/Reduce
+Conflicts}) can be solved explicitly. This shift/reduce conflicts occurs
+in the following situation, where the period denotes the current parsing
+state:
+
+@example
+if @var{e1} then if @var{e2} then @var{s1} . else @var{s2}
+@end example
+
+The conflict involves the reduction of the rule @samp{IF expr THEN
+stmt}, which precedence is by default that of its last token
+(@code{THEN}), and the shifting of the token @code{ELSE}. The usual
+disambiguation (attach the @code{else} to the closest @code{if}),
+shifting must be preferred, i.e., the precedence of @code{ELSE} must be
+higher than that of @code{THEN}. But neither is expected to be involved
+in an associativity related conflict, which can be specified as follows.
+
+@example
+%precedence THEN
+%precedence ELSE
+@end example
+
+The unary-minus is another typical example where associativity is
+usually over-specified, see @ref{Infix Calc, , Infix Notation
+Calculator: @code{calc}}. The @code{%left} directive is traditionally
+used to declare the precedence of @code{NEG}, which is more than needed
+since it also defines its associativity. While this is harmless in the
+traditional example, who knows how @code{NEG} might be used in future
+evolutions of the grammar@dots{}
+
@node Precedence Examples
@subsection Precedence Examples
sign typically has a very high precedence as a unary operator, and a
somewhat lower precedence (lower than multiplication) as a binary operator.
-The Bison precedence declarations, @code{%left}, @code{%right} and
-@code{%nonassoc}, can only be used once for a given token; so a token has
+The Bison precedence declarations
+can only be used once for a given token; so a token has
only one precedence declared in this way. For context-dependent
precedence, you need to use an additional mechanism: the @code{%prec}
modifier for rules.
historical reasons, but that behavior is often not robust. For example, in
the previous section, we discussed the mysterious conflicts that can be
produced by LALR(1), Bison's default parser table construction algorithm.
-Another example is Bison's @code{%error-verbose} directive, which instructs
-the generated parser to produce verbose syntax error messages, which can
-sometimes contain incorrect information.
+Another example is Bison's @code{%define parse.error verbose} directive,
+which instructs the generated parser to produce verbose syntax error
+messages, which can sometimes contain incorrect information.
In this section, we explore several modern features of Bison that allow you
to tune fundamental aspects of the generated LR-based parsers. Some of
Do not allow @code{YYINITDEPTH} to be greater than @code{YYMAXDEPTH}.
-@c FIXME: C++ output.
-Because of semantic differences between C and C++, the deterministic
-parsers in C produced by Bison cannot grow when compiled
-by C++ compilers. In this precise case (compiling a C parser as C++) you are
-suggested to grow @code{YYINITDEPTH}. The Bison maintainers hope to fix
-this deficiency in a future release.
+You can generate a deterministic parser containing C++ user code from
+the default (C) skeleton, as well as from the C++ skeleton
+(@pxref{C++ Parsers}). However, if you do use the default skeleton
+and want to allow the parsing stack to grow,
+be careful not to use semantic types or location types that require
+non-trivial copy constructors.
+The C skeleton bypasses these constructors when copying data to
+new, larger stacks.
@node Error Recovery
@chapter Error Recovery
@item the directive @samp{%debug}
@findex %debug
-Add the @code{%debug} directive (@pxref{Decl Summary, ,Bison
-Declaration Summary}). This is a Bison extension, which will prove
-useful when Bison will output parsers for languages that don't use a
-preprocessor. Unless POSIX and Yacc portability matter to
-you, this is
-the preferred solution.
+Add the @code{%debug} directive (@pxref{Decl Summary, ,Bison Declaration
+Summary}). This Bison extension is maintained for backward
+compatibility with previous versions of Bison.
+
+@item the variable @samp{parse.trace}
+@findex %define parse.trace
+Add the @samp{%define parse.trace} directive (@pxref{%define
+Summary,,parse.trace}), or pass the @option{-Dparse.trace} option
+(@pxref{Bison Options}). This is a Bison extension, which is especially
+useful for languages that don't use a preprocessor. Unless POSIX and Yacc
+portability matter to you, this is the preferred solution.
@end table
-We suggest that you always enable the debug option so that debugging is
+We suggest that you always enable the trace option so that debugging is
always possible.
@findex YYFPRINTF
When run, @command{bison} will create several entities in the @samp{yy}
namespace.
-@findex %define namespace
-Use the @samp{%define namespace} directive to change the namespace
-name, see @ref{%define Summary,,namespace}. The various classes are
-generated in the following files:
+@findex %define api.namespace
+Use the @samp{%define api.namespace} directive to change the namespace name,
+see @ref{%define Summary,,api.namespace}. The various classes are generated
+in the following files:
@table @file
@item position.hh
@itemx location.hh
The definition of the classes @code{position} and @code{location},
-used for location tracking. @xref{C++ Location Values}.
+used for location tracking when enabled. @xref{C++ Location Values}.
@item stack.hh
An auxiliary class @code{stack} used by the parser.
@c - YYSTYPE
@c - Printer and destructor
+Bison supports two different means to handle semantic values in C++. One is
+alike the C interface, and relies on unions (@pxref{C++ Unions}). As C++
+practitioners know, unions are inconvenient in C++, therefore another
+approach is provided, based on variants (@pxref{C++ Variants}).
+
+@menu
+* C++ Unions:: Semantic values cannot be objects
+* C++ Variants:: Using objects as semantic values
+@end menu
+
+@node C++ Unions
+@subsubsection C++ Unions
+
The @code{%union} directive works as for C, see @ref{Union Decl, ,The
Collection of Value Types}. In particular it produces a genuine
-@code{union}@footnote{In the future techniques to allow complex types
-within pseudo-unions (similar to Boost variants) might be implemented to
-alleviate these issues.}, which have a few specific features in C++.
+@code{union}, which have a few specific features in C++.
@itemize @minus
@item
The type @code{YYSTYPE} is defined but its use is discouraged: rather
only means to avoid leaks. @xref{Destructor Decl, , Freeing Discarded
Symbols}.
+@node C++ Variants
+@subsubsection C++ Variants
+
+Starting with version 2.6, Bison provides a @emph{variant} based
+implementation of semantic values for C++. This alleviates all the
+limitations reported in the previous section, and in particular, object
+types can be used without pointers.
+
+To enable variant-based semantic values, set @code{%define} variable
+@code{variant} (@pxref{%define Summary,, variant}). Once this defined,
+@code{%union} is ignored, and instead of using the name of the fields of the
+@code{%union} to ``type'' the symbols, use genuine types.
+
+For instance, instead of
+
+@example
+%union
+@{
+ int ival;
+ std::string* sval;
+@}
+%token <ival> NUMBER;
+%token <sval> STRING;
+@end example
+
+@noindent
+write
+
+@example
+%token <int> NUMBER;
+%token <std::string> STRING;
+@end example
+
+@code{STRING} is no longer a pointer, which should fairly simplify the user
+actions in the grammar and in the scanner (in particular the memory
+management).
+
+Since C++ features destructors, and since it is customary to specialize
+@code{operator<<} to support uniform printing of values, variants also
+typically simplify Bison printers and destructors.
+
+Variants are stricter than unions. When based on unions, you may play any
+dirty game with @code{yylval}, say storing an @code{int}, reading a
+@code{char*}, and then storing a @code{double} in it. This is no longer
+possible with variants: they must be initialized, then assigned to, and
+eventually, destroyed.
+
+@deftypemethod {semantic_type} {T&} build<T> ()
+Initialize, but leave empty. Returns the address where the actual value may
+be stored. Requires that the variant was not initialized yet.
+@end deftypemethod
+
+@deftypemethod {semantic_type} {T&} build<T> (const T& @var{t})
+Initialize, and copy-construct from @var{t}.
+@end deftypemethod
+
+
+@strong{Warning}: We do not use Boost.Variant, for two reasons. First, it
+appeared unacceptable to require Boost on the user's machine (i.e., the
+machine on which the generated parser will be compiled, not the machine on
+which @command{bison} was run). Second, for each possible semantic value,
+Boost.Variant not only stores the value, but also a tag specifying its
+type. But the parser already ``knows'' the type of the semantic value, so
+that would be duplicating the information.
+
+Therefore we developed light-weight variants whose type tag is external (so
+they are really like @code{unions} for C++ actually). But our code is much
+less mature that Boost.Variant. So there is a number of limitations in
+(the current implementation of) variants:
+@itemize
+@item
+Alignment must be enforced: values should be aligned in memory according to
+the most demanding type. Computing the smallest alignment possible requires
+meta-programming techniques that are not currently implemented in Bison, and
+therefore, since, as far as we know, @code{double} is the most demanding
+type on all platforms, alignments are enforced for @code{double} whatever
+types are actually used. This may waste space in some cases.
+
+@item
+Our implementation is not conforming with strict aliasing rules. Alias
+analysis is a technique used in optimizing compilers to detect when two
+pointers are disjoint (they cannot ``meet''). Our implementation breaks
+some of the rules that G++ 4.4 uses in its alias analysis, so @emph{strict
+alias analysis must be disabled}. Use the option
+@option{-fno-strict-aliasing} to compile the generated parser.
+
+@item
+There might be portability issues we are not aware of.
+@end itemize
+
+As far as we know, these limitations @emph{can} be alleviated. All it takes
+is some time and/or some talented C++ hacker willing to contribute to Bison.
@node C++ Location Values
@subsection C++ Location Values
@defcv {Type} {parser} {semantic_type}
@defcvx {Type} {parser} {location_type}
-The types for semantics value and locations.
+The types for semantic values and locations (if enabled).
@end defcv
@defcv {Type} {parser} {token}
(@pxref{Calc++ Scanner}).
@end defcv
+@defcv {Type} {parser} {syntax_error}
+This class derives from @code{std::runtime_error}. Throw instances of it
+from the scanner or from the user actions to raise parse errors. This is
+equivalent with first
+invoking @code{error} to report the location and message of the syntax
+error, and then to invoke @code{YYERROR} to enter the error-recovery mode.
+But contrary to @code{YYERROR} which can only be invoked from user actions
+(i.e., written in the action itself), the exception can be thrown from
+function invoked from the user action.
+@end defcv
+
@deftypemethod {parser} {} parser (@var{type1} @var{arg1}, ...)
Build a new parser object. There are no arguments by default, unless
@samp{%parse-param @{@var{type1} @var{arg1}@}} was used.
@end deftypemethod
+@deftypemethod {syntax_error} {} syntax_error (const location_type& @var{l}, const std::string& @var{m})
+@deftypemethodx {syntax_error} {} syntax_error (const std::string& @var{m})
+Instantiate a syntax-error exception.
+@end deftypemethod
+
@deftypemethod {parser} {int} parse ()
Run the syntactic analysis, and return 0 on success, 1 otherwise.
@end deftypemethod
@end deftypemethod
@deftypemethod {parser} {void} error (const location_type& @var{l}, const std::string& @var{m})
+@deftypemethodx {parser} {void} error (const std::string& @var{m})
The definition for this member function must be supplied by the user:
the parser uses it to report a parser error occurring at @var{l},
-described by @var{m}.
+described by @var{m}. If location tracking is not enabled, the second
+signature is used.
@end deftypemethod
The parser invokes the scanner by calling @code{yylex}. Contrary to C
parsers, C++ parsers are always pure: there is no point in using the
-@code{%define api.pure} directive. Therefore the interface is as follows.
+@samp{%define api.pure} directive. The actual interface with @code{yylex}
+depends whether you use unions, or variants.
+
+@menu
+* Split Symbols:: Passing symbols as two/three components
+* Complete Symbols:: Making symbols a whole
+@end menu
+
+@node Split Symbols
+@subsubsection Split Symbols
+
+Therefore the interface is as follows.
@deftypemethod {parser} {int} yylex (semantic_type* @var{yylval}, location_type* @var{yylloc}, @var{type1} @var{arg1}, ...)
-Return the next token. Its type is the return value, its semantic
-value and location being @var{yylval} and @var{yylloc}. Invocations of
+@deftypemethodx {parser} {int} yylex (semantic_type* @var{yylval}, @var{type1} @var{arg1}, ...)
+Return the next token. Its type is the return value, its semantic value and
+location (if enabled) being @var{yylval} and @var{yylloc}. Invocations of
@samp{%lex-param @{@var{type1} @var{arg1}@}} yield additional arguments.
@end deftypemethod
+Note that when using variants, the interface for @code{yylex} is the same,
+but @code{yylval} is handled differently.
+
+Regular union-based code in Lex scanner typically look like:
+
+@example
+[0-9]+ @{
+ yylval.ival = text_to_int (yytext);
+ return yy::parser::INTEGER;
+ @}
+[a-z]+ @{
+ yylval.sval = new std::string (yytext);
+ return yy::parser::IDENTIFIER;
+ @}
+@end example
+
+Using variants, @code{yylval} is already constructed, but it is not
+initialized. So the code would look like:
+
+@example
+[0-9]+ @{
+ yylval.build<int>() = text_to_int (yytext);
+ return yy::parser::INTEGER;
+ @}
+[a-z]+ @{
+ yylval.build<std::string> = yytext;
+ return yy::parser::IDENTIFIER;
+ @}
+@end example
+
+@noindent
+or
+
+@example
+[0-9]+ @{
+ yylval.build(text_to_int (yytext));
+ return yy::parser::INTEGER;
+ @}
+[a-z]+ @{
+ yylval.build(yytext);
+ return yy::parser::IDENTIFIER;
+ @}
+@end example
+
+
+@node Complete Symbols
+@subsubsection Complete Symbols
+
+If you specified both @code{%define variant} and @code{%define lex_symbol},
+the @code{parser} class also defines the class @code{parser::symbol_type}
+which defines a @emph{complete} symbol, aggregating its type (i.e., the
+traditional value returned by @code{yylex}), its semantic value (i.e., the
+value passed in @code{yylval}, and possibly its location (@code{yylloc}).
+
+@deftypemethod {symbol_type} {} symbol_type (token_type @var{type}, const semantic_type& @var{value}, const location_type& @var{location})
+Build a complete terminal symbol which token type is @var{type}, and which
+semantic value is @var{value}. If location tracking is enabled, also pass
+the @var{location}.
+@end deftypemethod
+
+This interface is low-level and should not be used for two reasons. First,
+it is inconvenient, as you still have to build the semantic value, which is
+a variant, and second, because consistency is not enforced: as with unions,
+it is still possible to give an integer as semantic value for a string.
+
+So for each token type, Bison generates named constructors as follows.
+
+@deftypemethod {symbol_type} {} make_@var{token} (const @var{value_type}& @var{value}, const location_type& @var{location})
+@deftypemethodx {symbol_type} {} make_@var{token} (const location_type& @var{location})
+Build a complete terminal symbol for the token type @var{token} (not
+including the @code{api.tokens.prefix}) whose possible semantic value is
+@var{value} of adequate @var{value_type}. If location tracking is enabled,
+also pass the @var{location}.
+@end deftypemethod
+
+For instance, given the following declarations:
+
+@example
+%define api.tokens.prefix "TOK_"
+%token <std::string> IDENTIFIER;
+%token <int> INTEGER;
+%token COLON;
+@end example
+
+@noindent
+Bison generates the following functions:
+
+@example
+symbol_type make_IDENTIFIER(const std::string& v,
+ const location_type& l);
+symbol_type make_INTEGER(const int& v,
+ const location_type& loc);
+symbol_type make_COLON(const location_type& loc);
+@end example
+
+@noindent
+which should be used in a Lex-scanner as follows.
+
+@example
+[0-9]+ return yy::parser::make_INTEGER(text_to_int (yytext), loc);
+[a-z]+ return yy::parser::make_IDENTIFIER(yytext, loc);
+":" return yy::parser::make_COLON(loc);
+@end example
+
+Tokens that do not have an identifier are not accessible: you cannot simply
+use characters such as @code{':'}, they must be declared with @code{%token}.
@node A Complete C++ Example
@subsection A Complete C++ Example
This section demonstrates the use of a C++ parser with a simple but
complete example. This example should be available on your system,
-ready to compile, in the directory @dfn{../bison/examples/calc++}. It
+ready to compile, in the directory @dfn{.../bison/examples/calc++}. It
focuses on the use of Bison, therefore the design of the various C++
classes is very naive: no accessors, no encapsulation of members etc.
We will use a Lex scanner, and more precisely, a Flex scanner, to
-demonstrate the various interaction. A hand written scanner is
+demonstrate the various interactions. A hand-written scanner is
actually easier to interface with.
@menu
@comment file: calc++-driver.hh
@example
// Tell Flex the lexer's prototype ...
-# define YY_DECL \
- yy::calcxx_parser::token_type \
- yylex (yy::calcxx_parser::semantic_type* yylval, \
- yy::calcxx_parser::location_type* yylloc, \
- calcxx_driver& driver)
+# define YY_DECL \
+ yy::calcxx_parser::symbol_type yylex (calcxx_driver& driver)
// ... and declare it for the parser's sake.
YY_DECL;
@end example
@end example
@noindent
-To encapsulate the coordination with the Flex scanner, it is useful to
-have two members function to open and close the scanning phase.
+To encapsulate the coordination with the Flex scanner, it is useful to have
+member functions to open and close the scanning phase.
@comment file: calc++-driver.hh
@example
@comment file: calc++-driver.hh
@example
- // Run the parser. Return 0 on success.
+ // Run the parser on file F.
+ // Return 0 on success.
int parse (const std::string& f);
+ // The name of the file being parsed.
+ // Used later to pass the file name to the location tracker.
std::string file;
+ // Whether parser traces should be generated.
bool trace_parsing;
@end example
%define parser_class_name "calcxx_parser"
@end example
+@noindent
+@findex %define variant
+@findex %define lex_symbol
+This example will use genuine C++ objects as semantic values, therefore, we
+require the variant-based interface. To make sure we properly use it, we
+enable assertions. To fully benefit from type-safety and more natural
+definition of ``symbol'', we enable @code{lex_symbol}.
+
+@comment file: calc++-parser.yy
+@example
+%define variant
+%define parse.assert
+%define lex_symbol
+@end example
+
@noindent
@findex %code requires
-Then come the declarations/inclusions needed to define the
-@code{%union}. Because the parser uses the parsing driver and
-reciprocally, both cannot include the header of the other. Because the
+Then come the declarations/inclusions needed by the semantic values.
+Because the parser uses the parsing driver and reciprocally, both would like
+to include the header of the other, which is, of course, insane. This
+mutual dependency will be broken using forward declarations. Because the
driver's header needs detailed knowledge about the parser class (in
-particular its inner types), it is the parser's header which will simply
-use a forward declaration of the driver.
-@xref{%code Summary}.
+particular its inner types), it is the parser's header which will use a
+forward declaration of the driver. @xref{%code Summary}.
@comment file: calc++-parser.yy
@example
-%code requires @{
+%code requires
+@{
# include <string>
class calcxx_driver;
@}
@comment file: calc++-parser.yy
@example
// The parsing context.
-%parse-param @{ calcxx_driver& driver @}
-%lex-param @{ calcxx_driver& driver @}
+%param @{ calcxx_driver& driver @}
@end example
@noindent
-Then we request the location tracking feature, and initialize the
+Then we request location tracking, and initialize the
first location's file name. Afterward new locations are computed
relatively to the previous locations: the file name will be
-automatically propagated.
+propagated.
@comment file: calc++-parser.yy
@example
@end example
@noindent
-Use the two following directives to enable parser tracing and verbose error
+Use the following two directives to enable parser tracing and verbose error
messages. However, verbose error messages can contain incorrect information
(@pxref{LAC}).
@comment file: calc++-parser.yy
@example
-%debug
-%error-verbose
-@end example
-
-@noindent
-Semantic values cannot use ``real'' objects, but only pointers to
-them.
-
-@comment file: calc++-parser.yy
-@example
-// Symbols.
-%union
-@{
- int ival;
- std::string *sval;
-@};
+%define parse.trace
+%define parse.error verbose
@end example
@noindent
@comment file: calc++-parser.yy
@example
-%code @{
+%code
+@{
# include "calc++-driver.hh"
@}
@end example
@noindent
The token numbered as 0 corresponds to end of file; the following line
-allows for nicer error messages referring to ``end of file'' instead
-of ``$end''. Similarly user friendly named are provided for each
-symbol. Note that the tokens names are prefixed by @code{TOKEN_} to
-avoid name clashes.
+allows for nicer error messages referring to ``end of file'' instead of
+``$end''. Similarly user friendly names are provided for each symbol. To
+avoid name clashes in the generated files (@pxref{Calc++ Scanner}), prefix
+tokens with @code{TOK_} (@pxref{%define Summary,,api.tokens.prefix}).
@comment file: calc++-parser.yy
@example
-%token END 0 "end of file"
-%token ASSIGN ":="
-%token <sval> IDENTIFIER "identifier"
-%token <ival> NUMBER "number"
-%type <ival> exp
+%define api.tokens.prefix "TOK_"
+%token
+ END 0 "end of file"
+ ASSIGN ":="
+ MINUS "-"
+ PLUS "+"
+ STAR "*"
+ SLASH "/"
+ LPAREN "("
+ RPAREN ")"
+;
@end example
@noindent
-To enable memory deallocation during error recovery, use
-@code{%destructor}.
+Since we use variant-based semantic values, @code{%union} is not used, and
+both @code{%type} and @code{%token} expect genuine types, as opposed to type
+tags.
-@c FIXME: Document %printer, and mention that it takes a braced-code operand.
@comment file: calc++-parser.yy
@example
-%printer @{ yyoutput << *$$; @} "identifier"
-%destructor @{ delete $$; @} "identifier"
+%token <std::string> IDENTIFIER "identifier"
+%token <int> NUMBER "number"
+%type <int> exp
+@end example
+
+@noindent
+No @code{%destructor} is needed to enable memory deallocation during error
+recovery; the memory, for strings for instance, will be reclaimed by the
+regular destructors. All the values are printed using their
+@code{operator<<}.
-%printer @{ yyoutput << $$; @} <ival>
+@c FIXME: Document %printer, and mention that it takes a braced-code operand.
+@comment file: calc++-parser.yy
+@example
+%printer @{ yyoutput << $$; @} <*>;
@end example
@noindent
-The grammar itself is straightforward.
+The grammar itself is straightforward (@pxref{Location Tracking Calc, ,
+Location Tracking Calculator: @code{ltcalc}}).
@comment file: calc++-parser.yy
@example
| assignments assignment @{@};
assignment:
- "identifier" ":=" exp
- @{ driver.variables[*$1] = $3; delete $1; @};
-
-%left '+' '-';
-%left '*' '/';
-exp: exp '+' exp @{ $$ = $1 + $3; @}
- | exp '-' exp @{ $$ = $1 - $3; @}
- | exp '*' exp @{ $$ = $1 * $3; @}
- | exp '/' exp @{ $$ = $1 / $3; @}
- | "identifier" @{ $$ = driver.variables[*$1]; delete $1; @}
- | "number" @{ $$ = $1; @};
+ "identifier" ":=" exp @{ driver.variables[$1] = $3; @};
+
+%left "+" "-";
+%left "*" "/";
+exp:
+ exp "+" exp @{ $$ = $1 + $3; @}
+| exp "-" exp @{ $$ = $1 - $3; @}
+| exp "*" exp @{ $$ = $1 * $3; @}
+| exp "/" exp @{ $$ = $1 / $3; @}
+| "(" exp ")" @{ std::swap ($$, $2); @}
+| "identifier" @{ $$ = driver.variables[$1]; @}
+| "number" @{ std::swap ($$, $1); @};
%%
@end example
@comment file: calc++-parser.yy
@example
void
-yy::calcxx_parser::error (const yy::calcxx_parser::location_type& l,
+yy::calcxx_parser::error (const location_type& l,
const std::string& m)
@{
driver.error (l, m);
@comment file: calc++-scanner.ll
@example
%@{ /* -*- C++ -*- */
-# include <cstdlib>
# include <cerrno>
# include <climits>
+# include <cstdlib>
# include <string>
# include "calc++-driver.hh"
# include "calc++-parser.hh"
-/* Work around an incompatibility in flex (at least versions
- 2.5.31 through 2.5.33): it generates code that does
- not conform to C89. See Debian bug 333231
- <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>. */
+// Work around an incompatibility in flex (at least versions
+// 2.5.31 through 2.5.33): it generates code that does
+// not conform to C89. See Debian bug 333231
+// <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>.
# undef yywrap
# define yywrap() 1
-/* By default yylex returns int, we use token_type.
- Unfortunately yyterminate by default returns 0, which is
- not of token_type. */
-#define yyterminate() return token::END
+// The location of the current token.
+static yy::location loc;
%@}
@end example
Because there is no @code{#include}-like feature we don't need
@code{yywrap}, we don't need @code{unput} either, and we parse an
actual file, this is not an interactive session with the user.
-Finally we enable the scanner tracing features.
+Finally, we enable scanner tracing.
@comment file: calc++-scanner.ll
@example
@noindent
The following paragraph suffices to track locations accurately. Each
time @code{yylex} is invoked, the begin position is moved onto the end
-position. Then when a pattern is matched, the end position is
-advanced of its width. In case it matched ends of lines, the end
+position. Then when a pattern is matched, its width is added to the end
+column. When matching ends of lines, the end
cursor is adjusted, and each time blanks are matched, the begin cursor
is moved onto the end cursor to effectively ignore the blanks
preceding tokens. Comments would be treated equally.
@example
@group
%@{
-# define YY_USER_ACTION yylloc->columns (yyleng);
+ // Code run each time a pattern is matched.
+ # define YY_USER_ACTION loc.columns (yyleng);
%@}
@end group
%%
+@group
%@{
- yylloc->step ();
+ // Code run each time yylex is called.
+ loc.step ();
%@}
-@{blank@}+ yylloc->step ();
-[\n]+ yylloc->lines (yyleng); yylloc->step ();
+@end group
+@{blank@}+ loc.step ();
+[\n]+ loc.lines (yyleng); loc.step ();
@end example
@noindent
-The rules are simple, just note the use of the driver to report errors.
-It is convenient to use a typedef to shorten
-@code{yy::calcxx_parser::token::identifier} into
-@code{token::identifier} for instance.
+The rules are simple. The driver is used to report errors.
@comment file: calc++-scanner.ll
@example
-%@{
- typedef yy::calcxx_parser::token token;
-%@}
- /* Convert ints to the actual type of tokens. */
-[-+*/] return yy::calcxx_parser::token_type (yytext[0]);
-":=" return token::ASSIGN;
+"-" return yy::calcxx_parser::make_MINUS(loc);
+"+" return yy::calcxx_parser::make_PLUS(loc);
+"*" return yy::calcxx_parser::make_STAR(loc);
+"/" return yy::calcxx_parser::make_SLASH(loc);
+"(" return yy::calcxx_parser::make_LPAREN(loc);
+")" return yy::calcxx_parser::make_RPAREN(loc);
+":=" return yy::calcxx_parser::make_ASSIGN(loc);
+
+@group
@{int@} @{
errno = 0;
long n = strtol (yytext, NULL, 10);
if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
- driver.error (*yylloc, "integer is out of range");
- yylval->ival = n;
- return token::NUMBER;
+ driver.error (loc, "integer is out of range");
+ return yy::calcxx_parser::make_NUMBER(n, loc);
@}
-@{id@} yylval->sval = new std::string (yytext); return token::IDENTIFIER;
-. driver.error (*yylloc, "invalid character");
+@end group
+@{id@} return yy::calcxx_parser::make_IDENTIFIER(yytext, loc);
+. driver.error (loc, "invalid character");
+<<EOF>> return yy::calcxx_parser::make_END(loc);
%%
@end example
@noindent
-Finally, because the scanner related driver's member function depend
+Finally, because the scanner-related driver's member-functions depend
on the scanner's data, it is simpler to implement them in this file.
@comment file: calc++-scanner.ll
int
main (int argc, char *argv[])
@{
+ int res = 0;
calcxx_driver driver;
for (int i = 1; i < argc; ++i)
if (argv[i] == std::string ("-p"))
driver.trace_scanning = true;
else if (!driver.parse (argv[i]))
std::cout << driver.result << std::endl;
+ else
+ res = 1;
+ return res;
@}
@end group
@end example
Contrary to C parsers, Java parsers do not use global variables; the
state of the parser is always local to an instance of the parser class.
Therefore, all Java parsers are ``pure'', and the @code{%pure-parser}
-and @code{%define api.pure} directives does not do anything when used in
+and @samp{%define api.pure} directives does not do anything when used in
Java.
Push parsers are currently unsupported in Java and @code{%define
@code{%defines} directive or the @option{-d}/@option{--defines} options.
@c FIXME: Possible code change.
-Currently, support for debugging and verbose errors are always compiled
-in. Thus the @code{%debug} and @code{%token-table} directives and the
+Currently, support for tracing is always compiled
+in. Thus the @samp{%define parse.trace} and @samp{%token-table}
+directives and the
@option{-t}/@option{--debug} and @option{-k}/@option{--token-table}
options have no effect. This may change in the future to eliminate
-unused code in the generated parser, so use @code{%debug} and
-@code{%verbose-error} explicitly if needed. Also, in the future the
+unused code in the generated parser, so use @samp{%define parse.trace}
+explicitly
+if needed. Also, in the future the
@code{%token-table} directive might enable a public interface to
access the token names and codes.
+Getting a ``code too large'' error from the Java compiler means the code
+hit the 64KB bytecode per method limitation of the Java class file.
+Try reducing the amount of code in actions and static initializers;
+otherwise, report a bug so that the parser skeleton will be improved.
+
+
@node Java Semantic Values
@subsection Java Semantic Values
@c - No %union, specify type in %type/%token.
By default, the semantic stack is declared to have @code{Object} members,
which means that the class types you specify can be of any class.
To improve the type safety of the parser, you can declare the common
-superclass of all the semantic values using the @code{%define stype}
+superclass of all the semantic values using the @samp{%define stype}
directive. For example, after the following declaration:
@example
defines a class representing a @dfn{location}, a range composed of a pair of
positions (possibly spanning several files). The location class is an inner
class of the parser; the name is @code{Location} by default, and may also be
-renamed using @code{%define location_type "@var{class-name}"}.
+renamed using @samp{%define location_type "@var{class-name}"}.
The location class treats the position as a completely opaque value.
By default, the class name is @code{Position}, but this can be changed
-with @code{%define position_type "@var{class-name}"}. This class must
+with @samp{%define position_type "@var{class-name}"}. This class must
be supplied by the user.
The name of the generated parser class defaults to @code{YYParser}. The
@code{YY} prefix may be changed using the @code{%name-prefix} directive
or the @option{-p}/@option{--name-prefix} option. Alternatively, use
-@code{%define parser_class_name "@var{name}"} to give a custom name to
+@samp{%define parser_class_name "@var{name}"} to give a custom name to
the class. The interface of this class is detailed below.
By default, the parser class has package visibility. A declaration
-@code{%define public} will change to public visibility. Remember that,
+@samp{%define public} will change to public visibility. Remember that,
according to the Java language specification, the name of the @file{.java}
file should match the name of the class in this case. Similarly, you can
use @code{abstract}, @code{final} and @code{strictfp} with the
@code{%define} declaration to add other modifiers to the parser class.
+A single @samp{%define annotations "@var{annotations}"} directive can
+be used to add any number of annotations to the parser class.
The Java package name of the parser class can be specified using the
-@code{%define package} directive. The superclass and the implemented
+@samp{%define package} directive. The superclass and the implemented
interfaces of the parser class can be specified with the @code{%define
-extends} and @code{%define implements} directives.
+extends} and @samp{%define implements} directives.
The parser class defines an inner class, @code{Location}, that is used
for location tracking (see @ref{Java Location Values}), and a inner
below, all the other members and fields are preceded with a @code{yy} or
@code{YY} prefix to avoid clashes with user code.
-@c FIXME: The following constants and variables are still undocumented:
-@c @code{bisonVersion}, @code{bisonSkeleton} and @code{errorVerbose}.
-
The parser class can be extended using the @code{%parse-param}
directive. Each occurrence of the directive will add a @code{protected
final} field to the parser class, and an argument to its constructor,
which initialize them automatically.
-Token names defined by @code{%token} and the predefined @code{EOF} token
-name are added as constant fields to the parser class.
-
@deftypeop {Constructor} {YYParser} {} YYParser (@var{lex_param}, @dots{}, @var{parse_param}, @dots{})
Build a new parser object with embedded @code{%code lexer}. There are
-no parameters, unless @code{%parse-param}s and/or @code{%lex-param}s are
-used.
+no parameters, unless @code{%param}s and/or @code{%parse-param}s and/or
+@code{%lex-param}s are used.
+
+Use @code{%code init} for code added to the start of the constructor
+body. This is especially useful to initialize superclasses. Use
+@samp{%define init_throws} to specify any uncaught exceptions.
@end deftypeop
@deftypeop {Constructor} {YYParser} {} YYParser (Lexer @var{lexer}, @var{parse_param}, @dots{})
Build a new parser object using the specified scanner. There are no
-additional parameters unless @code{%parse-param}s are used.
+additional parameters unless @code{%param}s and/or @code{%parse-param}s are
+used.
If the scanner is defined by @code{%code lexer}, this constructor is
declared @code{protected} and is called automatically with a scanner
-created with the correct @code{%lex-param}s.
+created with the correct @code{%param}s and/or @code{%lex-param}s.
+
+Use @code{%code init} for code added to the start of the constructor
+body. This is especially useful to initialize superclasses. Use
+@samp{%define init_throws} to specify any uncaught exceptions.
@end deftypeop
@deftypemethod {YYParser} {boolean} parse ()
@code{false} otherwise.
@end deftypemethod
+@deftypemethod {YYParser} {boolean} getErrorVerbose ()
+@deftypemethodx {YYParser} {void} setErrorVerbose (boolean @var{verbose})
+Get or set the option to produce verbose error messages. These are only
+available with @samp{%define parse.error verbose}, which also turns on
+verbose error messages.
+@end deftypemethod
+
+@deftypemethod {YYParser} {void} yyerror (String @var{msg})
+@deftypemethodx {YYParser} {void} yyerror (Position @var{pos}, String @var{msg})
+@deftypemethodx {YYParser} {void} yyerror (Location @var{loc}, String @var{msg})
+Print an error message using the @code{yyerror} method of the scanner
+instance in use. The @code{Location} and @code{Position} parameters are
+available only if location tracking is active.
+@end deftypemethod
+
@deftypemethod {YYParser} {boolean} recovering ()
During the syntactic analysis, return @code{true} if recovering
from a syntax error.
or nonzero, full tracing.
@end deftypemethod
+@deftypecv {Constant} {YYParser} {String} {bisonVersion}
+@deftypecvx {Constant} {YYParser} {String} {bisonSkeleton}
+Identify the Bison version and skeleton used to generate this parser.
+@end deftypecv
+
@node Java Scanner Interface
@subsection Java Scanner Interface
There are two possible ways to interface a Bison-generated Java parser
with a scanner: the scanner may be defined by @code{%code lexer}, or
defined elsewhere. In either case, the scanner has to implement the
-@code{Lexer} inner interface of the parser class.
+@code{Lexer} inner interface of the parser class. This interface also
+contain constants for all user-defined token names and the predefined
+@code{EOF} token.
In the first case, the body of the scanner class is placed in
@code{%code lexer} blocks. If you want to pass parameters from the
@deftypemethod {Lexer} {void} yyerror (Location @var{loc}, String @var{msg})
This method is defined by the user to emit an error message. The first
parameter is omitted if location tracking is not active. Its type can be
-changed using @code{%define location_type "@var{class-name}".}
+changed using @samp{%define location_type "@var{class-name}".}
@end deftypemethod
@deftypemethod {Lexer} {int} yylex ()
value and location are saved and returned by the their methods in the
interface.
-Use @code{%define lex_throws} to specify any uncaught exceptions.
+Use @samp{%define lex_throws} to specify any uncaught exceptions.
Default is @code{java.io.IOException}.
@end deftypemethod
@code{yylex} returned, and the first position beyond it. These
methods are not needed unless location tracking is active.
-The return type can be changed using @code{%define position_type
+The return type can be changed using @samp{%define position_type
"@var{class-name}".}
@end deftypemethod
@deftypemethod {Lexer} {Object} getLVal ()
Return the semantic value of the last token that yylex returned.
-The return type can be changed using @code{%define stype
+The return type can be changed using @samp{%define stype
"@var{class-name}".}
@end deftypemethod
The following special constructs can be uses in Java actions.
Other analogous C action features are currently unavailable for Java.
-Use @code{%define throws} to specify any uncaught exceptions from parser
+Use @samp{%define throws} to specify any uncaught exceptions from parser
actions, and initial actions specified by @code{%initial-action}.
@defvar $@var{n}
@defvar $$
The semantic value for the grouping made by the current rule. As a
value, this is in the base type (@code{Object} or as specified by
-@code{%define stype}) as in not cast to the declared subtype because
+@samp{%define stype}) as in not cast to the declared subtype because
casts are not allowed on the left-hand side of Java assignments.
Use an explicit Java cast if the correct subtype is needed.
@xref{Java Semantic Values}.
@xref{Error Recovery}.
@end deftypefn
-@deftypefn {Function} {protected void} yyerror (String msg)
-@deftypefnx {Function} {protected void} yyerror (Position pos, String msg)
-@deftypefnx {Function} {protected void} yyerror (Location loc, String msg)
+@deftypefn {Function} {void} yyerror (String @var{msg})
+@deftypefnx {Function} {void} yyerror (Position @var{loc}, String @var{msg})
+@deftypefnx {Function} {void} yyerror (Location @var{loc}, String @var{msg})
Print an error message using the @code{yyerror} method of the scanner
-instance in use.
+instance in use. The @code{Location} and @code{Position} parameters are
+available only if location tracking is active.
@end deftypefn
@item @code{%code imports}
blocks are placed at the beginning of the Java source code. They may
include copyright notices. For a @code{package} declarations, it is
-suggested to use @code{%define package} instead.
+suggested to use @samp{%define package} instead.
@item unqualified @code{%code}
blocks are placed inside the parser class.
@deffn {Directive} %name-prefix "@var{prefix}"
The prefix of the parser class name @code{@var{prefix}Parser} if
-@code{%define parser_class_name} is not used. Default is @code{YY}.
+@samp{%define parser_class_name} is not used. Default is @code{YY}.
@xref{Java Bison Interface}.
@end deffn
@xref{Java Differences}.
@end deffn
+@deffn {Directive} {%code init} @{ @var{code} @dots{} @}
+Code inserted at the beginning of the parser constructor body.
+@xref{Java Parser Interface}.
+@end deffn
+
@deffn {Directive} {%code lexer} @{ @var{code} @dots{} @}
Code added to the body of a inner lexer class within the parser class.
@xref{Java Scanner Interface}.
@end deffn
@deffn {Directive} %@{ @var{code} @dots{} %@}
-Not supported. Use @code{%code import} instead.
+Not supported. Use @code{%code imports} instead.
@xref{Java Differences}.
@end deffn
@xref{Java Bison Interface}.
@end deffn
+@deffn {Directive} {%define annotations} "@var{annotations}"
+The Java annotations for the parser class. Default is none.
+@xref{Java Bison Interface}.
+@end deffn
+
@deffn {Directive} {%define extends} "@var{superclass}"
The superclass of the parser class. Default is none.
@xref{Java Bison Interface}.
@xref{Java Bison Interface}.
@end deffn
+@deffn {Directive} {%define init_throws} "@var{exceptions}"
+The exceptions thrown by @code{%code init} from the parser class
+constructor. Default is none.
+@xref{Java Parser Interface}.
+@end deffn
+
@deffn {Directive} {%define lex_throws} "@var{exceptions}"
The exceptions thrown by the @code{yylex} method of the lexer, a
comma-separated list. Default is @code{java.io.IOException}.
Grammar}.
@end deffn
+@deffn {Directive} %?@{@var{expression}@}
+Predicate actions. This is a type of action clause that may appear in
+rules. The expression is evaluated, and if false, causes a syntax error. In
+GLR parsers during nondeterministic operation,
+this silently causes an alternative parse to die. During deterministic
+operation, it is the same as the effect of YYERROR.
+@xref{Semantic Predicates}.
+
+This feature is experimental.
+More user feedback will help to determine whether it should become a permanent
+feature.
+@end deffn
+
@deffn {Construct} /*@dots{}*/
Comment delimiters, as in C.
@end deffn
@end deffn
@deffn {Directive} %error-verbose
-Bison declaration to request verbose, specific error message strings
-when @code{yyerror} is called. @xref{Error Reporting}.
+An obsolete directive standing for @samp{%define parse.error verbose}
+(@pxref{Error Reporting, ,The Error Reporting Function @code{yyerror}}).
@end deffn
@deffn {Directive} %file-prefix "@var{prefix}"
@end deffn
@deffn {Directive} %left
-Bison declaration to assign left associativity to token(s).
+Bison declaration to assign precedence and left associativity to token(s).
@xref{Precedence Decl, ,Operator Precedence}.
@end deffn
-@deffn {Directive} %lex-param @{@var{argument-declaration}@}
-Bison declaration to specifying an additional parameter that
+@deffn {Directive} %lex-param @{@var{argument-declaration}@} @dots{}
+Bison declaration to specifying additional arguments that
@code{yylex} should accept. @xref{Pure Calling,, Calling Conventions
for Pure Parsers}.
@end deffn
@end deffn
@deffn {Directive} %nonassoc
-Bison declaration to assign nonassociativity to token(s).
+Bison declaration to assign precedence and nonassociativity to token(s).
@xref{Precedence Decl, ,Operator Precedence}.
@end deffn
@xref{Decl Summary}.
@end deffn
-@deffn {Directive} %parse-param @{@var{argument-declaration}@}
-Bison declaration to specifying an additional parameter that
-@code{yyparse} should accept. @xref{Parser Function,, The Parser
-Function @code{yyparse}}.
+@deffn {Directive} %param @{@var{argument-declaration}@} @dots{}
+Bison declaration to specify additional arguments that both
+@code{yylex} and @code{yyparse} should accept. @xref{Parser Function,, The
+Parser Function @code{yyparse}}.
+@end deffn
+
+@deffn {Directive} %parse-param @{@var{argument-declaration}@} @dots{}
+Bison declaration to specify additional arguments that @code{yyparse}
+should accept. @xref{Parser Function,, The Parser Function @code{yyparse}}.
@end deffn
@deffn {Directive} %prec
@xref{Contextual Precedence, ,Context-Dependent Precedence}.
@end deffn
+@deffn {Directive} %precedence
+Bison declaration to assign precedence to token(s), but no associativity
+@xref{Precedence Decl, ,Operator Precedence}.
+@end deffn
+
@deffn {Directive} %pure-parser
-Deprecated version of @code{%define api.pure} (@pxref{%define
+Deprecated version of @samp{%define api.pure} (@pxref{%define
Summary,,api.pure}), for which Bison is more careful to warn about
unreasonable usage.
@end deffn
@end deffn
@deffn {Directive} %right
-Bison declaration to assign right associativity to token(s).
+Bison declaration to assign precedence and right associativity to token(s).
@xref{Precedence Decl, ,Operator Precedence}.
@end deffn
@deffn {Function} yyerror
User-supplied function to be called by @code{yyparse} on error.
-@xref{Error Reporting, ,The Error
-Reporting Function @code{yyerror}}.
+@xref{Error Reporting, ,The Error Reporting Function @code{yyerror}}.
@end deffn
@deffn {Macro} YYERROR_VERBOSE
-An obsolete macro that you define with @code{#define} in the prologue
-to request verbose, specific error message strings
-when @code{yyerror} is called. It doesn't matter what definition you
-use for @code{YYERROR_VERBOSE}, just whether you define it. Using
-@code{%error-verbose} is preferred. @xref{Error Reporting}.
+An obsolete macro used in the @file{yacc.c} skeleton, that you define
+with @code{#define} in the prologue to request verbose, specific error
+message strings when @code{yyerror} is called. It doesn't matter what
+definition you use for @code{YYERROR_VERBOSE}, just whether you define
+it. Using @samp{%define parse.error verbose} is preferred
+(@pxref{Error Reporting, ,The Error Reporting Function @code{yyerror}}).
@end deffn
@deffn {Macro} YYFPRINTF
#include <config.h>
#include "system.h"
+#include <concat-filename.h>
#include <configmake.h>
-#include <error.h>
+#include <filename.h>
#include <get-errno.h>
#include <quotearg.h>
#include <spawn-pipe.h>
`-------------------------------------------------------------------*/
-#define GENERATE_MUSCLE_INSERT_TABLE(Name, Type) \
- \
-static void \
-Name (char const *name, \
- Type *table_data, \
- Type first, \
- int begin, \
- int end) \
-{ \
- Type min = first; \
- Type max = first; \
- long int lmin; \
- long int lmax; \
- int i; \
- int j = 1; \
- \
- obstack_fgrow1 (&format_obstack, "%6d", first); \
- for (i = begin; i < end; ++i) \
- { \
- obstack_1grow (&format_obstack, ','); \
- if (j >= 10) \
- { \
- obstack_sgrow (&format_obstack, "\n "); \
- j = 1; \
- } \
- else \
- ++j; \
- obstack_fgrow1 (&format_obstack, "%6d", table_data[i]); \
- if (table_data[i] < min) \
- min = table_data[i]; \
- if (max < table_data[i]) \
- max = table_data[i]; \
- } \
- obstack_1grow (&format_obstack, 0); \
- muscle_insert (name, obstack_finish (&format_obstack)); \
- \
- lmin = min; \
- lmax = max; \
- /* Build `NAME_min' and `NAME_max' in the obstack. */ \
- obstack_fgrow1 (&format_obstack, "%s_min", name); \
- obstack_1grow (&format_obstack, 0); \
- MUSCLE_INSERT_LONG_INT (obstack_finish (&format_obstack), lmin); \
- obstack_fgrow1 (&format_obstack, "%s_max", name); \
- obstack_1grow (&format_obstack, 0); \
- MUSCLE_INSERT_LONG_INT (obstack_finish (&format_obstack), lmax); \
+#define GENERATE_MUSCLE_INSERT_TABLE(Name, Type) \
+ \
+static void \
+Name (char const *name, \
+ Type *table_data, \
+ Type first, \
+ int begin, \
+ int end) \
+{ \
+ Type min = first; \
+ Type max = first; \
+ long int lmin; \
+ long int lmax; \
+ int i; \
+ int j = 1; \
+ \
+ obstack_fgrow1 (&format_obstack, "%6d", first); \
+ for (i = begin; i < end; ++i) \
+ { \
+ obstack_1grow (&format_obstack, ','); \
+ if (j >= 10) \
+ { \
+ obstack_sgrow (&format_obstack, "\n "); \
+ j = 1; \
+ } \
+ else \
+ ++j; \
+ obstack_fgrow1 (&format_obstack, "%6d", table_data[i]); \
+ if (table_data[i] < min) \
+ min = table_data[i]; \
+ if (max < table_data[i]) \
+ max = table_data[i]; \
+ } \
+ obstack_1grow (&format_obstack, 0); \
+ muscle_insert (name, obstack_finish (&format_obstack)); \
+ \
+ lmin = min; \
+ lmax = max; \
+ /* Build `NAME_min' and `NAME_max' in the obstack. */ \
+ obstack_fgrow1 (&format_obstack, "%s_min", name); \
+ obstack_1grow (&format_obstack, 0); \
+ MUSCLE_INSERT_LONG_INT (obstack_finish (&format_obstack), lmin); \
+ obstack_fgrow1 (&format_obstack, "%s_max", name); \
+ obstack_1grow (&format_obstack, 0); \
+ MUSCLE_INSERT_LONG_INT (obstack_finish (&format_obstack), lmax); \
}
GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_unsigned_int_table, unsigned int)
GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_base_table, base_number)
GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_rule_number_table, rule_number)
GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_symbol_number_table, symbol_number)
-GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_item_number_table, item_number)
GENERATE_MUSCLE_INSERT_TABLE(muscle_insert_state_number_table, state_number)
MUSCLE_INSERT_BOOL ("token_table", token_table_flag);
MUSCLE_INSERT_INT ("tokens_number", ntokens);
MUSCLE_INSERT_INT ("nterms_number", nvars);
+ MUSCLE_INSERT_INT ("symbols_number", nsyms);
MUSCLE_INSERT_INT ("undef_token_number", undeftoken->number);
MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number);
muscle_insert_symbol_number_table ("translate",
- token_translations,
- token_translations[0],
- 1, max_user_token_number + 1);
+ token_translations,
+ token_translations[0],
+ 1, max_user_token_number + 1);
/* tname -- token names. */
{
set_quoting_flags (qo, QA_SPLIT_TRIGRAPHS);
for (i = 0; i < nsyms; i++)
{
- char *cp = quotearg_alloc (symbols[i]->tag, -1, qo);
- /* Width of the next token, including the two quotes, the
- comma and the space. */
- int width = strlen (cp) + 2;
-
- if (j + width > 75)
- {
- obstack_sgrow (&format_obstack, "\n ");
- j = 1;
- }
-
- if (i)
- obstack_1grow (&format_obstack, ' ');
- MUSCLE_OBSTACK_SGROW (&format_obstack, cp);
+ char *cp = quotearg_alloc (symbols[i]->tag, -1, qo);
+ /* Width of the next token, including the two quotes, the
+ comma and the space. */
+ int width = strlen (cp) + 2;
+
+ if (j + width > 75)
+ {
+ obstack_sgrow (&format_obstack, "\n ");
+ j = 1;
+ }
+
+ if (i)
+ obstack_1grow (&format_obstack, ' ');
+ MUSCLE_OBSTACK_SGROW (&format_obstack, cp);
free (cp);
- obstack_1grow (&format_obstack, ',');
- j += width;
+ obstack_1grow (&format_obstack, ',');
+ j += width;
}
free (qo);
obstack_sgrow (&format_obstack, " ]b4_null[");
for (i = 0; i < ntokens; ++i)
values[i] = symbols[i]->user_token_number;
muscle_insert_int_table ("toknum", values,
- values[0], 1, ntokens);
+ values[0], 1, ntokens);
free (values);
}
}
-/*-------------------------------------------------------------.
-| Prepare the muscles related to the rules: rhs, prhs, r1, r2, |
-| rline, dprec, merger. |
-`-------------------------------------------------------------*/
+/*----------------------------------------------------------------.
+| Prepare the muscles related to the rules: r1, r2, rline, dprec, |
+| merger, immediate. |
+`----------------------------------------------------------------*/
static void
prepare_rules (void)
{
- rule_number r;
- unsigned int i = 0;
- item_number *rhs = xnmalloc (nritems, sizeof *rhs);
- unsigned int *prhs = xnmalloc (nrules, sizeof *prhs);
unsigned int *rline = xnmalloc (nrules, sizeof *rline);
symbol_number *r1 = xnmalloc (nrules, sizeof *r1);
unsigned int *r2 = xnmalloc (nrules, sizeof *r2);
int *dprec = xnmalloc (nrules, sizeof *dprec);
int *merger = xnmalloc (nrules, sizeof *merger);
+ int *immediate = xnmalloc (nrules, sizeof *immediate);
+ rule_number r;
for (r = 0; r < nrules; ++r)
{
- item_number *rhsp = NULL;
- /* Index of rule R in RHS. */
- prhs[r] = i;
- /* RHS of the rule R. */
- for (rhsp = rules[r].rhs; *rhsp >= 0; ++rhsp)
- rhs[i++] = *rhsp;
/* LHS of the rule R. */
r1[r] = rules[r].lhs->number;
/* Length of rule R's RHS. */
- r2[r] = i - prhs[r];
- /* Separator in RHS. */
- rhs[i++] = -1;
+ r2[r] = rule_rhs_length(&rules[r]);
/* Line where rule was defined. */
rline[r] = rules[r].location.start.line;
/* Dynamic precedence (GLR). */
dprec[r] = rules[r].dprec;
/* Merger-function index (GLR). */
merger[r] = rules[r].merger;
+ /* Immediate reduction flags (GLR). */
+ immediate[r] = rules[r].is_predicate;
}
- aver (i == nritems);
- muscle_insert_item_number_table ("rhs", rhs, ritem[0], 1, nritems);
- muscle_insert_unsigned_int_table ("prhs", prhs, 0, 0, nrules);
muscle_insert_unsigned_int_table ("rline", rline, 0, 0, nrules);
muscle_insert_symbol_number_table ("r1", r1, 0, 0, nrules);
muscle_insert_unsigned_int_table ("r2", r2, 0, 0, nrules);
muscle_insert_int_table ("dprec", dprec, 0, 0, nrules);
muscle_insert_int_table ("merger", merger, 0, 0, nrules);
+ muscle_insert_int_table ("immediate", immediate, 0, 0, nrules);
MUSCLE_INSERT_INT ("rules_number", nrules);
MUSCLE_INSERT_INT ("max_left_semantic_context", max_left_semantic_context);
- free (rhs);
- free (prhs);
free (rline);
free (r1);
free (r2);
free (dprec);
free (merger);
+ free (immediate);
}
/*--------------------------------------------.
for (i = 0; i < nstates; ++i)
values[i] = states[i]->accessing_symbol;
muscle_insert_symbol_number_table ("stos", values,
- 0, 1, nstates);
+ 0, 1, nstates);
free (values);
MUSCLE_INSERT_INT ("last", high);
}
+/*-------------------------------------------------------.
+| Compare two symbols by type-name, and then by number. |
+`-------------------------------------------------------*/
+
+static int
+symbol_type_name_cmp (const symbol **lhs, const symbol **rhs)
+{
+ int res = UNIQSTR_CMP((*lhs)->type_name, (*rhs)->type_name);
+ if (res)
+ return res;
+ return (*lhs)->number - (*rhs)->number;
+}
+
+
+/*----------------------------------------------------------------.
+| Return a (malloc'ed) table of the symbols sorted by type-name. |
+`----------------------------------------------------------------*/
+
+static symbol **
+symbols_by_type_name (void)
+{
+ typedef int (*qcmp_type) (const void *, const void *);
+ symbol **res = xmemdup (symbols, nsyms * sizeof *res);
+ qsort (res, nsyms, sizeof *res, (qcmp_type) &symbol_type_name_cmp);
+ return res;
+}
+
+
+/*------------------------------------------------------------------.
+| Define b4_type_names, which is a list of (lists of the numbers of |
+| symbols with same type-name). |
+`------------------------------------------------------------------*/
+
+static void
+type_names_output (FILE *out)
+{
+ int i;
+ symbol **syms = symbols_by_type_name ();
+ fputs ("m4_define([b4_type_names],\n[", out);
+ for (i = 0; i < nsyms; /* nothing */)
+ {
+ // The index of the first symbol of the current type-name.
+ int i0 = i;
+ fputs (i ? ",\n[" : "[", out);
+ for (; i < nsyms && syms[i]->type_name == syms[i0]->type_name; ++i)
+ fprintf (out, "%s%d", i != i0 ? ", " : "", syms[i]->number);
+ fputs ("]", out);
+ }
+ fputs ("])\n\n", out);
+ free (syms);
+}
+
+
+/*-------------------------------------.
+| The list of all the symbol numbers. |
+`-------------------------------------*/
+
+static void
+symbol_numbers_output (FILE *out)
+{
+ int i;
+ fputs ("m4_define([b4_symbol_numbers],\n[", out);
+ for (i = 0; i < nsyms; ++i)
+ fprintf (out, "%s[%d]", i ? ", " : "", i);
+ fputs ("])\n\n", out);
+}
+
/*---------------------------------.
| Output the user actions to OUT. |
for (r = 0; r < nrules; ++r)
if (rules[r].action)
{
- fprintf (out, "b4_case(%d, [b4_syncline(%d, ", r + 1,
- rules[r].action_location.start.line);
- escaped_output (out, rules[r].action_location.start.file);
- fprintf (out, ")\n[ %s]])\n\n", rules[r].action);
+ fprintf (out, "b4_%scase(%d, [b4_syncline(%d, ",
+ rules[r].is_predicate ? "predicate_" : "",
+ r + 1, rules[r].action_location.start.line);
+ escaped_output (out, rules[r].action_location.start.file);
+ fprintf (out, ")\n[ %s]])\n\n", rules[r].action);
}
fputs ("])\n\n", out);
}
-/*--------------------------------------.
-| Output the merge functions to OUT. |
-`--------------------------------------*/
+/*------------------------------------.
+| Output the merge functions to OUT. |
+`------------------------------------*/
static void
merger_output (FILE *out)
for (n = 1, p = merge_functions; p != NULL; n += 1, p = p->next)
{
if (p->type[0] == '\0')
- fprintf (out, " case %d: *yy0 = %s (*yy0, *yy1); break;\n",
- n, p->name);
+ fprintf (out, " case %d: *yy0 = %s (*yy0, *yy1); break;\n",
+ n, p->name);
else
- fprintf (out, " case %d: yy0->%s = %s (*yy0, *yy1); break;\n",
- n, p->type, p->name);
+ fprintf (out, " case %d: yy0->%s = %s (*yy0, *yy1); break;\n",
+ n, p->type, p->name);
}
fputs ("]])\n\n", out);
}
+
+/*---------------------------------------------.
+| Prepare the muscles for symbol definitions. |
+`---------------------------------------------*/
+
+static void
+prepare_symbol_definitions (void)
+{
+ int i;
+ for (i = 0; i < nsyms; ++i)
+ {
+ symbol *sym = symbols[i];
+ const char *key;
+ const char *value;
+
+#define SET_KEY(Entry) \
+ obstack_fgrow2 (&format_obstack, "symbol(%d, %s)", \
+ i, Entry); \
+ obstack_1grow (&format_obstack, 0); \
+ key = obstack_finish (&format_obstack);
+
+#define SET_KEY2(Entry, Suffix) \
+ obstack_fgrow3 (&format_obstack, "symbol(%d, %s_%s)", \
+ i, Entry, Suffix); \
+ obstack_1grow (&format_obstack, 0); \
+ key = obstack_finish (&format_obstack);
+
+ // Whether the symbol has an identifier.
+ value = symbol_id_get (sym);
+ SET_KEY("has_id");
+ MUSCLE_INSERT_INT (key, !!value);
+
+ // Its identifier.
+ SET_KEY("id");
+ MUSCLE_INSERT_STRING (key, value ? value : "");
+
+ // Its tag. Typically for documentation purpose.
+ SET_KEY("tag");
+ MUSCLE_INSERT_STRING (key, sym->tag);
+
+ SET_KEY("user_number");
+ MUSCLE_INSERT_INT (key, sym->user_token_number);
+
+ SET_KEY("is_token");
+ MUSCLE_INSERT_INT (key,
+ i < ntokens && sym != errtoken && sym != undeftoken);
+
+ SET_KEY("number");
+ MUSCLE_INSERT_INT (key, sym->number);
+
+ SET_KEY("has_type");
+ MUSCLE_INSERT_INT (key, !!sym->type_name);
+
+ SET_KEY("type");
+ MUSCLE_INSERT_STRING (key, sym->type_name ? sym->type_name : "");
+
+ {
+ int j;
+ for (j = 0; j < CODE_PROPS_SIZE; ++j)
+ {
+ char const *pname = code_props_type_string (j);
+ code_props const *p = symbol_code_props_get (sym, j);
+ SET_KEY2("has", pname);
+ MUSCLE_INSERT_INT (key, !!p->code);
+
+ if (p->code)
+ {
+ SET_KEY2(pname, "file");
+ MUSCLE_INSERT_STRING (key, p->location.start.file);
+
+ SET_KEY2(pname, "line");
+ MUSCLE_INSERT_INT (key, p->location.start.line);
+
+ SET_KEY(pname);
+ MUSCLE_INSERT_STRING_RAW (key, p->code);
+ }
+ }
+ }
+#undef SET_KEY2
+#undef SET_KEY
+ }
+}
+
+
/*--------------------------------------.
| Output the tokens definition to OUT. |
`--------------------------------------*/
{
symbol *sym = symbols[i];
int number = sym->user_token_number;
+ uniqstr id = symbol_id_get (sym);
/* At this stage, if there are literal string aliases, they are
part of SYMBOLS, so we should not find their aliased symbols
here. */
aver (number != USER_NUMBER_HAS_STRING_ALIAS);
- /* Skip error token. */
- if (sym == errtoken)
- continue;
-
- /* If this string has an alias, then it is necessarily the alias
- which is to be output. */
- if (sym->alias)
- sym = sym->alias;
-
- /* Don't output literal chars or strings (when defined only as a
- string). Note that must be done after the alias resolution:
- think about `%token 'f' "f"'. */
- if (sym->tag[0] == '\'' || sym->tag[0] == '\"')
- continue;
-
- /* Don't #define nonliteral tokens whose names contain periods,
- dashes or '$' (as does the default value of the EOF token). */
- if (mbschr (sym->tag, '.')
- || mbschr (sym->tag, '-')
- || mbschr (sym->tag, '$'))
- continue;
-
- fprintf (out, "%s[[[%s]], %d]",
- sep, sym->tag, number);
- sep = ",\n";
- }
- fputs ("])\n\n", out);
-}
-
-
-/*---------------------------------------------------.
-| Output the symbol destructors or printers to OUT. |
-`---------------------------------------------------*/
-
-static void
-symbol_code_props_output (FILE *out, char const *what,
- code_props const *(*get)(symbol const *))
-{
- int i;
- char const *sep = "";
-
- fputs ("m4_define([b4_symbol_", out);
- fputs (what, out);
- fputs ("], \n[", out);
- for (i = 0; i < nsyms; ++i)
- {
- symbol *sym = symbols[i];
- char const *code = (*get) (sym)->code;
- if (code)
+ /* Skip error token and tokens without identifier. */
+ if (sym != errtoken && id)
{
- location loc = (*get) (sym)->location;
- /* Filename, lineno,
- Symbol-name, Symbol-number,
- code, optional typename. */
- fprintf (out, "%s[", sep);
+ fprintf (out, "%s[[[%s]], %d]",
+ sep, id, number);
sep = ",\n";
- escaped_output (out, loc.start.file);
- fprintf (out, ", %d, ", loc.start.line);
- escaped_output (out, sym->tag);
- fprintf (out, ", %d, [[%s]]", sym->number, code);
- if (sym->type_name)
- fprintf (out, ", [[%s]]", sym->type_name);
- fputc (']', out);
}
}
fputs ("])\n\n", out);
lookahead token type. */
muscle_insert_rule_number_table ("defact", yydefact,
- yydefact[0], 1, nstates);
+ yydefact[0], 1, nstates);
/* Figure out what to do after reducing with each rule, depending on
the saved state from before the beginning of parsing the data
that matched this rule. */
muscle_insert_state_number_table ("defgoto", yydefgoto,
- yydefgoto[0], 1, nsyms - ntokens);
+ yydefgoto[0], 1, nsyms - ntokens);
/* Output PACT. */
muscle_insert_base_table ("pact", base,
- base[0], 1, nstates);
+ base[0], 1, nstates);
MUSCLE_INSERT_INT ("pact_ninf", base_ninf);
/* Output PGOTO. */
muscle_insert_base_table ("pgoto", base,
- base[nstates], nstates + 1, nvectors);
+ base[nstates], nstates + 1, nvectors);
muscle_insert_base_table ("table", table,
- table[0], 1, high + 1);
+ table[0], 1, high + 1);
MUSCLE_INSERT_INT ("table_ninf", table_ninf);
muscle_insert_base_table ("check", check,
- check[0], 1, high + 1);
+ check[0], 1, high + 1);
/* GLR parsing slightly modifies YYTABLE and YYCHECK (and thus
YYPACT) so that in states with unresolved conflicts, the default
that case. Nevertheless, it seems even better to be able to use
the GLR skeletons even without the non-deterministic tables. */
muscle_insert_unsigned_int_table ("conflict_list_heads", conflict_table,
- conflict_table[0], 1, high + 1);
+ conflict_table[0], 1, high + 1);
muscle_insert_unsigned_int_table ("conflicting_rules", conflict_list,
- 0, 1, conflict_list_cnt);
+ 0, 1, conflict_list_cnt);
}
+
/*--------------------------------------------.
| Output the definitions of all the muscles. |
`--------------------------------------------*/
muscles_output (FILE *out)
{
fputs ("m4_init()\n", out);
-
- user_actions_output (out);
merger_output (out);
+ symbol_numbers_output (out);
token_definitions_output (out);
- symbol_code_props_output (out, "destructors", &symbol_destructor_get);
- symbol_code_props_output (out, "printers", &symbol_printer_get);
-
+ type_names_output (out);
+ user_actions_output (out);
+ // Must be last.
muscles_m4_output (out);
}
\f
static void
output_skeleton (void)
{
- FILE *in;
int filter_fd[2];
- char const *argv[10];
pid_t pid;
/* Compute the names of the package data dir and skeleton files. */
- char const m4sugar[] = "m4sugar/m4sugar.m4";
- char const m4bison[] = "bison.m4";
- char *full_m4sugar;
- char *full_m4bison;
- char *full_skeleton;
- char const *p;
- char const *m4 = (p = getenv ("M4")) ? p : M4;
- char const *pkgdatadir = compute_pkgdatadir ();
- size_t skeleton_size = strlen (skeleton) + 1;
- size_t pkgdatadirlen = strlen (pkgdatadir);
- while (pkgdatadirlen && pkgdatadir[pkgdatadirlen - 1] == '/')
- pkgdatadirlen--;
- full_skeleton = xmalloc (pkgdatadirlen + 1
- + (skeleton_size < sizeof m4sugar
- ? sizeof m4sugar : skeleton_size));
- memcpy (full_skeleton, pkgdatadir, pkgdatadirlen);
- full_skeleton[pkgdatadirlen] = '/';
- strcpy (full_skeleton + pkgdatadirlen + 1, m4sugar);
- full_m4sugar = xstrdup (full_skeleton);
- strcpy (full_skeleton + pkgdatadirlen + 1, m4bison);
- full_m4bison = xstrdup (full_skeleton);
- if (mbschr (skeleton, '/'))
- strcpy (full_skeleton, skeleton);
- else
- strcpy (full_skeleton + pkgdatadirlen + 1, skeleton);
+ char const *m4 = (m4 = getenv ("M4")) ? m4 : M4;
+ char const *datadir = pkgdatadir ();
+ char *m4sugar = xconcatenated_filename (datadir, "m4sugar/m4sugar.m4", NULL);
+ char *m4bison = xconcatenated_filename (datadir, "bison.m4", NULL);
+ char *skel = (IS_PATH_WITH_DIR (skeleton)
- ? xstrdup (skeleton)
- : xconcatenated_filename (datadir, skeleton, NULL));
++ ? xstrdup (skeleton)
++ : xconcatenated_filename (datadir, skeleton, NULL));
/* Test whether m4sugar.m4 is readable, to check for proper
installation. A faulty installation can cause deadlock, so a
cheap sanity check is worthwhile. */
- xfclose (xfopen (full_m4sugar, "r"));
+ xfclose (xfopen (m4sugar, "r"));
/* Create an m4 subprocess connected to us via two pipes. */
if (trace_flag & trace_tools)
fprintf (stderr, "running: %s %s - %s %s\n",
- m4, full_m4sugar, full_m4bison, full_skeleton);
+ m4, m4sugar, m4bison, skel);
/* Some future version of GNU M4 (most likely 1.6) may treat the -dV in a
position-dependent manner. Keep it as the first argument so that all
<http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html>
for details. */
{
+ char const *argv[10];
int i = 0;
argv[i++] = m4;
argv[i++] = M4_GNU_OPTION;
argv[i++] = "-I";
- argv[i++] = pkgdatadir;
+ argv[i++] = datadir;
if (trace_flag & trace_m4)
argv[i++] = "-dV";
- argv[i++] = full_m4sugar;
+ argv[i++] = m4sugar;
argv[i++] = "-";
- argv[i++] = full_m4bison;
- argv[i++] = full_skeleton;
+ argv[i++] = m4bison;
+ argv[i++] = skel;
argv[i++] = NULL;
aver (i <= ARRAY_CARDINALITY (argv));
+
+ /* The ugly cast is because gnulib gets the const-ness wrong. */
+ pid = create_pipe_bidi ("m4", m4, (char **)(void*)argv, false, true,
+ true, filter_fd);
}
- /* The ugly cast is because gnulib gets the const-ness wrong. */
- pid = create_pipe_bidi ("m4", m4, (char **)(void*)argv, false, true,
- true, filter_fd);
- free (full_m4sugar);
- free (full_m4bison);
- free (full_skeleton);
+ free (m4sugar);
+ free (m4bison);
+ free (skel);
if (trace_flag & trace_muscles)
muscles_output (stderr);
{
- FILE *out = fdopen (filter_fd[1], "w");
- if (! out)
- error (EXIT_FAILURE, get_errno (),
- "fdopen");
+ FILE *out = xfdopen (filter_fd[1], "w");
muscles_output (out);
xfclose (out);
}
/* Read and process m4's output. */
timevar_push (TV_M4);
- in = fdopen (filter_fd[0], "r");
- if (! in)
- error (EXIT_FAILURE, get_errno (),
- "fdopen");
- scan_skel (in);
- /* scan_skel should have read all of M4's output. Otherwise, when we
- close the pipe, we risk letting M4 report a broken-pipe to the
- Bison user. */
- aver (feof (in));
- xfclose (in);
+ {
+ FILE *in = xfdopen (filter_fd[0], "r");
+ scan_skel (in);
+ /* scan_skel should have read all of M4's output. Otherwise, when we
+ close the pipe, we risk letting M4 report a broken-pipe to the
+ Bison user. */
+ aver (feof (in));
+ xfclose (in);
+ }
wait_subprocess (pid, "m4", false, false, true, true, NULL);
timevar_pop (TV_M4);
}
static void
prepare (void)
{
- /* BISON_USE_PUSH_FOR_PULL is for the test suite and should not be documented
- for the user. */
- char const *use_push_for_pull_env = getenv ("BISON_USE_PUSH_FOR_PULL");
- bool use_push_for_pull_flag = false;
- if (use_push_for_pull_env != NULL
- && use_push_for_pull_env[0] != '\0'
- && 0 != strcmp (use_push_for_pull_env, "0"))
- use_push_for_pull_flag = true;
+ /* BISON_USE_PUSH_FOR_PULL is for the test suite and should not be
+ documented for the user. */
+ char const *cp = getenv ("BISON_USE_PUSH_FOR_PULL");
+ bool use_push_for_pull_flag = cp && *cp && strtol (cp, 0, 10);
/* Flags. */
- MUSCLE_INSERT_BOOL ("debug_flag", debug_flag);
MUSCLE_INSERT_BOOL ("defines_flag", defines_flag);
- MUSCLE_INSERT_BOOL ("error_verbose_flag", error_verbose);
MUSCLE_INSERT_BOOL ("glr_flag", glr_parser);
- MUSCLE_INSERT_BOOL ("locations_flag", locations_flag);
MUSCLE_INSERT_BOOL ("nondeterministic_flag", nondeterministic_parser);
MUSCLE_INSERT_BOOL ("synclines_flag", !no_lines_flag);
MUSCLE_INSERT_BOOL ("tag_seen_flag", tag_seen);
/* b4_pkgdatadir is used inside m4_include in the skeletons, so digraphs
would never be expanded. Hopefully no one has M4-special characters in
his Bison installation path. */
- MUSCLE_INSERT_STRING_RAW ("pkgdatadir", compute_pkgdatadir ());
+ MUSCLE_INSERT_STRING_RAW ("pkgdatadir", pkgdatadir ());
}
}
prepare_rules ();
prepare_states ();
prepare_actions ();
+ prepare_symbol_definitions ();
prepare ();
}
char const *
-compute_pkgdatadir (void)
+pkgdatadir (void)
{
- char const *pkgdatadir = getenv ("BISON_PKGDATADIR");
- return pkgdatadir ? pkgdatadir : PKGDATADIR;
+ char const *cp = getenv ("BISON_PKGDATADIR");
+ return cp ? cp : PKGDATADIR;
}
AT_BISON_OPTION_PUSHDEFS
AT_DATA_GRAMMAR([[input.y]],
-[[%error-verbose
+[[%define parse.error verbose
%debug
%{
]AT_YYERROR_DECLARE[
AT_BISON_OPTION_PUSHDEFS
AT_DATA_GRAMMAR([[input.y]],
-[[%error-verbose
+[[%define parse.error verbose
%debug
%{
]AT_YYERROR_DECLARE[
AT_DATA_GRAMMAR([[input.y]],
[[
%{
-#include <stdio.h>
+# include <stdio.h>
]AT_YYERROR_DECLARE[
]AT_YYLEX_DECLARE[
typedef struct { int val; } stype;
sum: { printf ("%d\n", $0.val + $-1.val + $-2.val); } ;
%%
-
- static int
- yylex (void)
- {
- return 0;
- }
-
]AT_YYERROR_DEFINE[
+ ]AT_YYLEX_DEFINE()[
int
main (void)
{
}])
AT_LALR1_CC_IF([%define global_tokens_and_yystype])
m4_ifval([$6], [[%code provides {]], [[%code {]])
- AT_LALR1_CC_IF([typedef yy::location YYLTYPE;])
- [static int yylex (]AT_LEX_FORMALS[);
+ AT_LALR1_CC_IF([typedef yy::location YYLTYPE;])[
+ ]AT_YYLEX_DECLARE[
]AT_LALR1_CC_IF([], [AT_YYERROR_DECLARE])
[}
printf ("input (%d@%d-%d): /* Nothing */\n", $$, RANGE (@$));
}
| line input /* Right recursive to load the stack so that popping at
- END can be exercised. */
+ END can be exercised. */
{
$$ = 2;
printf ("input (%d@%d-%d): line (%d@%d-%d) input (%d@%d-%d)\n",
- $$, RANGE (@$), $1, RANGE (@1), $2, RANGE (@2));
+ $$, RANGE (@$), $1, RANGE (@1), $2, RANGE (@2));
}
;
/* Alias to ARGV[1]. */
const char *source = YY_NULL;
- static int
- yylex (]AT_LEX_FORMALS[)
+ static
+ ]AT_YYLEX_PROTOTYPE[
{
static unsigned int counter = 0;
$3
_AT_CHECK_PRINTER_AND_DESTRUCTOR($[1], $[2], $[3], $[4],
-[%error-verbose
+[%define parse.error verbose
%debug
%verbose
%locations
AT_SETUP([Default tagless %printer and %destructor])
AT_BISON_OPTION_PUSHDEFS([%locations])
AT_DATA_GRAMMAR([[input.y]],
-[[%error-verbose
+[[%define parse.error verbose
%debug
%locations
%initial-action {
Shifting token 'd' (1.4-1.4: <> printer for 'd' @ 4)
Entering state 6
Reading a token: Now at end of input.
- syntax error, unexpected $end, expecting 'e'
+ 1.5-4: syntax error, unexpected $end, expecting 'e'
Error: popping token 'd' (1.4-1.4: <> printer for 'd' @ 4)
Stack now 0 1 3 5
Error: popping token 'c' (1.3-1.3: 'b'/'c' printer for 'c' @ 3)
AT_SETUP([Default tagged and per-type %printer and %destructor])
AT_BISON_OPTION_PUSHDEFS
AT_DATA_GRAMMAR([[input.y]],
-[[%error-verbose
+[[%define parse.error verbose
%debug
%{
AT_BISON_OPTION_PUSHDEFS([%locations])
AT_DATA_GRAMMAR([[input]]$1[[.y]],
-[[%error-verbose
+[[%define parse.error verbose
%debug
%locations
%initial-action {
start: test2 test1 test0 testc;
test2
-: 'a' { semi; /* TEST:N:2 */ }
-| 'b' { if (0) {no_semi} /* TEST:N:2 */ }
-| 'c' { if (0) {semi;} /* TEST:N:2 */ }
-| 'd' { semi; no_semi /* TEST:Y:2 */ }
-| 'e' { semi(); no_semi() /* TEST:Y:2 */ }
-| 'f' { semi[]; no_semi[] /* TEST:Y:2 */ }
-| 'g' { semi++; no_semi++ /* TEST:Y:2 */ }
-| 'h' { {no_semi} no_semi /* TEST:Y:2 */ }
-| 'i' { {semi;} no_semi /* TEST:Y:2 */ }
+: 'a' { semi; /* TEST:N:2 */ }
+| 'b' { if (0) {no_semi} /* TEST:N:2 */ }
+| 'c' { if (0) {semi;} /* TEST:N:2 */ }
+| 'd' { semi; no_semi /* TEST:Y:2 */ }
+| 'e' { semi(); no_semi() /* TEST:Y:2 */ }
+| 'f' { semi[]; no_semi[] /* TEST:Y:2 */ }
+| 'g' { semi++; no_semi++ /* TEST:Y:2 */ }
+| 'h' { {no_semi} no_semi /* TEST:Y:2 */ }
+| 'i' { {semi;} no_semi /* TEST:Y:2 */ }
;
test1
- : 'a' { semi; // TEST:N:1 ;
-} | 'b' { if (0) {no_semi} // TEST:N:1 ;
-} | 'c' { if (0) {semi;} // TEST:N:1 ;
-} | 'd' { semi; no_semi // TEST:Y:1 ;
-} | 'e' { semi(); no_semi() // TEST:Y:1 ;
-} | 'f' { semi[]; no_semi[] // TEST:Y:1 ;
-} | 'g' { semi++; no_semi++ // TEST:Y:1 ;
-} | 'h' { {no_semi} no_semi // TEST:Y:1 ;
-} | 'i' { {semi;} no_semi // TEST:Y:1 ;
+ : 'a' { semi; // TEST:N:1 ;
+} | 'b' { if (0) {no_semi} // TEST:N:1 ;
+} | 'c' { if (0) {semi;} // TEST:N:1 ;
+} | 'd' { semi; no_semi // TEST:Y:1 ;
+} | 'e' { semi(); no_semi() // TEST:Y:1 ;
+} | 'f' { semi[]; no_semi[] // TEST:Y:1 ;
+} | 'g' { semi++; no_semi++ // TEST:Y:1 ;
+} | 'h' { {no_semi} no_semi // TEST:Y:1 ;
+} | 'i' { {semi;} no_semi // TEST:Y:1 ;
} ;
test0
- : 'a' { semi; // TEST:N:1 {}
-} | 'b' { if (0) {no_semi} // TEST:N:1 {}
-} | 'c' { if (0) {semi;} // TEST:N:1 {}
-} | 'd' { semi; no_semi // TEST:Y:1 {}
-} | 'e' { semi(); no_semi() // TEST:Y:1 {}
-} | 'f' { semi[]; no_semi[] // TEST:Y:1 {}
-} | 'g' { semi++; no_semi++ // TEST:Y:1 {}
-} | 'h' { {no_semi} no_semi // TEST:Y:1 {}
-} | 'i' { {semi;} no_semi // TEST:Y:1 {}
+ : 'a' { semi; // TEST:N:1 {}
+} | 'b' { if (0) {no_semi} // TEST:N:1 {}
+} | 'c' { if (0) {semi;} // TEST:N:1 {}
+} | 'd' { semi; no_semi // TEST:Y:1 {}
+} | 'e' { semi(); no_semi() // TEST:Y:1 {}
+} | 'f' { semi[]; no_semi[] // TEST:Y:1 {}
+} | 'g' { semi++; no_semi++ // TEST:Y:1 {}
+} | 'h' { {no_semi} no_semi // TEST:Y:1 {}
+} | 'i' { {semi;} no_semi // TEST:Y:1 {}
} ;
testc
m4_pushdef([AT_CALC_LEX],
[[#include <ctype.h>
- int ]AT_NAME_PREFIX[lex (]AT_LEX_FORMALS[);
- static int get_char (]AT_LEX_FORMALS[);
- static void unget_char (]AT_LEX_PRE_FORMALS[ int c);
+ ]AT_YYLEX_DECLARE_EXTERN[
+ static int get_char (]AT_YYLEX_FORMALS[);
+ static void unget_char (]AT_YYLEX_PRE_FORMALS[ int c);
]AT_LOCATION_IF([
static YYLTYPE last_yylloc;
])[
static int
- get_char (]AT_LEX_FORMALS[)
+ get_char (]AT_YYLEX_FORMALS[)
{
int res = getc (input);
]AT_USE_LEX_ARGS[;
}
static void
- unget_char (]AT_LEX_PRE_FORMALS[ int c)
+ unget_char (]AT_YYLEX_PRE_FORMALS[ int c)
{
]AT_USE_LEX_ARGS[;
]AT_LOCATION_IF([
}
static int
- read_signed_integer (]AT_LEX_FORMALS[)
+ read_signed_integer (]AT_YYLEX_FORMALS[)
{
- int c = get_char (]AT_LEX_ARGS[);
+ int c = get_char (]AT_YYLEX_ARGS[);
int sign = 1;
int n = 0;
]AT_USE_LEX_ARGS[;
if (c == '-')
{
- c = get_char (]AT_LEX_ARGS[);
+ c = get_char (]AT_YYLEX_ARGS[);
sign = -1;
}
while (isdigit (c))
{
n = 10 * n + (c - '0');
- c = get_char (]AT_LEX_ARGS[);
+ c = get_char (]AT_YYLEX_ARGS[);
}
- unget_char (]AT_LEX_PRE_ARGS[ c);
+ unget_char (]AT_YYLEX_PRE_ARGS[ c);
return sign * n;
}
| blanks and tabs, returns 0 for EOF. |
`---------------------------------------------------------------*/
- int
- ]AT_NAME_PREFIX[lex (]AT_LEX_FORMALS[)
+ ]AT_YYLEX_PROTOTYPE[
{
static int init = 1;
int c;
AT_LOC_FIRST_LINE = AT_LOC_LAST_LINE;
])[
}
- while ((c = get_char (]AT_LEX_ARGS[)) == ' ' || c == '\t');
+ while ((c = get_char (]AT_YYLEX_ARGS[)) == ' ' || c == '\t');
/* process numbers */
if (c == '.' || isdigit (c))
{
- unget_char (]AT_LEX_PRE_ARGS[ c);
- ]AT_VAL[.ival = read_signed_integer (]AT_LEX_ARGS[);
+ unget_char (]AT_YYLEX_PRE_ARGS[ c);
+ ]AT_VAL[.ival = read_signed_integer (]AT_YYLEX_ARGS[);
- return NUM;
+ return ]AT_TOKEN_PREFIX[NUM;
}
/* Return end-of-file. */
if (c == EOF)
- return CALC_EOF;
+ return ]AT_TOKEN_PREFIX[CALC_EOF;
/* Return single chars. */
return c;
static int power (int base, int exponent);
]AT_SKEL_CC_IF(,
- [/* yyerror receives the location if:
- - %location & %pure & %glr
- - %location & %pure & %yacc & %parse-param. */
- static void yyerror (AT_YYERROR_ARG_LOC_IF([YYLTYPE *llocp, ])
+ [static void yyerror (AT_YYERROR_ARG_LOC_IF([YYLTYPE *llocp, ])
AT_PARAM_IF([semantic_value *result, int *count, ])
const char *s
);])[
- int yylex (]AT_LEX_FORMALS[);
+ ]AT_YYLEX_DECLARE_EXTERN[
}
-]AT_SKEL_CC_IF([AT_LOCATION_TYPE_IF([], [
+]AT_SKEL_CC_IF([AT_LOCATION_IF([AT_LOCATION_TYPE_IF([], [
/* The lalr1.cc skeleton, for backward compatibility, defines
a constructor for position that initializes the filename. The
glr.cc skeleton does not (and in fact cannot: location/position
are stored in a union, from which objects with constructors are
- excluded in C++. */
+ excluded in C++). */
%initial-action {
@$.initialize ();
}
-])])[
+])])])[
/* Bison Declarations */
%token CALC_EOF 0 "end of input"
%token <ival> NUM "number"
%type <ival> exp
-%nonassoc '=' /* comparison */
+%nonassoc '=' /* comparison */
%left '-' '+'
%left '*' '/'
-%left NEG /* negation--unary minus */
-%right '^' /* exponentiation */
+%precedence NEG /* negation--unary minus */
+%right '^' /* exponentiation */
/* Grammar follows */
%%
return o;
}
]])
-
- /* A C++ error reporting function. */
- void
- AT_NAME_PREFIX::parser::error (AT_LOCATION_IF([const location_type& l, ])const std::string& m)
- {
- std::cerr << AT_LOCATION_IF([l << ": " << ])m << std::endl;
- }
- ],
+ AT_YYERROR_DEFINE],
[/* A C error reporting function. */
static void
yyerror (AT_YYERROR_ARG_LOC_IF([YYLTYPE *llocp, ])
# If BISON-OPTIONS contains `%location', then make sure the ERROR-LOCATION
# is correctly output on stderr.
#
-# If BISON-OPTIONS contains `%error-verbose', then make sure the
+# If BISON-OPTIONS contains `%define parse.error verbose', then make sure the
# IF-YYERROR-VERBOSE message is properly output after `syntax error, '
# on STDERR.
#
[[sed 's/^[-0-9.]*: //' expout >at-expout
mv at-expout expout]])
# 4. If error-verbose is not used, strip the`, unexpected....' part.
-m4_bmatch([$1], [%error-verbose], [],
+m4_bmatch([$1], [%define parse.error verbose], [],
[[sed 's/syntax error, .*$/syntax error/' expout >at-expout
mv at-expout expout]])
# 5. Check
])
- # AT_CHECK_CALC([BISON-OPTIONS, [EXPECTED-TO-FAIL]])
- # --------------------------------------------------
+ # AT_CHECK_CALC([BISON-OPTIONS])
+ # ------------------------------
# Start a testing chunk which compiles `calc' grammar with
# BISON-OPTIONS, and performs several tests over the parser.
- # However, if EXPECTED-TO-FAIL is nonempty, this test is expected to fail.
m4_define([AT_CHECK_CALC],
- [# We use integers to avoid dependencies upon the precision of doubles.
- AT_SETUP([Calculator $1])
+ [m4_ifval([$2], [m4_fatal([$0: expected a single argument])])
- m4_ifval([$2], [AT_CHECK([exit 77])])
+ # We use integers to avoid dependencies upon the precision of doubles.
+ AT_SETUP([Calculator $1])
AT_BISON_OPTION_PUSHDEFS([$1])
AT_CHECK_CALC_LALR([%name-prefix="calc"]) dnl test deprecated `='
AT_CHECK_CALC_LALR([%verbose])
AT_CHECK_CALC_LALR([%yacc])
-AT_CHECK_CALC_LALR([%error-verbose])
+AT_CHECK_CALC_LALR([%define parse.error verbose])
AT_CHECK_CALC_LALR([%define api.pure %locations])
AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure %locations])
-AT_CHECK_CALC_LALR([%error-verbose %locations])
+AT_CHECK_CALC_LALR([%define parse.error verbose %locations])
-AT_CHECK_CALC_LALR([%error-verbose %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define parse.error verbose %locations %defines %name-prefix "calc" %define api.tokens.prefix "TOK_" %verbose %yacc])
AT_CHECK_CALC_LALR([%debug])
-AT_CHECK_CALC_LALR([%error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR([%define api.pure %error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure %error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR([%define api.push-pull both %define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR([%define api.pure %error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_LALR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
# ----------------------- #
AT_CHECK_CALC_GLR([%name-prefix "calc"])
AT_CHECK_CALC_GLR([%verbose])
AT_CHECK_CALC_GLR([%yacc])
-AT_CHECK_CALC_GLR([%error-verbose])
+AT_CHECK_CALC_GLR([%define parse.error verbose])
AT_CHECK_CALC_GLR([%define api.pure %locations])
-AT_CHECK_CALC_GLR([%error-verbose %locations])
+AT_CHECK_CALC_GLR([%define parse.error verbose %locations])
-AT_CHECK_CALC_GLR([%error-verbose %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR([%define parse.error verbose %locations %defines %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR([%debug])
-AT_CHECK_CALC_GLR([%error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR([%define parse.error verbose %debug %locations %defines %name-prefix "calc" %define api.tokens.prefix "TOK_" %verbose %yacc])
-AT_CHECK_CALC_GLR([%define api.pure %error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_GLR([%define api.pure %error-verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_GLR([%define api.pure %define parse.error verbose %debug %locations %defines %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
# ----------------------------- #
# 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([%language "C++" %defines %locations] $@)])
+[AT_CHECK_CALC([%language "C++" %defines] $@)])
AT_CHECK_CALC_LALR1_CC([])
-AT_CHECK_CALC_LALR1_CC([%define location_type Span])
-AT_CHECK_CALC_LALR1_CC([%error-verbose %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR1_CC([%error-verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR1_CC([%locations])
+AT_CHECK_CALC_LALR1_CC([%locations %define location_type Span])
+AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR1_CC([%pure-parser %error-verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR1_CC([%locations %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_LALR1_CC([%pure-parser %error-verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_LALR1_CC([%locations %pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_LALR1_CC([%locations %pure-parser %define parse.error verbose %debug %name-prefix "calc" %define api.tokens.prefix "TOK_" %verbose %yacc])
+
+AT_CHECK_CALC_LALR1_CC([%locations %pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
AT_CHECK_CALC_GLR_CC([])
AT_CHECK_CALC_GLR_CC([%define location_type Span])
-AT_CHECK_CALC_GLR_CC([%error-verbose %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%define parse.error verbose %name-prefix "calc" %verbose %yacc])
AT_CHECK_CALC_GLR_CC([%debug])
-AT_CHECK_CALC_GLR_CC([%error-verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
-AT_CHECK_CALC_GLR_CC([%pure-parser %error-verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc])
+AT_CHECK_CALC_GLR_CC([%pure-parser %define parse.error verbose %debug %name-prefix "calc" %define api.tokens.prefix "TOK_" %verbose %yacc])
-AT_CHECK_CALC_GLR_CC([%pure-parser %error-verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
+AT_CHECK_CALC_GLR_CC([%pure-parser %define parse.error verbose %debug %name-prefix "calc" %verbose %yacc %parse-param {semantic_value *result} %parse-param {int *count}])
# _AT_DATA_JAVA_CALC_Y($1, $2, $3, [BISON-DIRECTIVES])
-# ----------------------------------------------------------------------
+# ----------------------------------------------------
# Produce `calc.y'. Don't call this macro directly, because it contains
# some occurrences of `$1' etc. which will be interpreted by m4. So
# you should call it with $1, $2, and $3 as arguments, which is what
m4_define([_AT_DATA_JAVA_CALC_Y],
[m4_if([$1$2$3], $[1]$[2]$[3], [],
[m4_fatal([$0: Invalid arguments: $@])])dnl
+ AT_BISON_OPTION_PUSHDEFS([%language "Java" $4])
AT_DATA([Calc.y],
[[/* Infix notation calculator--calc */
%language "Java"
public Position getEndPos() {
return yypos;
}
-
- public void yyerror (Calc.Location l, String s)
- {
- if (l == null)
- System.err.println (s);
- else
- System.err.println (l + ": " + s);
- }
- ]], [[
- public void yyerror (String s)
- {
- System.err.println (s);
- }
]])[
+ ]AT_YYERROR_DEFINE[
Integer yylval;
]AT_LOCATION_IF([[yypos = new Position (yypos.lineno (),
yypos.token () + 1);]])[
if (ttype == st.TT_EOF)
- return Calc.EOF;
+ return EOF;
else if (ttype == st.TT_EOL)
{
else if (ttype == st.TT_WORD)
{
yylval = new Integer (st.sval);
- return Calc.NUM;
+ return NUM;
}
else
}
]])
+ AT_BISON_OPTION_POPDEFS
])# _AT_DATA_JAVA_CALC_Y
# _AT_CHECK_JAVA_CALC_ERROR(BISON-OPTIONS, INPUT,
# [VERBOSE-AND-LOCATED-ERROR-MESSAGE])
- # ---------------------------------------------------------
+ # --------------------------------------------------------------
# Run `calc' on INPUT, and expect a `syntax error' message.
#
# If INPUT starts with a slash, it is used as absolute input file name,
])
# _AT_CHECK_JAVA_CALC([BISON-DIRECTIVES], [BISON-CODE])
-# -----------------------------------------------------------------------
+# -----------------------------------------------------
# Start a testing chunk which compiles `calc' grammar with
# BISON-DIRECTIVES, and performs several tests over the parser.
m4_define([_AT_CHECK_JAVA_CALC],
# AT_CHECK_JAVA_CALC([BISON-DIRECTIVES])
-# --------------------------------------------------------
+# --------------------------------------
# Start a testing chunk which compiles `calc' grammar with
# BISON-DIRECTIVES, and performs several tests over the parser.
# Run the test with and without %error-verbose.
%debug
%error-verbose
%token-table
+%token END "end"
$1
%%
-start: "end" {$2};
+start: END {$2};
%%
class m4_default([$3], [Position]) {}
])
# Check that YYParser.java contains exactly COUNT lines matching ^LINE$
# with grep.
m4_define([AT_CHECK_JAVA_GREP],
- [AT_CHECK([grep -c '^$1$' YYParser.java], [], [m4_default([$2], [1])
+ [AT_CHECK([grep -c '^$1$' YYParser.java], [], [m4_default([$2], [1])
])
])
-# ----------------------------------- #
-# Java parser class and package names #
-# ----------------------------------- #
+# ------------------------------------- #
+# Java parser class and package names. #
+# ------------------------------------- #
AT_SETUP([Java parser class and package names])
AT_CHECK_JAVA_MINIMAL([[%name-prefix "Prefix"]])
AT_CHECK_JAVA_GREP([[class PrefixParser]])
+AT_CHECK_JAVA_MINIMAL([[%define api.tokens.prefix "TOK_"]])
+AT_CHECK_JAVA_GREP([[.*TOK_END.*]])
+
AT_CHECK_JAVA_MINIMAL([[%define parser_class_name "ParserClassName"]])
AT_CHECK_JAVA_GREP([[class ParserClassName]])
AT_CLEANUP
-# --------------------------- #
-# Java parser class modifiers #
-# --------------------------- #
+# ----------------------------- #
+# Java parser class modifiers. #
+# ----------------------------- #
AT_SETUP([Java parser class modifiers])
%define strictfp]])
AT_CHECK_JAVA_GREP([[public final strictfp class YYParser]])
+# FIXME: Can't do a Java compile because javacomp.sh is configured for 1.3
+AT_CHECK_JAVA_MINIMAL([[
+%define annotations "/*@Deprecated @SupressWarnings(\"unchecked\") @SupressWarnings({\"unchecked\", \"deprecation\"}) @SupressWarnings(value={\"unchecked\", \"deprecation\"})*/"
+%define public]])
+AT_CHECK_JAVA_GREP([[/\*@Deprecated @SupressWarnings("unchecked") @SupressWarnings({"unchecked", "deprecation"}) @SupressWarnings(value={"unchecked", "deprecation"})\*/ public class YYParser]])
+
AT_CLEANUP
AT_SETUP([Java %parse-param and %lex-param])
AT_CHECK_JAVA_MINIMAL([])
-AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer) {]])
+AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer) *]])
AT_CHECK_JAVA_MINIMAL([[%parse-param {int parse_param1}]])
AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer, *int parse_param1) {]])
-AT_CHECK_JAVA_GREP([[[ ]*this.parse_param1 = parse_param1;]])
+AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer, *int parse_param1) *]])
+AT_CHECK_JAVA_GREP([[ *this.parse_param1 = parse_param1;]])
AT_CHECK_JAVA_MINIMAL([[
%parse-param {int parse_param1}
%parse-param {long parse_param2}]])
AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
AT_CHECK_JAVA_GREP([[ *protected final long parse_param2;]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) {]])
-AT_CHECK_JAVA_GREP([[[ ]*this.parse_param1 = parse_param1;]])
-AT_CHECK_JAVA_GREP([[[ ]*this.parse_param2 = parse_param2;]])
+AT_CHECK_JAVA_GREP([[ *public YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) *]])
+AT_CHECK_JAVA_GREP([[ *this.parse_param1 = parse_param1;]])
+AT_CHECK_JAVA_GREP([[ *this.parse_param2 = parse_param2;]])
AT_CHECK_JAVA_MINIMAL_W_LEXER([], [], [[return EOF;]])
-AT_CHECK_JAVA_GREP([[ *public YYParser () {]])
-AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer) {]])
+AT_CHECK_JAVA_GREP([[ *public YYParser () *]])
+AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer) *]])
AT_CHECK_JAVA_MINIMAL_W_LEXER([[%parse-param {int parse_param1}]],
- [], [[return EOF;]])
+ [], [[return EOF;]])
AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (int parse_param1) {]])
-AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1) {]])
-AT_CHECK_JAVA_GREP([[[ ]*this.parse_param1 = parse_param1;]], [2])
+AT_CHECK_JAVA_GREP([[ *public YYParser (int parse_param1) *]])
+AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1) *]])
+AT_CHECK_JAVA_GREP([[ *this.parse_param1 = parse_param1;]], [2])
AT_CHECK_JAVA_MINIMAL_W_LEXER([[
%parse-param {int parse_param1}
%parse-param {long parse_param2}]],
- [], [[return EOF;]])
+ [], [[return EOF;]])
AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
AT_CHECK_JAVA_GREP([[ *protected final long parse_param2;]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (int parse_param1, *long parse_param2) {]])
-AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) {]])
-AT_CHECK_JAVA_GREP([[[ ]*this.parse_param1 = parse_param1;]], [2])
-AT_CHECK_JAVA_GREP([[[ ]*this.parse_param2 = parse_param2;]], [2])
+AT_CHECK_JAVA_GREP([[ *public YYParser (int parse_param1, *long parse_param2) *]])
+AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) *]])
+AT_CHECK_JAVA_GREP([[ *this.parse_param1 = parse_param1;]], [2])
+AT_CHECK_JAVA_GREP([[ *this.parse_param2 = parse_param2;]], [2])
AT_CHECK_JAVA_MINIMAL_W_LEXER([[%lex-param {char lex_param1}]],
- [], [[return EOF;]], [[YYLexer (char lex_param1) {}]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1) {]])
+ [], [[return EOF;]], [[YYLexer (char lex_param1) {}]])
+AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1) *]])
AT_CHECK_JAVA_GREP([[.* = new YYLexer *(lex_param1);]])
AT_CHECK_JAVA_MINIMAL_W_LEXER([[
%lex-param {char lex_param1}
%lex-param {short lex_param2}]],
- [], [[return EOF;]], [[YYLexer (char lex_param1, short lex_param2) {}]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1, *short lex_param2) {]])
+ [], [[return EOF;]], [[YYLexer (char lex_param1, short lex_param2) {}]])
+AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1, *short lex_param2) *]])
AT_CHECK_JAVA_GREP([[.* = new YYLexer *(lex_param1, *lex_param2);]])
AT_CHECK_JAVA_MINIMAL_W_LEXER([[
%parse-param {long parse_param2}
%lex-param {char lex_param1}
%lex-param {short lex_param2}]],
- [], [[return EOF;]], [[YYLexer (char lex_param1, short lex_param2) {}]])
+ [], [[return EOF;]], [[YYLexer (char lex_param1, short lex_param2) {}]])
AT_CHECK_JAVA_GREP([[ *protected final int parse_param1;]])
AT_CHECK_JAVA_GREP([[ *protected final long parse_param2;]])
-AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1, *short lex_param2, *int parse_param1, *long parse_param2) {]])
+AT_CHECK_JAVA_GREP([[ *public YYParser (char lex_param1, *short lex_param2, *int parse_param1, *long parse_param2) *]])
AT_CHECK_JAVA_GREP([[.* = new YYLexer *(lex_param1, *lex_param2);]])
-AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) {]])
-AT_CHECK_JAVA_GREP([[[ ]*this.parse_param1 = parse_param1;]], [2])
-AT_CHECK_JAVA_GREP([[[ ]*this.parse_param2 = parse_param2;]], [2])
+AT_CHECK_JAVA_GREP([[ *protected YYParser (Lexer yylexer, *int parse_param1, *long parse_param2) *]])
+AT_CHECK_JAVA_GREP([[ *this.parse_param1 = parse_param1;]], [2])
+AT_CHECK_JAVA_GREP([[ *this.parse_param2 = parse_param2;]], [2])
AT_CLEANUP
AT_SETUP([Java throws specifications])
-# %define throws - 0 1 2
-# %define lex-throws - 0 1 2
-# %code lexer 0 1
+# %define throws - 0 1 2
+# %define lex-throws - 0 1 2
+# %code lexer 0 1
m4_define([AT_JT_lex_throws_define], [m4_case(AT_JT_lex_throws,
- -1, [],
- 0, [[%define lex_throws ""]],
- 1, [[%define lex_throws "InterruptedException"]],
- 2, [[%define lex_throws "InterruptedException, IllegalAccessException"]])])
+ -1, [],
+ 0, [[%define lex_throws ""]],
+ 1, [[%define lex_throws "InterruptedException"]],
+ 2, [[%define lex_throws "InterruptedException, IllegalAccessException"]])])
m4_define([AT_JT_yylex_throws], [m4_case(AT_JT_lex_throws,
- -1, [[ throws java.io.IOException]],
- 0, [],
- 1, [[ throws InterruptedException]],
- 2, [[ throws InterruptedException, IllegalAccessException]])])
+ -1, [[ throws java.io.IOException]],
+ 0, [],
+ 1, [[ throws InterruptedException]],
+ 2, [[ throws InterruptedException, IllegalAccessException]])])
m4_define([AT_JT_yylex_action], [m4_case(AT_JT_lex_throws,
- -1, [[throw new java.io.IOException();]],
- 0, [[return EOF;]],
- 1, [[throw new InterruptedException();]],
- 2, [[throw new IllegalAccessException();]])])
+ -1, [[throw new java.io.IOException();]],
+ 0, [[return EOF;]],
+ 1, [[throw new InterruptedException();]],
+ 2, [[throw new IllegalAccessException();]])])
m4_define([AT_JT_throws_define], [m4_case(AT_JT_throws,
- -1, [],
- 0, [[%define throws ""]],
- 1, [[%define throws "ClassNotFoundException"]],
- 2, [[%define throws "ClassNotFoundException, InstantiationException"]])])
+ -1, [],
+ 0, [[%define throws ""]],
+ 1, [[%define throws "ClassNotFoundException"]],
+ 2, [[%define throws "ClassNotFoundException, InstantiationException"]])])
m4_define([AT_JT_yyaction_throws], [m4_case(AT_JT_throws,
- -1, [],
- 0, [],
- 1, [[ throws ClassNotFoundException]],
- 2, [[ throws ClassNotFoundException, InstantiationException]])])
+ -1, [],
+ 0, [],
+ 1, [[ throws ClassNotFoundException]],
+ 2, [[ throws ClassNotFoundException, InstantiationException]])])
m4_define([AT_JT_parse_throws_2], [m4_case(AT_JT_throws,
- -1, [],
- 0, [],
- 1, [[, ClassNotFoundException]],
- 2, [[, ClassNotFoundException, InstantiationException]])])
+ -1, [],
+ 0, [],
+ 1, [[, ClassNotFoundException]],
+ 2, [[, ClassNotFoundException, InstantiationException]])])
m4_define([AT_JT_parse_throws],
- [m4_if(m4_quote(AT_JT_yylex_throws), [],
- [AT_JT_yyaction_throws],
- [AT_JT_yylex_throws[]AT_JT_parse_throws_2])])
+ [m4_if(m4_quote(AT_JT_yylex_throws), [],
+ [AT_JT_yyaction_throws],
+ [AT_JT_yylex_throws[]AT_JT_parse_throws_2])])
m4_define([AT_JT_initial_action], [m4_case(AT_JT_throws,
- -1, [],
- 0, [],
- 1, [[%initial-action {if (true) throw new ClassNotFoundException();}]],
- 2, [[%initial-action {if (true) throw new InstantiationException();}]])])
+ -1, [],
+ 0, [],
+ 1, [[%initial-action {if (true) throw new ClassNotFoundException();}]],
+ 2, [[%initial-action {if (true) throw new InstantiationException();}]])])
m4_define([AT_JT_parse_action], [m4_case(AT_JT_throws,
- -1, [],
- 0, [],
- 1, [[throw new ClassNotFoundException();]],
- 2, [[throw new ClassNotFoundException();]])])
+ -1, [],
+ 0, [],
+ 1, [[throw new ClassNotFoundException();]],
+ 2, [[throw new ClassNotFoundException();]])])
m4_for([AT_JT_lexer], 0, 1, 1,
[m4_for([AT_JT_lex_throws], -1, 2, 1,
[m4_for([AT_JT_throws], -1, 2, 1,
[m4_if(AT_JT_lexer, 0,
- [AT_CHECK_JAVA_MINIMAL([
+ [AT_CHECK_JAVA_MINIMAL([
AT_JT_throws_define
AT_JT_lex_throws_define
AT_JT_initial_action],
[AT_JT_parse_action])],
- [AT_CHECK_JAVA_MINIMAL_W_LEXER([
+ [AT_CHECK_JAVA_MINIMAL_W_LEXER([
AT_JT_throws_define
AT_JT_lex_throws_define
AT_JT_initial_action],
AT_CLEANUP
+# ------------------------------------- #
+# Java constructor init and init_throws #
+# ------------------------------------- #
+
+AT_SETUP([Java constructor init and init_throws])
+
+AT_CHECK_JAVA_MINIMAL([[
+%define extends "Thread"
+%code init { super("Test Thread"); if (true) throw new InterruptedException(); }
+%define init_throws "InterruptedException"
+%lex-param {int lex_param}]])
+AT_CHECK([[grep -q 'super("Test Thread"); if (true) throw new InterruptedException();' YYParser.java]])
+
+AT_CHECK_JAVA_MINIMAL_W_LEXER([[
+%define extends "Thread"
+%code init { super("Test Thread"); if (true) throw new InterruptedException(); }
+%define init_throws "InterruptedException"]], [], [[return EOF;]])
+AT_CHECK([[grep -q 'super("Test Thread"); if (true) throw new InterruptedException();' YYParser.java]])
+
+AT_CLEANUP
+
+
# --------------------------------------------- #
# Java stype, position_class and location_class #
# --------------------------------------------- #
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
- # We want a recent Autotest.
m4_version_prereq([2.58])
# --------------------------------------------------
# This macro works around the impossibility to define macros
# inside macros, because issuing `[$1]' is not possible in M4 :(.
-# This sucks hard, GNU M4 should really provide M5 like $$1.
+# This sucks hard, GNU M4 should really provide M5-like $$1.
m4_define([_AT_BISON_OPTION_PUSHDEFS],
[m4_if([$1$2], $[1]$[2], [],
[m4_fatal([$0: Invalid arguments: $@])])dnl
[m4_bmatch([$3], [%language "[Cc]\+\+"\|%skeleton "[a-z0-9]+\.cc"], [$1], [$2])])
m4_pushdef([AT_SKEL_JAVA_IF],
[m4_bmatch([$3], [%language "[Jj][Aa][Vv][Aa]"\|%skeleton "[a-z0-9]+\.java"], [$1], [$2])])
+ m4_pushdef([AT_LANG],
+ [AT_SKEL_JAVA_IF([java],
+ [AT_SKEL_CC_IF([c++],
+ [c])])])
m4_pushdef([AT_GLR_IF],
[m4_bmatch([$3], [%glr-parser\|%skeleton "glr\..*"], [$1], [$2])])
m4_pushdef([AT_LALR1_CC_IF],
[m4_bmatch([$3], [%glr-parser\|%parse-param], [$1], [$2])])
m4_pushdef([AT_NAME_PREFIX],
[m4_bmatch([$3], [%name-prefix ".*"],
- [m4_bregexp([$3], [name-prefix "\([^""]*\)"], [\1])],
+ [m4_bregexp([$3], [%name-prefix "\([^""]*\)"], [\1])],
[yy])])
m4_pushdef([AT_API_PREFIX],
- [m4_bmatch([$3], [%define api\.prefix ".*"],
- [m4_bregexp([$3], [%define api\.prefix "\([^""]*\)"], [\1])],
+ [m4_bmatch([$3], [\(%define api\.prefix\|%name-prefix\) ".*"],
+ [m4_bregexp([$3], [\(%define api\.prefix\|%name-prefix\) "\([^""]*\)"], [\2])],
[yy])])
+m4_pushdef([AT_TOKEN_PREFIX],
+[m4_bmatch([$3], [%define api.tokens.prefix ".*"],
+ [m4_bregexp([$3], [%define api.tokens.prefix "\(.*\)"], [\1])])])
# yyerror receives the location if %location & %pure & (%glr or %parse-param).
m4_pushdef([AT_YYERROR_ARG_LOC_IF],
[AT_GLR_OR_PARAM_IF([AT_PURE_AND_LOC_IF([$1], [$2])],
- [$2])])
+ [$2])])
# yyerror always sees the locations (when activated), except if
# (yacc & pure & !param). FIXME: This is wrong. See the manual.
m4_pushdef([AT_YYERROR_SEES_LOC_IF],
[AT_LOCATION_IF([AT_YACC_IF([AT_PURE_IF([AT_PARAM_IF([$1], [$2])],
- [$1])],
- [$1])],
- [$2])])
+ [$1])],
+ [$1])],
+ [$2])])
# The interface is pure: either because %define api.pure, or because we
# are using the C++ parsers.
m4_pushdef([AT_PURE_LEX_IF],
[AT_PURE_IF([$1],
- [AT_SKEL_CC_IF([$1], [$2])])])
+ [AT_SKEL_CC_IF([$1], [$2])])])
AT_PURE_LEX_IF(
[m4_pushdef([AT_LOC], [(*llocp)])
m4_pushdef([AT_VAL], [(*lvalp)])
- m4_pushdef([AT_LEX_FORMALS],
+ m4_pushdef([AT_YYLEX_FORMALS],
- [YYSTYPE *lvalp[]AT_LOCATION_IF([, YYLTYPE *llocp])])
+ [YYSTYPE *lvalp[]AT_LOCATION_IF([, YYLTYPE *llocp])])
- m4_pushdef([AT_LEX_ARGS],
+ m4_pushdef([AT_YYLEX_ARGS],
- [lvalp[]AT_LOCATION_IF([, llocp])])
+ [lvalp[]AT_LOCATION_IF([, llocp])])
m4_pushdef([AT_USE_LEX_ARGS],
- [(void) lvalp;AT_LOCATION_IF([(void) llocp])])
+ [(void) lvalp;AT_LOCATION_IF([(void) llocp])])
- m4_pushdef([AT_LEX_PRE_FORMALS],
- [AT_LEX_FORMALS, ])
- m4_pushdef([AT_LEX_PRE_ARGS],
- [AT_LEX_ARGS, ])
+ m4_pushdef([AT_YYLEX_PRE_FORMALS],
+ [AT_YYLEX_FORMALS, ])
+ m4_pushdef([AT_YYLEX_PRE_ARGS],
+ [AT_YYLEX_ARGS, ])
],
[m4_pushdef([AT_LOC], [[(]AT_NAME_PREFIX[lloc)]])
m4_pushdef([AT_VAL], [[(]AT_NAME_PREFIX[lval)]])
- m4_pushdef([AT_LEX_FORMALS], [void])
- m4_pushdef([AT_LEX_ARGS], [])
+ m4_pushdef([AT_YYLEX_FORMALS], [void])
+ m4_pushdef([AT_YYLEX_ARGS], [])
m4_pushdef([AT_USE_LEX_ARGS], [])
- m4_pushdef([AT_LEX_PRE_FORMALS], [])
- m4_pushdef([AT_LEX_PRE_ARGS], [])
+ m4_pushdef([AT_YYLEX_PRE_FORMALS], [])
+ m4_pushdef([AT_YYLEX_PRE_ARGS], [])
])
# Handle the different types of location components.
[AT_LOC_PUSHDEF([begin.line], [begin.column], [end.line], [end.column])])],
[AT_LOC_PUSHDEF([first_line], [first_column], [last_line], [last_column])])
+
+AT_GLR_IF([AT_KEYWORDS([glr])])
])# _AT_BISON_OPTION_PUSHDEFS
# AT_BISON_OPTION_POPDEFS
# -----------------------
m4_define([AT_BISON_OPTION_POPDEFS],
- [m4_popdef([AT_LEX_PRE_ARGS])
- m4_popdef([AT_LEX_PRE_FORMALS])
+ [m4_popdef([AT_YYLEX_PRE_ARGS])
+ m4_popdef([AT_YYLEX_PRE_FORMALS])
m4_popdef([AT_USE_LEX_ARGS])
- m4_popdef([AT_LEX_ARGS])
- m4_popdef([AT_LEX_FORMALS])
+ m4_popdef([AT_YYLEX_ARGS])
+ m4_popdef([AT_YYLEX_FORMALS])
m4_popdef([AT_VAL])
m4_popdef([AT_LOC])
m4_popdef([AT_PURE_LEX_IF])
m4_popdef([AT_YACC_IF])
m4_popdef([AT_GLR_IF])
m4_popdef([AT_SKEL_CC_IF])
+ m4_popdef([AT_LANG])
m4_popdef([AT_SKEL_JAVA_IF])
m4_popdef([AT_GLR_CC_IF])
m4_popdef([AT_LALR1_CC_IF])
$2])
])
+ # AT_YYLEX_PROTOTYPE
# AT_YYLEX_DECLARE_EXTERN
# AT_YYLEX_DECLARE
# AT_YYLEX_DEFINE(INPUT-STRING, [ACTION])
# ---------------------------------------
+ m4_define([AT_YYLEX_PROTOTYPE],
+ [int AT_API_PREFIX[]lex (]AT_YYLEX_FORMALS[)[]dnl
+ ])
+
m4_define([AT_YYLEX_DECLARE_EXTERN],
- [int AT_API_PREFIX[]lex (void);dnl
+ [AT_YYLEX_PROTOTYPE;dnl
])
m4_define([AT_YYLEX_DECLARE],
m4_define([AT_YYLEX_DEFINE],
[[#include <stdlib.h> /* abort */
- static int
- ]AT_API_PREFIX[lex (void)
+ static
+ ]AT_YYLEX_PROTOTYPE[
{
static char const input[] = "$1";
static size_t toknum = 0;
}]dnl
])
+ # AT_YYERROR_PROTOTYPE
# AT_YYERROR_DECLARE_EXTERN
# AT_YYERROR_DECLARE
# AT_YYERROR_DEFINE
# -------------------------
- # Beware that must be called inside a AT_BISON_OPTION_PUSHDEFS/POPDEFS
- # pair.
+ # Must be called inside a AT_BISON_OPTION_PUSHDEFS/POPDEFS pair.
+ m4_define([AT_YYERROR_FORMALS],
+ [m4_case(AT_LANG,
+ [c], [AT_YYERROR_ARG_LOC_IF([YYLTYPE *llocp, ])[const char *msg]])[]dnl
+ ])
+
+ m4_define([AT_YYERROR_PROTOTYPE],
+ [m4_case(AT_LANG,
+ [c], [[void ]AT_API_PREFIX[error (]AT_YYERROR_FORMALS[)]])[]dnl
+ ])
+
m4_define([AT_YYERROR_DECLARE_EXTERN],
- [void AT_API_PREFIX[]error (const char *msg);dnl
+ [m4_case(AT_LANG,
+ [c], [AT_YYERROR_PROTOTYPE;])[]dnl
])
m4_define([AT_YYERROR_DECLARE],
- [static AT_YYERROR_DECLARE_EXTERN[]dnl
+ [m4_case(AT_LANG,
+ [c], [static AT_YYERROR_DECLARE_EXTERN])[]dnl
])
m4_define([AT_YYERROR_DEFINE],
- [AT_SKEL_JAVA_IF([[public void yyerror (String msg)
- {
- System.err.println (msg);
- }]], [AT_SKEL_CC_IF([[void
- yy::parser::error (]AT_LOCATION_IF([[const yy::location &, ]])[std::string const &msg)
- {
- std::cerr << msg << std::endl;
- }]], [[#include <stdio.h>
- static void
- ]AT_API_PREFIX[error (char const *msg)
+ [m4_case(AT_LANG,
+ [c], [[#include <stdio.h>
+ /* A C error reporting function. */
+ static
+ ]AT_YYERROR_PROTOTYPE[
{
+ ]AT_YYERROR_SEES_LOC_IF([[
+ fprintf (stderr, "%d.%d",
+ ]AT_LOC_FIRST_LINE[, ]AT_LOC_FIRST_COLUMN[);
+ if (]AT_LOC_FIRST_LINE[ != ]AT_LOC_LAST_LINE[)
+ fprintf (stderr, "-%d.%d",
+ ]AT_LOC_LAST_LINE[, ]AT_LOC_LAST_COLUMN[ - 1);
+ else if (]AT_LOC_FIRST_COLUMN[ != ]AT_LOC_LAST_COLUMN[ - 1)
+ fprintf (stderr, "-%d",
+ ]AT_LOC_LAST_COLUMN[ - 1);
+ fprintf (stderr, ": ");]])[
fprintf (stderr, "%s\n", msg);
-]AT_NAME_PREFIX[::parser::error (const location_type& l, const std::string& m)
-{
- (void) l;
- std::cerr << ]AT_LOCATION_IF([l << ": " << ])[m << std::endl;
+ }]],
+ [c++], [[/* A C++ error reporting function. */
+ void
- {
++]AT_NAME_PREFIX[::parser::error (]AT_LOCATION_IF([[const location_type& l, ]])[const std::string& m)
++{ std::cerr << ]AT_LOCATION_IF([l << ": " << ])[m << std::endl;
+ }]],
+ [java], [AT_LOCATION_IF([[public void yyerror (Calc.Location l, String s)
- }]])])dnl
++{
+ if (l == null)
+ System.err.println (s);
+ else
+ System.err.println (l + ": " + s);
+ }
+ ]], [[
+ public void yyerror (String s)
+ {
+ System.err.println (s);
+}]])])dnl
])
+
## --------------- ##
## Running Bison. ##
## --------------- ##
# assume that we are linking too; this is a hack.
m4_define([AT_COMPILE],
[AT_CHECK([$CC $CFLAGS $CPPFLAGS m4_bmatch([$1], [[.]], [], [$LDFLAGS ])-o $1 m4_default([$2], [$1.c])[]m4_bmatch([$1], [[.]], [], [ $LIBS])],
- 0, [ignore], [ignore])])
+ 0, [ignore], [ignore])])
# AT_COMPILE_CXX(OUTPUT, [SOURCES = OUTPUT.cc])
# --------------------------------------------
[AT_KEYWORDS(c++)
AT_CHECK([$BISON_CXX_WORKS], 0, ignore, ignore)
AT_CHECK([$CXX $CXXFLAGS $CPPFLAGS m4_bmatch([$1], [[.]], [], [$LDFLAGS ])-o $1 m4_default([$2], [$1.cc])[]m4_bmatch([$1], [[.]], [], [ $LIBS])],
- 0, [ignore], [ignore])])
+ 0, [ignore], [ignore])])
# AT_JAVA_COMPILE(SOURCES)
# ------------------------
# is not installed.
m4_define([AT_JAVA_COMPILE],
[AT_KEYWORDS(java)
- AT_CHECK([[test -n "$CONF_JAVA" || exit 77
- test -n "$CONF_JAVAC" || exit 77]])
+ AT_SKIP_IF([[test -z "$CONF_JAVA$CONF_JAVAC"]])
AT_CHECK([[$SHELL ../../../javacomp.sh ]$1],
[[0]], [ignore], [ignore])])
+ # AT_LANG_COMPILE(OUTPUT, [SOURCES = OUTPUT.c]
+ # --------------------------------------------
+ m4_define([AT_LANG_COMPILE],
+ [m4_case(AT_LANG,
+ [c], [AT_COMPILE([$1], [$2])],
+ [c++], [AT_COMPILE_CXX([$1], [$2])],
+ [java], [AT_JAVA_COMPILE([$1.java], [$2])],
+ [m4_fatal([unknown language: ]m4_defn([AT_LANG]))])[]dnl
+ ])
+
# AT_FULL_COMPILE(OUTPUT, [OTHER1], [OTHER2])
# -------------------------------------------
# Compile OUTPUT.y to OUTPUT.c, OUTPUT.cc, or OUTPUT.java, and then
# OUTPUT-OTHER.c, OUTPUT-OTHER.cc, or OUTPUT-OTHER.java to OUTPUT or
# OUTPUT.java along with it. Relies on AT_SKEL_CC_IF and
# AT_SKEL_JAVA_IF.
- m4_define([AT_FULL_COMPILE], [
- AT_SKEL_JAVA_IF([
- AT_BISON_CHECK([-o $1.java $1.y])
- AT_JAVA_COMPILE([$1.java],
+ m4_define([AT_FULL_COMPILE],
+ [m4_case(AT_LANG,
+ [java],
+ [AT_BISON_CHECK([-o $1.java $1.y])
+ AT_LANG_COMPILE([$1],
- m4_join([ ],
- [$1.java],
- m4_ifval($2, [[$1-$2.java]]),
+ m4_join([ ],
+ [$1.java],
+ m4_ifval($2, [[$1-$2.java]]),
- m4_ifval($3, [[$1-$3.java]])))
- ], [
- AT_SKEL_CC_IF([
- AT_BISON_CHECK([-o $1.cc $1.y])
- AT_COMPILE_CXX([$1],
+ m4_ifval($3, [[$1-$3.java]])))],
+ [c++],
+ [AT_BISON_CHECK([-o $1.cc $1.y])
+ AT_LANG_COMPILE([$1],
- m4_join([ ],
- [$1.cc],
- m4_ifval($2, [[$1-$2.cc]]),
+ m4_join([ ],
+ [$1.cc],
+ m4_ifval($2, [[$1-$2.cc]]),
- m4_ifval($3, [[$1-$3.cc]])))
- ], [
- AT_BISON_CHECK([-o $1.c $1.y])
- AT_COMPILE([$1],
+ m4_ifval($3, [[$1-$3.cc]])))],
+ [c],
+ [AT_BISON_CHECK([-o $1.c $1.y])
+ AT_LANG_COMPILE([$1],
- m4_join([ ],
- [$1.c],
- m4_ifval($2, [[$1-$2.c]]),
+ m4_join([ ],
+ [$1.c],
+ m4_ifval($2, [[$1-$2.c]]),
- m4_ifval($3, [[$1-$3.c]])))
- ])
- ])
+ m4_ifval($3, [[$1-$3.c]])))])
])
# [ADDITIONAL-TESTS], [PRE-TESTS])
# -----------------------------------------------------------------------------
m4_define([AT_CHECK_OUTPUT],
-[AT_SETUP([[Output files: $2 $3 $5]])
+[AT_SETUP([[Output files: ]$2 $3 $5])
$7
for file in $1 $4; do
case "$file" in
esac
done
AT_DATA([$1],
-[[$2
+[$2[
%%
foo: {};
]])
])
AT_CHECK_OUTPUT([foo.y], [], [-dv],
- [foo.output foo.tab.c foo.tab.h])
+ [foo.output foo.tab.c foo.tab.h])
# Some versions of Valgrind (at least valgrind-3.6.0.SVN-Debian) report
# "fgrep: write error: Bad file descriptor" when stdout is closed, so we
# skip this test group during maintainer-check-valgrind.
AT_CHECK_OUTPUT([foo.y], [], [-dv],
- [foo.output foo.tab.c foo.tab.h],
- [>&-], [],
- [AT_CHECK([[case "$PREBISON" in *valgrind*) exit 77;; esac]])])
+ [foo.output foo.tab.c foo.tab.h],
+ [>&-], [],
+ [AT_CHECK([[case "$PREBISON" in *valgrind*) exit 77;; esac]])])
AT_CHECK_OUTPUT([foo.y], [], [-dv -o foo.c],
- [foo.c foo.h foo.output])
+ [foo.c foo.h foo.output])
AT_CHECK_OUTPUT([foo.y], [], [-dv -o foo.tab.c],
- [foo.output foo.tab.c foo.tab.h])
+ [foo.output foo.tab.c foo.tab.h])
AT_CHECK_OUTPUT([foo.y], [], [-dv -y],
- [y.output y.tab.c y.tab.h])
+ [y.output y.tab.c y.tab.h])
AT_CHECK_OUTPUT([foo.y], [], [-dv -b bar],
- [bar.output bar.tab.c bar.tab.h])
+ [bar.output bar.tab.c bar.tab.h])
AT_CHECK_OUTPUT([foo.y], [], [-dv -g -o foo.c],
- [foo.c foo.dot foo.h foo.output])
+ [foo.c foo.dot foo.h foo.output])
AT_CHECK_OUTPUT([foo.y], [%defines %verbose], [],
- [foo.output foo.tab.c foo.tab.h])
+ [foo.output foo.tab.c foo.tab.h])
AT_CHECK_OUTPUT([foo.y], [%defines %verbose %yacc],[],
- [y.output y.tab.c y.tab.h])
+ [y.output y.tab.c y.tab.h])
AT_CHECK_OUTPUT([foo.yy], [%defines %verbose %yacc],[],
- [y.output y.tab.c y.tab.h])
+ [y.output y.tab.c y.tab.h])
# Exercise %output and %file-prefix including deprecated '='
AT_CHECK_OUTPUT([foo.y], [%file-prefix "bar" %defines %verbose], [],
- [bar.output bar.tab.c bar.tab.h])
+ [bar.output bar.tab.c bar.tab.h])
AT_CHECK_OUTPUT([foo.y], [%output="bar.c" %defines %verbose %yacc],[],
- [bar.output bar.c bar.h])
+ [bar.output bar.c bar.h])
AT_CHECK_OUTPUT([foo.y],
- [%file-prefix="baz" %output "bar.c" %defines %verbose %yacc],
- [],
- [bar.output bar.c bar.h])
+ [%file-prefix="baz" %output "bar.c" %defines %verbose %yacc],
+ [],
+ [bar.output bar.c bar.h])
# Check priorities of extension control.
AT_CHECK_OUTPUT([foo.yy], [%defines %verbose], [],
- [foo.output foo.tab.cc foo.tab.hh])
+ [foo.output foo.tab.cc foo.tab.hh])
AT_CHECK_OUTPUT([foo.yy], [%defines %verbose ], [-o foo.c],
- [foo.c foo.h foo.output])
+ [foo.c foo.h foo.output])
AT_CHECK_OUTPUT([foo.yy], [],
- [--defines=foo.hpp -o foo.c++],
- [foo.c++ foo.hpp])
+ [--defines=foo.hpp -o foo.c++],
+ [foo.c++ foo.hpp])
AT_CHECK_OUTPUT([foo.yy], [%defines "foo.hpp"],
- [-o foo.c++],
- [foo.c++ foo.hpp])
+ [-o foo.c++],
+ [foo.c++ foo.hpp])
AT_CHECK_OUTPUT([foo.yy], [],
- [-o foo.c++ --graph=foo.gph],
- [foo.c++ foo.gph])
+ [-o foo.c++ --graph=foo.gph],
+ [foo.c++ foo.gph])
## ------------ ##
])
AT_CHECK_OUTPUT([foo.yy], [%skeleton "lalr1.cc" %defines %verbose], [],
- [foo.tab.cc foo.tab.hh foo.output location.hh stack.hh position.hh])
+ [foo.tab.cc foo.tab.hh foo.output stack.hh])
+
+AT_CHECK_OUTPUT([foo.yy], [%skeleton "lalr1.cc" %defines %verbose %locations], [],
+ [foo.tab.cc foo.tab.hh foo.output location.hh stack.hh position.hh])
AT_CHECK_OUTPUT([subdir/foo.yy], [%skeleton "lalr1.cc" %defines %verbose], [],
- [foo.tab.cc foo.tab.hh foo.output location.hh stack.hh position.hh],
- [], [AT_CHECK_NO_SUBDIR_PART([foo.tab])])
+ [foo.tab.cc foo.tab.hh foo.output stack.hh],
+ [], [AT_CHECK_NO_SUBDIR_PART([foo.tab])])
-AT_CHECK_OUTPUT([subdir/foo.yy], [%skeleton "lalr1.cc" %defines %verbose],
- [-o subdir/foo.cc],
- [subdir/foo.cc subdir/foo.hh subdir/foo.output subdir/location.hh subdir/stack.hh subdir/position.hh],
- [], [AT_CHECK_NO_SUBDIR_PART([subdir/foo])])
+AT_CHECK_OUTPUT([subdir/foo.yy], [%skeleton "lalr1.cc" %defines %verbose %locations],
+ [-o subdir/foo.cc],
+ [subdir/foo.cc subdir/foo.hh subdir/foo.output subdir/location.hh subdir/stack.hh subdir/position.hh],
+ [], [AT_CHECK_NO_SUBDIR_PART([subdir/foo])])
AT_CHECK_OUTPUT([gram_dir/foo.yy],
[%skeleton "lalr1.cc" %defines %verbose %file-prefix "output_dir/foo"],
[],
- [output_dir/foo.tab.cc output_dir/foo.tab.hh output_dir/foo.output output_dir/location.hh output_dir/stack.hh output_dir/position.hh])
+ [output_dir/foo.tab.cc output_dir/foo.tab.hh output_dir/foo.output output_dir/stack.hh])
+
+AT_CHECK_OUTPUT([gram_dir/foo.yy],
+ [%skeleton "lalr1.cc" %defines %locations %verbose %file-prefix "output_dir/foo"],
+ [],
+ [output_dir/foo.tab.cc output_dir/foo.tab.hh output_dir/foo.output output_dir/location.hh output_dir/stack.hh output_dir/position.hh])
# AT_CHECK_CONFLICTING_OUTPUT(INPUT-FILE, DIRECTIVES, FLAGS, STDERR,
])
AT_CHECK_CONFLICTING_OUTPUT([foo.y],
-[%skeleton "lalr1.cc" %defines], [--graph="location.hh"],
+[%skeleton "lalr1.cc" %defines %locations], [--graph="location.hh"],
[foo.y: warning: conflicting outputs to file 'location.hh'
])
m4_define([AT_CHECK_OUTPUT_FILE_NAME],
[AT_SETUP([Output file name: $1])
+ AT_BISON_OPTION_PUSHDEFS
# Skip if platform doesn't support file name. For example, Cygwin
# doesn't support file names containing ":" or "\".
AT_CHECK([[touch "]AS_ESCAPE([$1[.tmp]])[" || exit 77]])
AT_DATA_GRAMMAR([glr.y],
[[%glr-parser
%code {
- int yylex (void);
- void yyerror (const char *);
+ ]AT_YYERROR_DECLARE_EXTERN[
+ ]AT_YYLEX_DECLARE_EXTERN[
}
%%
start: {};
AT_COMPILE_CXX([cxx.o], [-c "AS_ESCAPE([$1.c])"])
$2
+ AT_BISON_OPTION_POPDEFS
AT_CLEANUP
])
%%
exp: "a" "\\\'\?\"\a\b\f\n\r\t\v\001\201\x001\x000081??!";
%%
- void
- yyerror (char const *s)
- {
- fprintf (stderr, "%s\n", s);
- }
+ ]AT_YYERROR_DEFINE[
int
yylex (void)
AT_KEYWORDS([report])
AT_DATA([input.y],
-[[%token undef_id_tok const_id_tok
+[[%token undef_id_tok const_id_tok
%start CONST_DEC_PART
\f
;
CONST_DEC_LIST:
- CONST_DEC
+ CONST_DEC
| CONST_DEC_LIST CONST_DEC
;
CONST_DEC:
- { } undef_id_tok '=' const_id_tok ';'
+ { } undef_id_tok '=' const_id_tok ';'
;
%%
]])
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5, 6
};
-static const yytype_uint8 yyprhs[] =
-{
- 0, 0, 3, 5, 6, 9, 14
-};
-static const yytype_int8 yyrhs[] =
-{
- 8, 0, -1, 9, -1, -1, 10, 11, -1, 3,
- 4, 5, 8, -1, 6, 8, -1
-};
static const yytype_uint8 yyrline[] =
{
0, 2, 2, 3, 3, 4, 5
{
0, 256, 257, 258, 259, 260, 261
};
-static const yytype_uint8 yyr1[] =
-{
- 0, 7, 8, 9, 9, 10, 11
-};
-static const yytype_uint8 yyr2[] =
+static const yytype_int8 yypact[] =
{
- 0, 2, 1, 0, 2, 4, 2
+ -2, -1, 4, -8, 0, 2, -8, -2, -8, -2,
+ -8, -8
};
static const yytype_uint8 yydefact[] =
{
3, 0, 0, 2, 0, 0, 1, 3, 4, 3,
6, 5
};
-static const yytype_int8 yydefgoto[] =
-{
- -1, 2, 3, 4, 8
-};
-static const yytype_int8 yypact[] =
-{
- -2, -1, 4, -8, 0, 2, -8, -2, -8, -2,
- -8, -8
-};
static const yytype_int8 yypgoto[] =
{
-8, -7, -8, -8, -8
};
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 2, 3, 4, 8
+};
static const yytype_uint8 yytable[] =
{
10, 1, 11, 5, 6, 0, 7, 9
0, 3, 8, 9, 10, 4, 0, 6, 11, 5,
8, 8
};
+static const yytype_uint8 yyr1[] =
+{
+ 0, 7, 8, 9, 9, 10, 11
+};
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 0, 2, 4, 2
+};
]])
AT_CLEANUP
[AT_DATA_GRAMMAR([dancer.y],
[%{
static int yylex (AT_LALR1_CC_IF([int *], [void]));
-AT_LALR1_CC_IF([],
+AT_LALR1_CC_IF([#include <cstdlib>],
[#include <stdlib.h>
#include <stdio.h>
]AT_YYERROR_DECLARE[])
| INVALID
;
%%
- AT_LALR1_CC_IF(
- [/* A C++ error reporting function. */
- void
- yy::parser::error (const std::string& m)
- {
- std::cerr << m << std::endl;
- }
-
- int
+ AT_YYERROR_DEFINE[
+ ]AT_LALR1_CC_IF(
+ [int
yyparse ()
{
yy::parser parser;
#endif
return parser.parse ();
}
- ],
- [static void
- yyerror (const char *s)
- {
- fprintf (stderr, "%s\n", s);
- }])
+ ])
static int
yylex (AT_LALR1_CC_IF([int *lval], [void]))
# --------------------------------
m4_define([_AT_DATA_EXPECT2_Y],
[AT_DATA_GRAMMAR([expect2.y],
-[[%{
-static int yylex (]AT_LALR1_CC_IF([int *], [void]));
-AT_LALR1_CC_IF([],
-[[#include <stdio.h>
-#include <stdlib.h>
+[%{
+static int yylex (AT_LALR1_CC_IF([int *], [void]));
+AT_LALR1_CC_IF([[#include <cstdlib>]],
+[[#include <stdlib.h>
+#include <stdio.h>
]AT_YYERROR_DECLARE])[
%}
$1
start:
{
printf ("Bison would once convert this action to a midrule because of the"
- " subsequent braced code.\n");
+ " subsequent braced code.\n");
}
;
AT_SETUP([[parse-gram.y: LALR = IELR]])
-# Avoid differences in synclines by telling bison that the output files
-# have the same name.
+# Avoid tests/bison's dark magic by processing a local copy of the
+# grammar. Avoid differences in synclines by telling bison that the
+# output files have the same name.
[cp $abs_top_srcdir/src/parse-gram.y input.y]
AT_BISON_CHECK([[-o input.c -Dlr.type=lalr input.y]])
[mv input.c lalr.c]
-## --------------------------------------- ##
-## %error-verbose and YYSTACK_USE_ALLOCA. ##
-## --------------------------------------- ##
+## -------------------------------------------- ##
+## parse.error=verbose and YYSTACK_USE_ALLOCA. ##
+## -------------------------------------------- ##
-AT_SETUP([[%error-verbose and YYSTACK_USE_ALLOCA]])
+AT_SETUP([[parse.error=verbose and YYSTACK_USE_ALLOCA]])
AT_BISON_OPTION_PUSHDEFS
AT_DATA_GRAMMAR([input.y],
#define YYSTACK_USE_ALLOCA 1
}
-%error-verbose
+%define parse.error verbose
%%
%%
]AT_YYERROR_DEFINE[
-/* Induce two syntax error messages (which requires full error
- recovery by shifting 3 tokens) in order to detect any loss of the
- reallocated buffer. */
+ /* Induce two syntax error messages (which requires full error
+ recovery by shifting 3 tokens) in order to detect any loss of the
+ reallocated buffer. */
]AT_YYLEX_DEFINE([abc])[
int
main (void)
-## ------------------------- ##
-## %error-verbose overflow. ##
-## ------------------------- ##
+## ------------------------------ ##
+## parse.error=verbose overflow. ##
+## ------------------------------ ##
# Imagine the case where YYSTACK_ALLOC_MAXIMUM = YYSIZE_MAXIMUM and an
# invocation of yysyntax_error has caused yymsg_alloc to grow to exactly
# size calculation would return YYSIZE_MAXIMUM to yyparse. Then,
# yyparse would invoke yyerror using the old contents of yymsg.
-AT_SETUP([[%error-verbose overflow]])
+AT_SETUP([[parse.error=verbose overflow]])
+
AT_BISON_OPTION_PUSHDEFS
AT_DATA_GRAMMAR([input.y],
[[%code {
#define YYMAXDEPTH 100
}
-%error-verbose
+%define parse.error verbose
%%
%%
]AT_YYERROR_DEFINE[
-/* Induce two syntax error messages (which requires full error
- recovery by shifting 3 tokens). */
+ /* Induce two syntax error messages (which requires full error
+ recovery by shifting 3 tokens). */
]AT_YYLEX_DEFINE([abc])[
int
main (void)
}
]$1[
-%error-verbose
+%define parse.error verbose
%token 'c'
%%