* data/c.m4 (b4_identification, b4_user_args, b4_parse_param):

New.
* data/yacc.m4 (b4_pure_args, b4_Pure_args): New.
(b4_parse_param): Remove.
Use b4_identification.
Propagate b4_pure_args where needed to pass them to yyerror.
* data/glr.m4 (b4_parse_param): Remove.
(b4_user_formals, b4_pure_args, b4_pure_formals, b4_lpure_args)
(b4_lpure_formals): New.
Use b4_identification.
(YY_USER_FORMALS, YY_USER_ARGS): Remove, replaced by
b4_user_formals and b4_user_args.
(yyexpandGLRStack, yyFail, yyaddDeferredAction, yyglrShiftDefer)
(yyreportAmbiguity): When using a pure parser, also need
the location, and the parse-params.
Adjust callers.
(yyuserAction, yyglrShift, yyreportParseError, yyrecoverParseError):
When using a pure parser, also need the parse-params.
Adjust callers.
* tests/calc.at: Test pure (%pure-parser) and absolutely pure
(%pure-parser + %parse-param) LALR and GLR parsers.
(AT_CHECK_PUSHDEFS, AT_CHECK_POPDEFS): New, define AT_PARAM_IF,
AT_LOCATION_IF, AT_PURE_IF, AT_GLR_IF, AAT_PURE_AND_LOC_IF,
AT_GLR_OR_PARAM_IF, AT_YYERROR_ARG_LOC_IF, AT_YYERROR_SEES_LOC_IF.
(_AT_DATA_CALC_Y): Equip for purity of yyerror.
(_AT_CHECK_CALC_ERROR): Use AT_YYERROR_SEES_LOC_IF.
* tests/cxx-type.at (_AT_TEST_GLR_CALC): Equip for yyerror purity.
* doc/bison.texinfo: Untabify the whole file.
(Parser Function): Document %parse-param, deprecate YYPARSE_PARAM.
(Pure Calling): Document %lex-param, deprecate YYLEX_PARAM.
(Error Reporting): Adjust to these new directives.
Document %error-verbose, deprecate YYERROR_VERBOSE.
This commit is contained in:
Akim Demaille
2002-11-03 16:41:57 +00:00
parent 9e32add8e6
commit 2a8d363aab
8 changed files with 553 additions and 301 deletions

View File

@@ -1,3 +1,38 @@
2002-11-03 Akim Demaille <akim@epita.fr>
* data/c.m4 (b4_identification, b4_user_args, b4_parse_param):
New.
* data/yacc.m4 (b4_pure_args, b4_Pure_args): New.
(b4_parse_param): Remove.
Use b4_identification.
Propagate b4_pure_args where needed to pass them to yyerror.
* data/glr.m4 (b4_parse_param): Remove.
(b4_user_formals, b4_pure_args, b4_pure_formals, b4_lpure_args)
(b4_lpure_formals): New.
Use b4_identification.
(YY_USER_FORMALS, YY_USER_ARGS): Remove, replaced by
b4_user_formals and b4_user_args.
(yyexpandGLRStack, yyFail, yyaddDeferredAction, yyglrShiftDefer)
(yyreportAmbiguity): When using a pure parser, also need
the location, and the parse-params.
Adjust callers.
(yyuserAction, yyglrShift, yyreportParseError, yyrecoverParseError):
When using a pure parser, also need the parse-params.
Adjust callers.
* tests/calc.at: Test pure (%pure-parser) and absolutely pure
(%pure-parser + %parse-param) LALR and GLR parsers.
(AT_CHECK_PUSHDEFS, AT_CHECK_POPDEFS): New, define AT_PARAM_IF,
AT_LOCATION_IF, AT_PURE_IF, AT_GLR_IF, AAT_PURE_AND_LOC_IF,
AT_GLR_OR_PARAM_IF, AT_YYERROR_ARG_LOC_IF, AT_YYERROR_SEES_LOC_IF.
(_AT_DATA_CALC_Y): Equip for purity of yyerror.
(_AT_CHECK_CALC_ERROR): Use AT_YYERROR_SEES_LOC_IF.
* tests/cxx-type.at (_AT_TEST_GLR_CALC): Equip for yyerror purity.
* doc/bison.texinfo: Untabify the whole file.
(Parser Function): Document %parse-param, deprecate YYPARSE_PARAM.
(Pure Calling): Document %lex-param, deprecate YYLEX_PARAM.
(Error Reporting): Adjust to these new directives.
Document %error-verbose, deprecate YYERROR_VERBOSE.
2002-11-03 Akim Demaille <akim@epita.fr>
* tests/calc.at: Change all the AT_CHECK_CALC_LALR and

8
NEWS
View File

@@ -8,6 +8,14 @@ Changes in version 1.75a, 2002-10-24:
ago, but nobody noticed until we recently asked someone to try
building Bison with a K&R C compiler.
* %error-verbose
This new directive is preferred over YYERROR_VERBOSE.
* %lex-param, %parse-param
These new directives are preferred over PARSE_PARAM and LEX_PARAM.
In addition, they provide a means for yyerror to remain pure, and
to access to the current location.
Changes in version 1.75, 2002-10-14:
* Bison should now work on 64-bit hosts.

View File

