mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
* 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:
35
ChangeLog
35
ChangeLog
@@ -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
8
NEWS
@@ -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.
|
||||
|
||||
45
data/c.m4
45
data/c.m4
@@ -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. ##
|
||||
## ------------ ##
|
||||
|
||||
216
data/glr.c
216
data/glr.c
@@ -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:
|
||||
|
||||
54
data/yacc.c
54
data/yacc.c
@@ -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
|
||||
|
||||
@@ -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}.
|
||||
|
||||
145
tests/calc.at
145
tests/calc.at
@@ -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"])
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user