@@ -19,9 +19,9 @@ m4_divert(-1) -*- Autoconf -*-
# 02111-1307 USA
## ----------- ##
## Copyright. ##
## ----------- ##
## ---------------- ##
## Identification. ##
## ---------------- ##
# b4_copyright(TITLE, YEARS)
# --------------------------
@@ -47,6 +47,45 @@ m4_define([b4_copyright],
Boston, MA 02111-1307, USA. */])
# b4_identification
# -----------------
m4_define([b4_identification],
[/* Identify Bison output. */
[#]define YYBISON 1
/* Skeleton name. */
[#]define YYSKELETON_NAME "b4_skeleton"
/* Pure parsers. */
[#]define YYPURE b4_pure
/* Using locations. */
[#]define YYLSP_NEEDED b4_locations_flag
])
## ------------------------ ##
## Pure/impure interfaces. ##
## ------------------------ ##
# b4_user_args
# ------------
m4_define([b4_user_args],
[m4_ifset([b4_parse_param], [, b4_c_args(b4_parse_param)])])
# b4_parse_param
# --------------
# If defined, b4_parse_param arrives double quoted, but below we prefer
# it to be single quoted.
m4_define_default([b4_parse_param])
m4_define([b4_parse_param],
b4_parse_param))
## ------------ ##
## Data Types. ##
## ------------ ##

View File

@@ -31,6 +31,15 @@ m4_define_default([b4_stack_depth_init], [200])
# Location type.
m4_define_default([b4_location_type], [yyltype])
## ------------------------ ##
## Pure/impure interfaces. ##
## ------------------------ ##
# b4_lex_param
# ------------
# Accumule in b4_lex_param all the yylex arguments.
# Yes, this is quite ugly...
m4_define([b4_lex_param],
@@ -38,12 +47,39 @@ m4_dquote(b4_pure_if([[[[YYSTYPE *]], [[yylvalp]]][]dnl
b4_location_if([, [[YYLTYPE *], [yyllocp]]])])dnl
m4_ifdef([b4_lex_param], [, ]b4_lex_param)))
# Yes, this is quite ugly...
m4_define_default([b4_parse_param])
m4_ifdef([b4_parse_param],
[m4_define([b4_parse_param],
b4_parse_param)])
# b4_user_formals
# ---------------
m4_define([b4_user_formals],
[m4_ifset([b4_parse_param], [, b4_c_ansi_formals(b4_parse_param)])])
# b4_pure_args
# ------------
# Arguments passed to yyerror: user args plus yylloc.
m4_define([b4_pure_args],
[b4_pure_if([b4_location_if([, yylocp])])[]b4_user_args])
# b4_pure_formals
# ---------------
# Arguments passed to yyerror: user formals plus yyllocp.
m4_define([b4_pure_formals],
[b4_pure_if([b4_location_if([, YYLTYPE *yylocp])])[]b4_user_formals])
# b4_lpure_args
# -------------
# Same as above, but on the lookahead, hence yyllocp instead of yylocp.
m4_define([b4_lpure_args],
[b4_pure_if([b4_location_if([, yyllocp])])[]b4_user_args])
# b4_lpure_formals
# ----------------
# Same as above, but on the lookahead, hence yyllocp instead of yylocp.
m4_define([b4_lpure_formals],
[b4_pure_if([b4_location_if([YYLTYPE *yyllocp])])[]b4_user_formals])
## ----------------- ##
@@ -119,24 +155,15 @@ b4_copyright([Skeleton parser for GLR parsing with Bison], [2002])
[
/* This is the parser code for GLR (Generalized LR) parser. */
/* FIXME: minimize these */
#include <assert.h>
#include <setjmp.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <setjmp.h>
/* Identify Bison output. */
#define YYBISON 1
/* Pure parsers. */
#define YYPURE ]b4_pure[
/* Using locations. */
#define YYLSP_NEEDED ]b4_locations_flag[
]m4_if(b4_prefix[], [yy], [],
]b4_identification
m4_if(b4_prefix[], [yy], [],
[/* If NAME_PREFIX is specified substitute the variables and functions
names. */
#define yyparse b4_prefix[]parse
@@ -378,16 +405,9 @@ static const ]b4_int_type_for([b4_check])[ yycheck[] =
/* Prevent warning if -Wmissing-prototypes. */
]b4_c_ansi_function_decl([yyparse], [int], b4_parse_param)
]b4_c_ansi_function_decl([yyparse], [int], b4_parse_param)[
m4_ifset([b4_parse_param],
[#define YY_USER_FORMALS , b4_c_ansi_formals(b4_parse_param)
#define YY_USER_ARGS , b4_c_args(b4_parse_param)],
[#define YY_USER_FORMALS
#define YY_USER_ARGS])
[/* Error token number */
/* Error token number */
#define YYTERROR 1
/* YYLLOC_DEFAULT -- Compute the default location (before the actions
@@ -548,11 +568,11 @@ struct yyGLRStack {
};
static void yyinitGLRStack (yyGLRStack* yystack, size_t yysize);
static void yyexpandGLRStack (yyGLRStack* yystack);
static void yyexpandGLRStack (yyGLRStack* yystack]b4_pure_formals[);
static void yyfreeGLRStack (yyGLRStack* yystack);
static void
yyFail (yyGLRStack* yystack, const char* yyformat, ...)
yyFail (yyGLRStack* yystack]b4_pure_formals[, const char* yyformat, ...)
{
if (yyformat != NULL)
{
@@ -561,7 +581,7 @@ yyFail (yyGLRStack* yystack, const char* yyformat, ...)
va_start (yyap, yyformat);
yystack->yyerrflag = 1;
vsprintf (yymsg, yyformat, yyap);
yyerror (yymsg);
yyerror (yymsg]b4_pure_args[);
}
longjmp (yystack->yyexception_buffer, 1);
}
@@ -584,7 +604,7 @@ yytokenName (yySymbol yytoken)
static YYRESULTTAG
yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
YYSTYPE* yyvalp, YYLTYPE* yylocp, yyGLRStack* yystack
YY_USER_FORMALS)
]b4_user_formals[)
{
/* Avoid `unused' warnings in there are no $n. */
(void) yystack;
@@ -616,7 +636,7 @@ yyuserAction (yyRuleNum yyn, int yyrhslen, yyGLRStackItem* yyvsp,
# undef YYBACKUP
# define YYBACKUP(Token, Value) \
do { \
yyerror ("syntax error: cannot back up"); \
yyerror ("syntax error: cannot back up"]b4_pure_args[); \
YYERROR; \
} while (0)
@@ -644,7 +664,7 @@ static YYSTYPE
yyuserMerge (int yyn, YYSTYPE* yy0, YYSTYPE* yy1)
{
YYSTYPE yyval = *yy0;
/* `Use' the arguments. */
/* `Use' the arguments. */
(void) yy0;
(void) yy1;
@@ -655,7 +675,7 @@ yyuserMerge (int yyn, YYSTYPE* yy0, YYSTYPE* yy1)
return yyval;
}
[
/* Bison grammar-table manipulation */
/* Bison grammar-table manipulation. */
/** Number of symbols composing the right hand side of rule #RULE. */
static inline int
@@ -751,7 +771,7 @@ yyhasResolvedValue (yyGLRState* yystate)
static void
yyaddDeferredAction (yyGLRStack* yystack, yyGLRState* yystate,
yyGLRState* rhs, yyRuleNum yyrule)
yyGLRState* rhs, yyRuleNum yyrule]b4_pure_formals[)
{
yySemanticOption* yynewItem;
yynewItem = &yystack->yynextFree->yyoption;
@@ -763,7 +783,7 @@ yyaddDeferredAction (yyGLRStack* yystack, yyGLRState* yystate,
yynewItem->yynext = yystate->yysemantics.yyfirstVal;
yystate->yysemantics.yyfirstVal = yynewItem;
if (yystack->yyspaceLeft < YYHEADROOM)
yyexpandGLRStack (yystack);
yyexpandGLRStack (yystack]b4_pure_args[);
}
/* GLRStacks */
@@ -808,7 +828,7 @@ yyinitGLRStack (yyGLRStack* yystack, size_t yysize)
allocation, so that we can avoid having external pointers exist
across an allocation. */
static void
yyexpandGLRStack (yyGLRStack* yystack)
yyexpandGLRStack (yyGLRStack* yystack]b4_pure_formals[)
{
#if YYSTACKEXPANDABLE
yyGLRStack yynewStack;
@@ -817,7 +837,8 @@ yyexpandGLRStack (yyGLRStack* yystack)
size_t yyn;
yysize = yystack->yynextFree - yystack->yyitems;
if (YYMAXDEPTH <= yysize)
yyFail (yystack, "parsing stack overflow (%d items)", yysize);
yyFail (yystack][]b4_pure_args[,
"parsing stack overflow (%d items)", yysize);
yynewSize = 2*yysize;
if (YYMAXDEPTH < yynewSize)
yynewSize = YYMAXDEPTH;
@@ -864,8 +885,8 @@ yyexpandGLRStack (yyGLRStack* yystack)
#else
yyFail (yystack, "parsing stack overflow (%d items)", yysize);
yyFail (yystack][]b4_lpure_args[,
"parsing stack overflow (%d items)", yysize);
#endif
}
@@ -937,7 +958,7 @@ yyremoveDeletes (yyGLRStack* yystack)
* LRSTATE, at input position POSN, with (resolved) semantic value SVAL. */
static inline void
yyglrShift (yyGLRStack* yystack, int yyk, yyStateNum yylrState, size_t yyposn,
YYSTYPE yysval, YYLTYPE* yylocp)
YYSTYPE yysval, YYLTYPE* yylocp]b4_user_formals[)
{
yyGLRStackItem* yynewItem;
@@ -953,7 +974,7 @@ yyglrShift (yyGLRStack* yystack, int yyk, yyStateNum yylrState, size_t yyposn,
yynewItem->yystate.yysemantics.yysval = yysval;
yynewItem->yystate.yyloc = *yylocp;
if (yystack->yyspaceLeft < YYHEADROOM)
yyexpandGLRStack (yystack);
yyexpandGLRStack (yystack]b4_pure_args[);
}
/** Shift to a new state on stack #K of STACK, to a new state
@@ -961,7 +982,7 @@ yyglrShift (yyGLRStack* yystack, int yyk, yyStateNum yylrState, size_t yyposn,
* the (unresolved) semantic value of RHS under the action for RULE. */
static inline void
yyglrShiftDefer (yyGLRStack* yystack, int yyk, yyStateNum yylrState,
size_t yyposn, yyGLRState* rhs, yyRuleNum yyrule)
size_t yyposn, yyGLRState* rhs, yyRuleNum yyrule]b4_pure_formals[)
{
yyGLRStackItem* yynewItem;
@@ -975,7 +996,7 @@ yyglrShiftDefer (yyGLRStack* yystack, int yyk, yyStateNum yylrState,
yystack->yytops.yystates[yyk] = &yynewItem->yystate;
yystack->yynextFree += 1;
yystack->yyspaceLeft -= 1;
yyaddDeferredAction (yystack, &yynewItem->yystate, rhs, yyrule);
yyaddDeferredAction (yystack, &yynewItem->yystate, rhs, yyrule]b4_pure_args[);
}
/** Pop the symbols consumed by reduction #RULE from the top of stack
@@ -986,7 +1007,7 @@ yyglrShiftDefer (yyGLRStack* yystack, int yyk, yyStateNum yylrState,
* for userAction. */
static inline int
yydoAction (yyGLRStack* yystack, int yyk, yyRuleNum yyrule,
YYSTYPE* yyvalp, YYLTYPE* yylocp YY_USER_FORMALS)
YYSTYPE* yyvalp, YYLTYPE* yylocp]b4_user_formals[)
{
int yynrhs = yyrhsLength (yyrule);
@@ -1009,7 +1030,7 @@ yydoAction (yyGLRStack* yystack, int yyk, yyRuleNum yyrule,
*yylocp = rhs[1-yynrhs].yystate.yyloc;
}
return yyuserAction (yyrule, yynrhs, rhs,
yyvalp, yylocp, yystack YY_USER_ARGS);
yyvalp, yylocp, yystack]b4_user_args[);
}
else
{
@@ -1037,7 +1058,7 @@ yydoAction (yyGLRStack* yystack, int yyk, yyRuleNum yyrule,
*yylocp = yyrhsVals[0].yystate.yyloc;
}
return yyuserAction (yyrule, yynrhs, yyrhsVals + (yynrhs-1),
yyvalp, yylocp, yystack YY_USER_ARGS);
yyvalp, yylocp, yystack]b4_user_args[);
}
}
@@ -1080,7 +1101,7 @@ yy_reduce_print (size_t yyk, yyRuleNum yyrule)
*/
static inline YYRESULTTAG
yyglrReduce (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
bool yyforceEval YY_USER_FORMALS)
bool yyforceEval]b4_pure_formals[)
{
size_t yyposn = yystack->yytops.yystates[yyk]->yyposn;
@@ -1090,11 +1111,11 @@ yyglrReduce (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
YYLTYPE yyloc;
YY_REDUCE_PRINT (yyk, yyrule);
YYCHK (yydoAction (yystack, yyk, yyrule, &yysval, &yyloc YY_USER_ARGS));
YYCHK (yydoAction (yystack, yyk, yyrule, &yysval, &yyloc]b4_user_args[));
yyglrShift (yystack, yyk,
yyLRgotoState (yystack->yytops.yystates[yyk]->yylrState,
yylhsNonterm (yyrule)),
yyposn, yysval, &yyloc);
yyposn, yysval, &yyloc]b4_user_args[);
YYDPRINTF ((stderr, "Stack %d entering state %d\n",
yyk, yystack->yytops.yystates[yyk]->yylrState));
}
@@ -1126,7 +1147,7 @@ yyglrReduce (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
{
if (yyp->yylrState == yynewLRState && yyp->yypred == yys)
{
yyaddDeferredAction (yystack, yyp, yys0, yyrule);
yyaddDeferredAction (yystack, yyp, yys0, yyrule]b4_pure_args[);
yymarkStackDeleted (yystack, yyk);
YYDPRINTF ((stderr, "Merging stack %d into stack %d.\n",
yyk, yyi));
@@ -1136,7 +1157,7 @@ yyglrReduce (yyGLRStack* yystack, size_t yyk, yyRuleNum yyrule,
}
}
yystack->yytops.yystates[yyk] = yys;
yyglrShiftDefer (yystack, yyk, yynewLRState, yyposn, yys0, yyrule);
yyglrShiftDefer (yystack, yyk, yynewLRState, yyposn, yys0, yyrule]b4_pure_args[);
}
return 0;
}
@@ -1236,23 +1257,23 @@ yypreference (yySemanticOption* y0, yySemanticOption* y1)
static YYRESULTTAG yyresolveValue (yySemanticOption* yyoptionList,
yyGLRStack* yystack, YYSTYPE* yyvalp,
YYLTYPE* yylocp YY_USER_FORMALS);
YYLTYPE* yylocp]b4_user_formals[);
static YYRESULTTAG
yyresolveStates (yyGLRState* yys, int yyn, yyGLRStack* yystack YY_USER_FORMALS)
yyresolveStates (yyGLRState* yys, int yyn, yyGLRStack* yystack]b4_user_formals[)
{
YYRESULTTAG yyflag;
if (0 < yyn)
{
assert (yys->yypred != NULL);
yyflag = yyresolveStates (yys->yypred, yyn-1, yystack YY_USER_ARGS);
yyflag = yyresolveStates (yys->yypred, yyn-1, yystack]b4_user_args[);
if (yyflag != yyok)
return yyflag;
if (! yys->yyresolved)
{
yyflag = yyresolveValue (yys->yysemantics.yyfirstVal, yystack,
&yys->yysemantics.yysval, &yys->yyloc
YY_USER_ARGS);
]b4_user_args[);
if (yyflag != yyok)
return yyflag;
yys->yyresolved = yytrue;
@@ -1263,14 +1284,14 @@ yyresolveStates (yyGLRState* yys, int yyn, yyGLRStack* yystack YY_USER_FORMALS)
static YYRESULTTAG
yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystack,
YYSTYPE* yyvalp, YYLTYPE* yylocp YY_USER_FORMALS)
YYSTYPE* yyvalp, YYLTYPE* yylocp]b4_user_formals[)
{
yyGLRStackItem yyrhsVals[YYMAXRHS];
int yynrhs, yyi;
yyGLRState* yys;
yynrhs = yyrhsLength (yyopt->yyrule);
YYCHK (yyresolveStates (yyopt->yystate, yynrhs, yystack YY_USER_ARGS));
YYCHK (yyresolveStates (yyopt->yystate, yynrhs, yystack]b4_user_args[));
for (yyi = yynrhs-1, yys = yyopt->yystate; 0 <= yyi;
yyi -= 1, yys = yys->yypred)
{
@@ -1280,7 +1301,7 @@ yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystack,
yyrhsVals[yyi].yystate.yyloc = yys->yyloc;
}
return yyuserAction (yyopt->yyrule, yynrhs, yyrhsVals + (yynrhs-1),
yyvalp, yylocp, yystack YY_USER_ARGS);
yyvalp, yylocp, yystack]b4_user_args[);
}
#if YYDEBUG
@@ -1331,7 +1352,7 @@ yyreportTree (yySemanticOption* yyx, int yyindent)
static void
yyreportAmbiguity (yySemanticOption* yyx0, yySemanticOption* yyx1,
yyGLRStack* yystack)
yyGLRStack* yystack]b4_pure_formals[)
{
/* `Unused' warnings. */
(void) yyx0;
@@ -1345,7 +1366,7 @@ yyreportAmbiguity (yySemanticOption* yyx0, yySemanticOption* yyx1,
yyreportTree (yyx1, 2);
YYFPRINTF (stderr, "\n");
#endif
yyFail (yystack, "ambiguity detected");
yyFail (yystack][]b4_pure_args[, "ambiguity detected");
}
@@ -1353,7 +1374,7 @@ yyreportAmbiguity (yySemanticOption* yyx0, yySemanticOption* yyx1,
* actions, and return the result. */
static YYRESULTTAG
yyresolveValue (yySemanticOption* yyoptionList, yyGLRStack* yystack,
YYSTYPE* yyvalp, YYLTYPE* yylocp YY_USER_FORMALS)
YYSTYPE* yyvalp, YYLTYPE* yylocp]b4_user_formals[)
{
yySemanticOption* yybest;
yySemanticOption* yyp;
@@ -1369,7 +1390,7 @@ yyresolveValue (yySemanticOption* yyoptionList, yyGLRStack* yystack,
switch (yypreference (yybest, yyp))
{
case 0:
yyreportAmbiguity (yybest, yyp, yystack);
yyreportAmbiguity (yybest, yyp, yystack]b4_pure_args[);
break;
case 1:
yymerge = 1;
@@ -1386,25 +1407,25 @@ yyresolveValue (yySemanticOption* yyoptionList, yyGLRStack* yystack,
if (yymerge)
{
int yyprec = yydprec[yybest->yyrule];
YYCHK (yyresolveAction (yybest, yystack, yyvalp, yylocp YY_USER_ARGS));
YYCHK (yyresolveAction (yybest, yystack, yyvalp, yylocp]b4_user_args[));
for (yyp = yybest->yynext; yyp != NULL; yyp = yyp->yynext)
{
if (yyprec == yydprec[yyp->yyrule])
{
YYSTYPE yyval1;
YYLTYPE yydummy;
YYCHK (yyresolveAction (yyp, yystack, &yyval1, &yydummy YY_USER_ARGS));
YYCHK (yyresolveAction (yyp, yystack, &yyval1, &yydummy]b4_user_args[));
*yyvalp = yyuserMerge (yymerger[yyp->yyrule], yyvalp, &yyval1);
}
}
return yyok;
}
else
return yyresolveAction (yybest, yystack, yyvalp, yylocp YY_USER_ARGS);
return yyresolveAction (yybest, yystack, yyvalp, yylocp]b4_user_args[);
}
static YYRESULTTAG
yyresolveStack (yyGLRStack* yystack YY_USER_FORMALS)
yyresolveStack (yyGLRStack* yystack]b4_user_formals[)
{
if (yystack->yysplitPoint != NULL)
{
@@ -1416,7 +1437,7 @@ yyresolveStack (yyGLRStack* yystack YY_USER_FORMALS)
yys = yys->yypred, yyn += 1)
;
YYCHK (yyresolveStates (yystack->yytops.yystates[0], yyn, yystack
YY_USER_ARGS));
]b4_user_args[));
}
return yyok;
}
@@ -1454,7 +1475,7 @@ yycompressStack (yyGLRStack* yystack)
static YYRESULTTAG
yyprocessOneStack (yyGLRStack* yystack, int yyk,
size_t yyposn, YYSTYPE* yylvalp, YYLTYPE* yyllocp
YY_USER_FORMALS)
]b4_user_formals[)
{
int yyaction;
const short* yyconflicts;
@@ -1475,7 +1496,7 @@ yyprocessOneStack (yyGLRStack* yystack, int yyk,
yymarkStackDeleted (yystack, yyk);
return yyok;
}
YYCHK (yyglrReduce (yystack, yyk, yyrule, yyfalse YY_USER_ARGS));
YYCHK (yyglrReduce (yystack, yyk, yyrule, yyfalse]b4_lpure_args[));
}
else
{
@@ -1495,9 +1516,9 @@ yyprocessOneStack (yyGLRStack* yystack, int yyk,
YYDPRINTF ((stderr, "Splitting off stack %d from %d.\n",
yynewStack, yyk));
YYCHK (yyglrReduce (yystack, yynewStack,
*yyconflicts, yyfalse YY_USER_ARGS));
*yyconflicts, yyfalse]b4_lpure_args[));
YYCHK (yyprocessOneStack (yystack, yynewStack, yyposn,
yylvalp, yyllocp YY_USER_ARGS));
yylvalp, yyllocp]b4_user_args[));
yyconflicts += 1;
}
@@ -1505,7 +1526,8 @@ yyprocessOneStack (yyGLRStack* yystack, int yyk,
{
YYDPRINTF ((stderr, "Shifting token %s on stack %d, ",
yytokenName (*yytokenp), yyk));
yyglrShift (yystack, yyk, yyaction, yyposn+1, *yylvalp, yyllocp);
yyglrShift (yystack, yyk, yyaction, yyposn+1,
*yylvalp, yyllocp]b4_user_args[);
YYDPRINTF ((stderr, "which is now in state #%d\n",
yystack->yytops.yystates[yyk]->yylrState));
break;
@@ -1517,14 +1539,15 @@ yyprocessOneStack (yyGLRStack* yystack, int yyk,
break;
}
else
YYCHK (yyglrReduce (yystack, yyk, -yyaction, yyfalse YY_USER_ARGS));
YYCHK (yyglrReduce (yystack, yyk, -yyaction, yyfalse]b4_lpure_args[));
}
}
return yyok;
}
static void
yyreportParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
yyreportParseError (yyGLRStack* yystack,
YYSTYPE* yylvalp, YYLTYPE* yyllocp]b4_user_formals[)
{
/* `Unused' warnings. */
(void) yylvalp;
@@ -1568,12 +1591,12 @@ yyreportParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
yyprefix = " or ";
}
}
yyerror (yymsg);
yyerror (yymsg]b4_lpure_args[);
free (yymsg);
}
else
#endif
yyerror ("parse error");
yyerror ("parse error"]b4_lpure_args[);
yynerrs += 1;
}
}
@@ -1582,7 +1605,8 @@ yyreportParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
YYLVALP, and YYLLOCP point to the syntactic category, semantic
value, and location of the lookahead. */
static void
yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
yyrecoverParseError (yyGLRStack* yystack,
YYSTYPE* yylvalp, YYLTYPE* yyllocp]b4_user_formals[)
{
yySymbol* const yytokenp = yystack->yytokenp;
size_t yyk;
@@ -1596,7 +1620,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
while (yytrue)
{
if (*yytokenp == YYEOF)
yyFail (yystack, NULL);
yyFail (yystack][]b4_lpure_args[, NULL);
if (*yytokenp != YYEMPTY)
YYDPRINTF ((stderr, "Discarding token %s\n",
yytokenName (*yytokenp)));
@@ -1607,7 +1631,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
yyj = yypact[yystack->yytops.yystates[0]->yylrState];
if (yyj == YYPACT_NINF)
/* Something's not right; we shouldn't be here. */
yyFail (yystack, NULL);
yyFail (yystack][]b4_lpure_args[, NULL);
yyj += *yytokenp;
if (yyj < 0 || YYLAST < yyj || yycheck[yyj] != *yytokenp)
{
@@ -1623,7 +1647,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
if (yystack->yytops.yystates[yyk] != NULL)
break;
if (yyk >= yystack->yytops.yysize)
yyFail (yystack, NULL);
yyFail (yystack][]b4_lpure_args[, NULL);
for (yyk += 1; yyk < yystack->yytops.yysize; yyk += 1)
yymarkStackDeleted (yystack, yyk);
yyremoveDeletes (yystack);
@@ -1637,7 +1661,8 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
yycheck[yyj] == YYTERROR && yyisShiftAction (yytable[yyj]))
{
yyglrShift (yystack, 0, yytable[yyj],
yystack->yytops.yystates[0]->yyposn, *yylvalp, yyllocp);
yystack->yytops.yystates[0]->yyposn,
*yylvalp, yyllocp]b4_user_args[);
break;
}
yystack->yytops.yystates[0] = yystack->yytops.yystates[0]->yypred;
@@ -1645,7 +1670,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
yystack->yyspaceLeft += 1;
}
if (yystack->yytops.yystates[0] == NULL)
yyFail (yystack, NULL);
yyFail (yystack][]b4_lpure_args[, NULL);
}
#define YYCHK1(YYE) \
@@ -1693,7 +1718,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
if (setjmp (yystack.yyexception_buffer) != 0)
goto yyDone;
yyglrShift (&yystack, 0, 0, 0, yyval_default, &yyloc_default);
yyglrShift (&yystack, 0, 0, 0, yyval_default, &yyloc_default]b4_user_args[);
yytoken = YYEMPTY;
yyposn = 0;
@@ -1718,10 +1743,10 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
yyrule = yydefaultAction (yystate);
if (yyrule == 0)
{
yyreportParseError (&yystack, yylvalp, yyllocp);
yyreportParseError (&yystack, yylvalp, yyllocp]b4_user_args[);
goto yyuser_error;
}
YYCHK1 (yyglrReduce (&yystack, 0, yyrule, yytrue YY_USER_ARGS));
YYCHK1 (yyglrReduce (&yystack, 0, yyrule, yytrue]b4_lpure_args[));
}
else
{
@@ -1743,7 +1768,8 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
if (yytoken != YYEOF)
yytoken = YYEMPTY;
yyposn += 1;
yyglrShift (&yystack, 0, yyaction, yyposn, yylval, yyllocp);
yyglrShift (&yystack, 0, yyaction, yyposn,
yylval, yyllocp]b4_user_args[);
if (0 < yystack.yyerrState)
yystack.yyerrState -= 1;
YYDPRINTF ((stderr, "Entering state %d\n",
@@ -1751,11 +1777,11 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
}
else if (yyisErrorAction (yyaction))
{
yyreportParseError (&yystack, yylvalp, yyllocp);
yyreportParseError (&yystack, yylvalp, yyllocp]b4_user_args[);
goto yyuser_error;
}
else
YYCHK1 (yyglrReduce (&yystack, 0, -yyaction, yytrue YY_USER_ARGS));
YYCHK1 (yyglrReduce (&yystack, 0, -yyaction, yytrue]b4_lpure_args[));
}
}
@@ -1765,7 +1791,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
int yyn = yystack.yytops.yysize;
for (yys = 0; yys < yyn; yys += 1)
YYCHK1 (yyprocessOneStack (&yystack, yys, yyposn,
yylvalp, yyllocp YY_USER_ARGS));
yylvalp, yyllocp]b4_user_args[));
yytoken = YYEMPTY;
yyposn += 1;
yyremoveDeletes (&yystack);
@@ -1773,15 +1799,15 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
{
yyundeleteLastStack (&yystack);
if (yystack.yytops.yysize == 0)
yyFail (&yystack, "parse error");
YYCHK1 (yyresolveStack (&yystack YY_USER_ARGS));
yyFail (&yystack][]b4_lpure_args[, "parse error");
YYCHK1 (yyresolveStack (&yystack]b4_user_args[));
YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
yyreportParseError (&yystack, yylvalp, yyllocp);
yyreportParseError (&yystack, yylvalp, yyllocp]b4_user_args[);
goto yyuser_error;
}
else if (yystack.yytops.yysize == 1)
{
YYCHK1 (yyresolveStack (&yystack YY_USER_ARGS));
YYCHK1 (yyresolveStack (&yystack]b4_user_args[));
YYDPRINTF ((stderr, "Returning to deterministic operation.\n"));
yycompressStack (&yystack);
break;
@@ -1789,7 +1815,7 @@ yyrecoverParseError (yyGLRStack* yystack, YYSTYPE* yylvalp, YYLTYPE* yyllocp)
}
continue;
yyuser_error:
yyrecoverParseError (&yystack, yylvalp, yyllocp);
yyrecoverParseError (&yystack, yylvalp, yyllocp]b4_user_args[);
yyposn = yystack.yytops.yystates[0]->yyposn;
}
yyDone:

View File

@@ -33,19 +33,37 @@ m4_define_default([b4_stack_depth_init], [200])
# Location type.
m4_define_default([b4_location_type], [yyltype])
## ------------------------ ##
## Pure/impure interfaces. ##
## ------------------------ ##
# b4_Pure_if(IF-TRUE, IF-FALSE)
# -----------------------------
# Expand IF-TRUE, if %pure-parser and %parse-param, IF-FALSE otherwise.
m4_define([b4_Pure_if],
[b4_pure_if([m4_ifset([b4_parse_param],
[$1], [$2])],
[$2])])
# b4_pure_args
# ------------
# Arguments passed to yyerror: user args plus yylloc.
m4_define([b4_pure_args],
[b4_Pure_if([b4_location_if([, &yylloc])])[]b4_user_args])
# b4_lex_param
# ------------
# Accumule in b4_lex_param all the yylex arguments.
# Yes, this is quite ugly...
# b4_lex_param arrives quoted twice, but we want to keep only one level.
m4_define([b4_lex_param],
m4_dquote(b4_pure_if([[[[YYSTYPE *]], [[&yylval]]][]dnl
b4_location_if([, [[YYLTYPE *], [&yylloc]]])])dnl
m4_ifdef([b4_lex_param], [, ]b4_lex_param)))
# Yes, this is quite ugly...
m4_define_default([b4_parse_param])
m4_ifdef([b4_parse_param],
[m4_define([b4_parse_param],
b4_parse_param)])
## ------------ ##
@@ -56,7 +74,7 @@ m4_ifdef([b4_parse_param],
# ---------------------
# Return the smallest int type able to handle numbers ranging from
# MIN to MAX (included). We overwrite the version from c.m4 which relies
# on `signed char' which is not portable to old K&R compilers.
# on "signed char" which is not portable to old K&R compilers.
m4_define([b4_int_type],
[m4_if(b4_ints_in($@, [0], [255]), [1], [unsigned char],
b4_ints_in($@, [-128], [127]), [1], [yysigned_char],
@@ -178,15 +196,7 @@ b4_copyright([Skeleton parser for Yacc-like parsing with Bison],
define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */
/* Identify Bison output. */
#define YYBISON 1
/* Pure parsers. */
#define YYPURE b4_pure
/* Using locations. */
#define YYLSP_NEEDED b4_locations_flag
b4_identification
m4_if(b4_prefix[], [yy], [],
[/* If NAME_PREFIX is specified substitute the variables and functions
names. */
@@ -519,7 +529,7 @@ do \
} \
else \
{ \
yyerror ("syntax error: cannot back up"); \
yyerror ("syntax error: cannot back up"b4_pure_args); \
YYERROR; \
} \
while (0)
@@ -1125,15 +1135,15 @@ yyerrlab:
yycount++;
}
}
yyerror (yymsg);
yyerror (yymsg]b4_pure_args[);
YYSTACK_FREE (yymsg);
}
else
yyerror ("parse error; also virtual memory exhausted");
yyerror ("parse error; also virtual memory exhausted"]b4_pure_args[);
}
else
#endif /* YYERROR_VERBOSE */
yyerror ("parse error");
yyerror ("parse error"]b4_pure_args[);
}
goto yyerrlab1;
@@ -1248,7 +1258,7 @@ yyabortlab:
| yyoverflowlab -- parser overflow comes here. |
`----------------------------------------------*/
yyoverflowlab:
yyerror ("parser stack overflow");
yyerror ("parser stack overflow"]b4_pure_args[);
yyresult = 2;
/* Fall through. */
#endif

View File

@@ -682,7 +682,7 @@ involved, or by performing both actions, and then calling a designated
user-defined function on the resulting values to produce an arbitrary
merged result.
Let's consider an example, vastly simplified from C++.
Let's consider an example, vastly simplified from a C++ grammar.
@example
%@{
@@ -706,20 +706,20 @@ stmt : expr ';' %dprec 1
| decl %dprec 2
;
expr : ID @{ printf ("%s ", $$); @}
expr : ID @{ printf ("%s ", $$); @}
| TYPENAME '(' expr ')'
@{ printf ("%s <cast> ", $1); @}
| expr '+' expr @{ printf ("+ "); @}
| expr '=' expr @{ printf ("= "); @}
@{ printf ("%s <cast> ", $1); @}
| expr '+' expr @{ printf ("+ "); @}
| expr '=' expr @{ printf ("= "); @}
;
decl : TYPENAME declarator ';'
@{ printf ("%s <declare> ", $1); @}
@{ printf ("%s <declare> ", $1); @}
| TYPENAME declarator '=' expr ';'
@{ printf ("%s <init-declare> ", $1); @}
@{ printf ("%s <init-declare> ", $1); @}
;
declarator : ID @{ printf ("\"%s\" ", $1); @}
declarator : ID @{ printf ("\"%s\" ", $1); @}
| '(' declarator ')'
;
@end example
@@ -3559,10 +3559,11 @@ accurate parse error messages.
Rename the external symbols used in the parser so that they start with
@var{prefix} instead of @samp{yy}. The precise list of symbols renamed
is @code{yyparse}, @code{yylex}, @code{yyerror}, @code{yynerrs},
@code{yylval}, @code{yychar}, @code{yydebug}, and possible
@code{yylloc}. For example, if you use @samp{%name-prefix="c_"}, the
names become @code{c_parse}, @code{c_lex}, and so on. @xref{Multiple
Parsers, ,Multiple Parsers in the Same Program}.
@code{yylval}, @code{yylloc}, @code{yychar}, @code{yydebug}, and
possible @code{yylloc}. For example, if you use
@samp{%name-prefix="c_"}, the names become @code{c_parse}, @code{c_lex},
and so on. @xref{Multiple Parsers, ,Multiple Parsers in the Same
Program}.
@item %no-parser
Do not include any C code in the parser file; generate tables only. The
@@ -3659,9 +3660,9 @@ instead of @samp{yy}. You can use this to give each parser distinct
names that do not conflict.
The precise list of symbols renamed is @code{yyparse}, @code{yylex},
@code{yyerror}, @code{yynerrs}, @code{yylval}, @code{yychar} and
@code{yydebug}. For example, if you use @samp{-p c}, the names become
@code{cparse}, @code{clex}, and so on.
@code{yyerror}, @code{yynerrs}, @code{yylval}, @code{yylloc},
@code{yychar} and @code{yydebug}. For example, if you use @samp{-p c},
the names become @code{cparse}, @code{clex}, and so on.
@strong{All the other variables and macros associated with Bison are not
renamed.} These others are not global; there is no conflict if the same
@@ -3706,23 +3707,65 @@ encounters end-of-input or an unrecoverable syntax error. You can also
write an action which directs @code{yyparse} to return immediately
without reading further.
@deftypefun int yyparse (void)
The value returned by @code{yyparse} is 0 if parsing was successful (return
is due to end-of-input).
The value is 1 if parsing failed (return is due to a syntax error).
@end deftypefun
In an action, you can cause immediate return from @code{yyparse} by using
these macros:
@table @code
@item YYACCEPT
@defmac YYACCEPT
@findex YYACCEPT
Return immediately with value 0 (to report success).
@end defmac
@item YYABORT
@defmac YYABORT
@findex YYABORT
Return immediately with value 1 (to report failure).
@end table
@end defmac
If you use a reentrant parser, you can optionally pass additional
parameter information to it in a reentrant way. To do so, use the
declaration @code{%parse-param}:
@deffn {Directive} %parse-param @var{argument-declaration} @var{argument-name}
@findex %parse-param
Declare that @code{argument-name} is an additional @code{yyparse}
argument. This argument is also passed to @code{yyerror}. The
@var{argument-declaration} is used when declaring functions or
prototypes.
@end deffn
Here's an example. Write this in the parser:
@example
%parse-param "int *nastiness" "nastiness"
%parse-param "int *randomness" "randomness"
@end example
@noindent
Then call the parser like this:
@example
@{
int nastiness, randomness;
@dots{} /* @r{Store proper data in @code{nastiness} and @code{randomness}.} */
value = yyparse (&nastiness, &randomness);
@dots{}
@}
@end example
@noindent
In the grammar actions, use expressions like this to refer to the data:
@example
exp: @dots{} @{ @dots{}; *randomness += 1; @dots{} @}
@end example
@node Lexical
@section The Lexical Analyzer Function @code{yylex}
@@ -3927,86 +3970,48 @@ textual positions, then the type @code{YYLTYPE} will not be defined. In
this case, omit the second argument; @code{yylex} will be called with
only one argument.
@vindex YYPARSE_PARAM
If you use a reentrant parser, you can optionally pass additional
parameter information to it in a reentrant way. To do so, define the
macro @code{YYPARSE_PARAM} as a variable name. This modifies the
@code{yyparse} function to accept one argument, of type @code{void *},
with that name.
When you call @code{yyparse}, pass the address of an object, casting the
address to @code{void *}. The grammar actions can refer to the contents
of the object by casting the pointer value back to its proper type and
then dereferencing it. Here's an example. Write this in the parser:
If you wish to pass the additional parameter data to @code{yylex}, use
@code{%lex-param} just like @code{%parse-param} (@pxref{Parser
Function}).
@deffn {Directive} lex-param @var{argument-declaration} @var{argument-name}
@findex %lex-param
Declare that @code{argument-name} is an additional @code{yylex}
argument.
@end deffn
For instance:
@example
%@{
struct parser_control
@{
int nastiness;
int randomness;
@};
#define YYPARSE_PARAM parm
%@}
%parse-param "int *nastiness" "nastiness"
%lex-param "int *nastiness" "nastiness"
%parse-param "int *randomness" "randomness"
@end example
@noindent
Then call the parser like this:
results in the following signature:
@example
struct parser_control
@{
int nastiness;
int randomness;
@};
int yylex (int *nastiness);
int yyparse (int *nastiness, int *randomness);
@end example
@dots{}
If @code{%pure-parser} is added:
@{
struct parser_control foo;
@dots{} /* @r{Store proper data in @code{foo}.} */
value = yyparse ((void *) &foo);
@dots{}
@}
@example
int yylex (YYSTYPE *lvalp, int *nastiness);
int yyparse (int *nastiness, int *randomness);
@end example
@noindent
In the grammar actions, use expressions like this to refer to the data:
and finally, if both @code{%pure-parser} and @code{%locations} are used:
@example
((struct parser_control *) parm)->randomness
int yylex (YYSTYPE *lvalp, YYLTYPE *llocp, int *nastiness);
int yyparse (int *nastiness, int *randomness);
@end example
@vindex YYLEX_PARAM
If you wish to pass the additional parameter data to @code{yylex},
define the macro @code{YYLEX_PARAM} just like @code{YYPARSE_PARAM}, as
shown here:
@example
%@{
struct parser_control
@{
int nastiness;
int randomness;
@};
#define YYPARSE_PARAM parm
#define YYLEX_PARAM parm
%@}
@end example
You should then define @code{yylex} to accept one additional
argument---the value of @code{parm}. (This makes either two or three
arguments in total, depending on whether an argument of type
@code{YYLTYPE} is passed.) You can declare the argument as a pointer to
the proper object type, or you can declare it as @code{void *} and
access the contents as shown above.
You can use @samp{%pure-parser} to request a reentrant parser without
also using @code{YYPARSE_PARAM}. Then you should call @code{yyparse}
with no arguments, as usual.
@node Error Reporting
@section The Error Reporting Function @code{yyerror}
@cindex error reporting function
@@ -4026,13 +4031,11 @@ called by @code{yyparse} whenever a syntax error is found, and it
receives one argument. For a parse error, the string is normally
@w{@code{"parse error"}}.
@findex YYERROR_VERBOSE
If you define the macro @code{YYERROR_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{"parse error"}}. It doesn't matter what
definition you use for @code{YYERROR_VERBOSE}, just whether you define
it.
@findex %error-verbose
If you invoke the directive @code{%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{"parse error"}}.
The parser can detect one other kind of error: stack overflow. This
happens when the input contains constructions that are very deeply
@@ -4061,6 +4064,50 @@ error recovery if you have written suitable error recovery grammar rules
(@pxref{Error Recovery}). If recovery is impossible, @code{yyparse} will
immediately return 1.
Oviously, in location tracking pure parsers, @code{yyerror} should have
an access to the current location. This is indeed the case for the GLR
parsers, but not for the Yacc parser, for historical reasons. I.e., if
@samp{%locations %pure-parser} is passed then the prototypes for
@code{yyerror} are:
@example
void yyerror (const char *msg); /* Yacc parsers. */
void yyerror (const char *msg, YYLTYPE *locp); /* GLR parsers. */
@end example
If @samp{%parse-param "int *nastiness" "nastiness"} is used, then:
@example
void yyerror (int *randomness); /* Yacc parsers. */
void yyerror (int *randomness); /* GLR parsers. */
@end example
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{%pure-parser} are pure. I.e.:
@example
/* Location tracking. */
%locations
/* Pure yylex. */
%pure-parser
%lex-param "int *nastiness" "nastiness"
/* Pure yyparse. */
%parse-param "int *nastiness" "nastiness"
%parse-param "int *randomness" "randomness"
@end example
@noindent
results in the following signatures for all the parser kinds:
@example
int yylex (YYSTYPE *lvalp, YYLTYPE *llocp, int *nastiness);
int yyparse (int *nastiness, int *randomness);
void yyerror (const char *msg, YYLTYPE *locp,
int *nastiness, int *randomness);
@end example
@vindex yynerrs
The variable @code{yynerrs} contains the number of syntax errors
encountered so far. Normally this variable is global; but if you
@@ -5450,9 +5497,9 @@ state 0
$accept -> . exp $ (rule 0)
NUM shift, and go to state 1
NUM shift, and go to state 1
exp go to state 2
exp go to state 2
@end example
This reads as follows: ``state 0 corresponds to being at the very
@@ -5499,7 +5546,7 @@ state 1
exp -> NUM . (rule 5)
$default reduce using rule 5 (exp)
$default reduce using rule 5 (exp)
@end example
@noindent
@@ -5517,11 +5564,11 @@ state 2
exp -> exp . '*' exp (rule 3)
exp -> exp . '/' exp (rule 4)
$ shift, and go to state 3
'+' shift, and go to state 4
'-' shift, and go to state 5
'*' shift, and go to state 6
'/' shift, and go to state 7
$ shift, and go to state 3
'+' shift, and go to state 4
'-' shift, and go to state 5
'*' shift, and go to state 6
'/' shift, and go to state 7
@end example
@noindent
@@ -5540,7 +5587,7 @@ state 3
$accept -> exp $ . (rule 0)
$default accept
$default accept
@end example
@noindent
@@ -5555,33 +5602,33 @@ state 4
exp -> exp '+' . exp (rule 1)
NUM shift, and go to state 1
NUM shift, and go to state 1
exp go to state 8
exp go to state 8
state 5
exp -> exp '-' . exp (rule 2)
NUM shift, and go to state 1
NUM shift, and go to state 1
exp go to state 9
exp go to state 9
state 6
exp -> exp '*' . exp (rule 3)
NUM shift, and go to state 1
NUM shift, and go to state 1
exp go to state 10
exp go to state 10
state 7
exp -> exp '/' . exp (rule 4)
NUM shift, and go to state 1
NUM shift, and go to state 1
exp go to state 11
exp go to state 11
@end example
As was announced in beginning of the report, @samp{State 8 contains 1
@@ -5596,11 +5643,11 @@ state 8
exp -> exp . '*' exp (rule 3)
exp -> exp . '/' exp (rule 4)
'*' shift, and go to state 6
'/' shift, and go to state 7
'*' shift, and go to state 6
'/' shift, and go to state 7
'/' [reduce using rule 1 (exp)]
$default reduce using rule 1 (exp)
'/' [reduce using rule 1 (exp)]
$default reduce using rule 1 (exp)
@end example
Indeed, there are two actions associated to the lookahead @samp{/}:
@@ -5657,11 +5704,11 @@ state 9
exp -> exp . '*' exp (rule 3)
exp -> exp . '/' exp (rule 4)
'*' shift, and go to state 6
'/' shift, and go to state 7
'*' shift, and go to state 6
'/' shift, and go to state 7
'/' [reduce using rule 2 (exp)]
$default reduce using rule 2 (exp)
'/' [reduce using rule 2 (exp)]
$default reduce using rule 2 (exp)
state 10
@@ -5671,10 +5718,10 @@ state 10
exp -> exp '*' exp . (rule 3)
exp -> exp . '/' exp (rule 4)
'/' shift, and go to state 7
'/' shift, and go to state 7
'/' [reduce using rule 3 (exp)]
$default reduce using rule 3 (exp)
'/' [reduce using rule 3 (exp)]
$default reduce using rule 3 (exp)
state 11
@@ -5684,16 +5731,16 @@ state 11
exp -> exp . '/' exp (rule 4)
exp -> exp '/' exp . (rule 4)
'+' shift, and go to state 4
'-' shift, and go to state 5
'*' shift, and go to state 6
'/' shift, and go to state 7
'+' shift, and go to state 4
'-' shift, and go to state 5
'*' shift, and go to state 6
'/' shift, and go to state 7
'+' [reduce using rule 4 (exp)]
'-' [reduce using rule 4 (exp)]
'*' [reduce using rule 4 (exp)]
'/' [reduce using rule 4 (exp)]
$default reduce using rule 4 (exp)
'+' [reduce using rule 4 (exp)]
'-' [reduce using rule 4 (exp)]
'*' [reduce using rule 4 (exp)]
'/' [reduce using rule 4 (exp)]
$default reduce using rule 4 (exp)
@end example
@noindent
@@ -6171,18 +6218,21 @@ Macro to pretend that a syntax error has just been detected: call
@code{yyparse} return 1. @xref{Error Recovery}.
@item YYERROR_VERBOSE
Macro that you define with @code{#define} in the Bison declarations
section to request verbose, specific error message strings when
@code{yyerror} is called.
An obsolete macro that you define with @code{#define} in the Bison
declarations section 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.
@item YYINITDEPTH
Macro for specifying the initial size of the parser stack.
@xref{Stack Overflow}.
@item YYLEX_PARAM
Macro for specifying an extra argument (or list of extra arguments) for
@code{yyparse} to pass to @code{yylex}. @xref{Pure Calling,, Calling
Conventions for Pure Parsers}.
An obsolete macro for specifying an extra argument (or list of extra
arguments) for @code{yyparse} to pass to @code{yylex}. he use of this
macro is deprecated, and is supported only for Yacc like parsers.
@xref{Pure Calling,, Calling Conventions for Pure Parsers}.
@item YYLTYPE
Macro for the data type of @code{yylloc}; a structure with four
@@ -6196,8 +6246,10 @@ Macro for specifying the maximum size of the parser stack.
@xref{Stack Overflow}.
@item YYPARSE_PARAM
Macro for specifying the name of a parameter that @code{yyparse} should
accept. @xref{Pure Calling,, Calling Conventions for Pure Parsers}.
An obsolete macro for specifying the name of a parameter that
@code{yyparse} should accept. The use of this macro is deprecated, and
is supported only for Yacc like parsers. @xref{Pure Calling,, Calling
Conventions for Pure Parsers}.
@item YYRECOVERING
Macro whose value indicates whether the parser is recovering from a
@@ -6278,6 +6330,10 @@ Bison declaration to assign a precedence to a rule that is used at parse
time to resolve reduce/reduce conflicts. @xref{GLR Parsers, ,Writing
@acronym{GLR} Parsers}.
@item %error-verbose
Bison declaration to request verbose, specific error message strings
when @code{yyerror} is called.
@item %file-prefix="@var{prefix}"
Bison declaration to set the prefix of the output files. @xref{Decl
Summary}.
@@ -6298,6 +6354,11 @@ Parsers, ,Writing @acronym{GLR} Parsers}.
Bison declaration to assign left associativity to token(s).
@xref{Precedence Decl, ,Operator Precedence}.
@item %lex-param "@var{argument-declaration}" "@var{argument-name}"
Bison declaration to specifying an additional parameter that
@code{yylex} should accept. @xref{Pure Calling,, Calling Conventions
for Pure Parsers}.
@item %merge
Bison declaration to assign a merging function to a rule. If there is a
reduce/reduce conflict with a rule having the same merging function, the
@@ -6319,6 +6380,11 @@ Bison declaration to assign non-associativity to token(s).
Bison declaration to set the name of the parser file. @xref{Decl
Summary}.
@item %parse-param "@var{argument-declaration}" "@var{argument-name}"
Bison declaration to specifying an additional parameter that
@code{yyparse} should accept. @xref{Parser Function,, The Parser
Function @code{yyparse}}.
@item %prec
Bison declaration to assign a precedence to a specific rule.
@xref{Contextual Precedence, ,Context-Dependent Precedence}.

View File

@@ -26,8 +26,8 @@
# ------------------------- #
# _AT_DATA_CALC_Y($1, $2, $3, [CPP-DIRECTIVES])
# ---------------------------------------------
# _AT_DATA_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
@@ -37,7 +37,7 @@ m4_define([_AT_DATA_CALC_Y],
[m4_fatal([$0: Invalid arguments: $@])])dnl
AT_DATA([calc.y],
[[/* Infix notation calculator--calc */
]$4[
%{
#include <config.h>
/* We don't need perfect functions for these tests. */
@@ -63,9 +63,6 @@ int global_count = 0;
%}
%parse-param "value_t *result", "result"
%parse-param "int *count", "count"
/* Exercise %union. */
%union
{
@@ -81,16 +78,14 @@ int global_count = 0;
# define VAL (yylval)
#endif
#define YYLLOC_FORMAL ]AT_LOCATION_IF([, YYLTYPE *yylloc])[
#define YYLLOC_ARG ]AT_LOCATION_IF([, yylloc])[
#define USE_YYLLOC ]AT_LOCATION_IF([(void) yylloc;])[
#if YYPURE
# if YYLSP_NEEDED
# define LEX_FORMALS YYSTYPE *yylval, YYLTYPE *yylloc
# define LEX_ARGS yylval, yylloc
# define USE_LEX_ARGS (void) yylval; (void) yylloc;
# else
# define LEX_FORMALS YYSTYPE *yylval
# define LEX_ARGS yylval
# define USE_LEX_ARGS (void) yylval
# endif
# define LEX_FORMALS YYSTYPE *yylval YYLLOC_FORMAL
# define LEX_ARGS yylval YYLLOC_ARG
# define USE_LEX_ARGS (void) yylval; USE_YYLLOC
# define LEX_PRE_FORMALS LEX_FORMALS,
# define LEX_PRE_ARGS LEX_ARGS,
#else
@@ -102,7 +97,13 @@ int global_count = 0;
#endif
static int power (int base, int exponent);
static void yyerror (const char *s);
/* yyerror receives the location if:
- %location & %pure & %glr
- %location & %pure & %yacc & %parse-param. */
static void yyerror (const char *s
]AT_YYERROR_ARG_LOC_IF([, YYLTYPE *yylloc])[
]AT_PARAM_IF([, value_t *result, int *count])[
);
static int yylex (LEX_FORMALS);
static int yygetc (LEX_FORMALS);
static void yyungetc (LEX_PRE_FORMALS int c);
@@ -119,27 +120,25 @@ static void yyungetc (LEX_PRE_FORMALS int c);
%left NEG /* negation--unary minus */
%right '^' /* exponentiation */
]$4[
/* Grammar follows */
%%
input:
line
| input line { ++*count; ++global_count; }
| input line { ]AT_PARAM_IF([++*count; ++global_count;])[ }
;
line:
'\n'
| exp '\n' { *result = global_result = $1; }
| exp '\n' { ]AT_PARAM_IF([*result = global_result = $1;])[ }
;
exp:
NUM { $$ = $1; }
| exp '=' exp
{
if ($1 != $3)
fprintf (stderr, "calc: error: %d != %d\n", $1, $3);
$$ = $1;
if ($1 != $3)
fprintf (stderr, "calc: error: %d != %d\n", $1, $3);
$$ = $1;
}
| exp '+' exp { $$ = $1 + $3; }
| exp '-' exp { $$ = $1 - $3; }
@@ -155,26 +154,28 @@ exp:
FILE *yyin;
static void
yyerror (const char *s)
yyerror (const char *s
]AT_YYERROR_ARG_LOC_IF([, YYLTYPE *yylloc])[
]AT_PARAM_IF([, value_t *result, int *count])[)
{
#if YYLSP_NEEDED
]AT_YYERROR_SEES_LOC_IF([
fprintf (stderr, "%d.%d-%d.%d: ",
LOC.first_line, LOC.first_column,
LOC.last_line, LOC.last_column);
#endif
])[
fprintf (stderr, "%s\n", s);
}
#if YYLSP_NEEDED
]AT_LOCATION_IF([
static YYLTYPE last_yylloc;
#endif
])[
static int
yygetc (LEX_FORMALS)
{
int res = getc (yyin);
USE_LEX_ARGS;
#if YYLSP_NEEDED
]AT_LOCATION_IF([
last_yylloc = LOC;
if (res == '\n')
{
@@ -183,7 +184,7 @@ yygetc (LEX_FORMALS)
}
else
LOC.last_column++;
#endif
])[
return res;
}
@@ -192,10 +193,10 @@ static void
yyungetc (LEX_PRE_FORMALS int c)
{
USE_LEX_ARGS;
#if YYLSP_NEEDED
]AT_LOCATION_IF([
/* Wrong when C == `\n'. */
LOC = last_yylloc;
#endif
])[
ungetc (c, yyin);
}
@@ -241,24 +242,24 @@ yylex (LEX_FORMALS)
if (init)
{
init = 0;
#if YYLSP_NEEDED
]AT_LOCATION_IF([
LOC.last_column = 1;
LOC.last_line = 1;
#endif
])[
}
#if YYLSP_NEEDED
]AT_LOCATION_IF([
LOC.first_column = LOC.last_column;
LOC.first_line = LOC.last_line;
#endif
])[
/* Skip white space. */
while ((c = yygetc (LEX_ARGS)) == ' ' || c == '\t')
{
#if YYLSP_NEEDED
]AT_LOCATION_IF([
LOC.first_column = LOC.last_column;
LOC.first_line = LOC.last_line;
#endif
])[
}
/* process numbers */
@@ -309,7 +310,7 @@ main (int argc, const char **argv)
#if YYDEBUG
yydebug = 1;
#endif
yyparse (&result, &count);
yyparse (]AT_PARAM_IF([&result, &count])[);
assert (global_result == result);
assert (global_count == count);
@@ -352,8 +353,8 @@ m4_bmatch([$1],
# _AT_CHECK_CALC_ERROR(BISON-OPTIONS, INPUT, [NUM-DEBUG-LINES],
# [ERROR-LOCATION], [IF-YYERROR-VERBOSE])
# ------------------------------------------------------------
# [VERBOSE-AND-LOCATED-ERROR-MESSAGE])
# -------------------------------------------------------------
# Run `calc' on INPUT, and expect a `parse error' message.
#
# If INPUT starts with a slash, it is used as absolute input file name,
@@ -402,7 +403,7 @@ AT_DATA([[expout]],
[$4
])
# 3. If locations are not used, remove them.
m4_bmatch([$1], [%locations], [],
AT_YYERROR_SEES_LOC_IF([],
[[sed 's/^[-0-9.]*: //' expout >at-expout
mv at-expout expout]])
# 4. If error-verbose is not used, strip the`, unexpected....' part.
@@ -414,6 +415,54 @@ AT_CHECK([cat stderr], 0, [expout])
])
# AT_CALC_PUSHDEFS($1, $2, [BISON-OPTIONS])
# -----------------------------------------
# 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.
m4_define([AT_CHECK_PUSHDEFS],
[m4_if([$1$2], $[1]$[2], [],
[m4_fatal([$0: Invalid arguments: $@])])dnl
m4_pushdef([AT_PARAM_IF],
[m4_bmatch([$3], [%parse-param], [$1], [$2])])
m4_pushdef([AT_LOCATION_IF],
[m4_bmatch([$3], [%locations], [$1], [$2])])
m4_pushdef([AT_PURE_IF],
[m4_bmatch([$3], [%pure-parser], [$1], [$2])])
m4_pushdef([AT_GLR_IF],
[m4_bmatch([$3], [%glr-parser], [$1], [$2])])
m4_pushdef([AT_PURE_AND_LOC_IF],
[m4_bmatch([$3], [%locations.*%pure-parser\|%pure-parser.*%locations],
[$1], [$2])])
m4_pushdef([AT_GLR_OR_PARAM_IF],
[m4_bmatch([$3], [%glr-parser\|%parse-param], [$1], [$2])])
# 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])])
# yyerror cannot see the locations if !glr & pure.
m4_pushdef([AT_YYERROR_SEES_LOC_IF],
[AT_LOCATION_IF([AT_GLR_IF([$1],
[AT_PURE_IF([$2], [$1])])],
[$2])])
])
# AT_CALC_POPDEFS
# ---------------
m4_define([AT_CHECK_POPDEFS],
[m4_popdef([AT_YYERROR_SEES_LOC_IF])
m4_popdef([AT_YYERROR_ARG_LOC_IF])
m4_popdef([AT_GLR_OR_PARAM_IF])
m4_popdef([AT_PURE_AND_LOC_IF])
m4_popdef([AT_GLR_IF])
m4_popdef([AT_LOCATION_IF])
m4_popdef([AT_PARAM_IF])
])
# AT_CHECK_CALC([BISON-OPTIONS])
# ------------------------------
# Start a testing chunk which compiles `calc' grammar with
@@ -422,6 +471,8 @@ m4_define([AT_CHECK_CALC],
[# We use integers to avoid dependencies upon the precision of doubles.
AT_SETUP([Calculator $1])
AT_CHECK_PUSHDEFS($[1], $[2], [$1])
AT_DATA_CALC_Y([$1])
# Specify the output files to avoid problems on different file systems.
@@ -473,6 +524,8 @@ _AT_CHECK_CALC_ERROR([$1], [(1 ++ 2) + (0 0) = 1], [82],
1.15-1.16: parse error, unexpected "number"
calc: error: 0 != 1])
AT_CHECK_POPDEFS
AT_CLEANUP
])# AT_CHECK_CALC
@@ -508,7 +561,9 @@ AT_CHECK_CALC_LALR([%error-verbose %locations %defines %name-prefix="calc" %verb
AT_CHECK_CALC_LALR([%debug])
AT_CHECK_CALC_LALR([%error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
# AT_CHECK_CALC_LALR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
AT_CHECK_CALC_LALR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc %parse-param "value_t *result", "result" %parse-param "int *count", "count"])
# ----------------------- #
@@ -541,4 +596,6 @@ AT_CHECK_CALC_GLR([%error-verbose %locations %defines %name-prefix="calc" %verbo
AT_CHECK_CALC_GLR([%debug])
AT_CHECK_CALC_GLR([%error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
# AT_CHECK_CALC_GLR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
AT_CHECK_CALC_GLR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc])
AT_CHECK_CALC_GLR([%pure-parser %error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc %parse-param "value_t *result", "result" %parse-param "int *count", "count"])

View File

@@ -36,7 +36,11 @@ $1
]m4_bmatch([$2], [stmtMerge],
[ static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1);])[
#define YYINITDEPTH 10
int yyerror (const char *s);
int yyerror (const char *s
#if YYPURE && YYLSP_NEEDED
, YYLTYPE *yylocation
#endif
);
#if YYPURE
]m4_bmatch([$1], [location],
@@ -130,7 +134,7 @@ yylex ()
break;
default:
if (isalpha (c))
{
{
i = 0;
do
@@ -153,8 +157,15 @@ yylex ()
}
int
yyerror (const char *s)
yyerror (const char *s
#if YYPURE && YYLSP_NEEDED
, YYLTYPE *yylocation
#endif
)
{
#if YYPURE && YYLSP_NEEDED
(void) *yylocation;
#endif
fprintf (stderr, "%s\n", s);
return 0;
}