* 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> 2002-11-03 Akim Demaille <akim@epita.fr>
* tests/calc.at: Change all the AT_CHECK_CALC_LALR and * 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 ago, but nobody noticed until we recently asked someone to try
building Bison with a K&R C compiler. 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: Changes in version 1.75, 2002-10-14:
* Bison should now work on 64-bit hosts. * Bison should now work on 64-bit hosts.

View File

@@ -19,9 +19,9 @@ m4_divert(-1) -*- Autoconf -*-
# 02111-1307 USA # 02111-1307 USA
## ----------- ## ## ---------------- ##
## Copyright. ## ## Identification. ##
## ----------- ## ## ---------------- ##
# b4_copyright(TITLE, YEARS) # b4_copyright(TITLE, YEARS)
# -------------------------- # --------------------------
@@ -47,6 +47,45 @@ m4_define([b4_copyright],
Boston, MA 02111-1307, USA. */]) 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. ## ## Data Types. ##
## ------------ ## ## ------------ ##

View File

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

View File

@@ -33,19 +33,37 @@ m4_define_default([b4_stack_depth_init], [200])
# Location type. # Location type.
m4_define_default([b4_location_type], [yyltype]) 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. # 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_define([b4_lex_param],
m4_dquote(b4_pure_if([[[[YYSTYPE *]], [[&yylval]]][]dnl m4_dquote(b4_pure_if([[[[YYSTYPE *]], [[&yylval]]][]dnl
b4_location_if([, [[YYLTYPE *], [&yylloc]]])])dnl b4_location_if([, [[YYLTYPE *], [&yylloc]]])])dnl
m4_ifdef([b4_lex_param], [, ]b4_lex_param))) 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 # Return the smallest int type able to handle numbers ranging from
# MIN to MAX (included). We overwrite the version from c.m4 which relies # 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_define([b4_int_type],
[m4_if(b4_ints_in($@, [0], [255]), [1], [unsigned char], [m4_if(b4_ints_in($@, [0], [255]), [1], [unsigned char],
b4_ints_in($@, [-128], [127]), [1], [yysigned_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 define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */ USER NAME SPACE" below. */
/* Identify Bison output. */ b4_identification
#define YYBISON 1
/* Pure parsers. */
#define YYPURE b4_pure
/* Using locations. */
#define YYLSP_NEEDED b4_locations_flag
m4_if(b4_prefix[], [yy], [], m4_if(b4_prefix[], [yy], [],
[/* If NAME_PREFIX is specified substitute the variables and functions [/* If NAME_PREFIX is specified substitute the variables and functions
names. */ names. */
@@ -519,7 +529,7 @@ do \
} \ } \
else \ else \
{ \ { \
yyerror ("syntax error: cannot back up"); \ yyerror ("syntax error: cannot back up"b4_pure_args); \
YYERROR; \ YYERROR; \
} \ } \
while (0) while (0)
@@ -1125,15 +1135,15 @@ yyerrlab:
yycount++; yycount++;
} }
} }
yyerror (yymsg); yyerror (yymsg]b4_pure_args[);
YYSTACK_FREE (yymsg); YYSTACK_FREE (yymsg);
} }
else else
yyerror ("parse error; also virtual memory exhausted"); yyerror ("parse error; also virtual memory exhausted"]b4_pure_args[);
} }
else else
#endif /* YYERROR_VERBOSE */ #endif /* YYERROR_VERBOSE */
yyerror ("parse error"); yyerror ("parse error"]b4_pure_args[);
} }
goto yyerrlab1; goto yyerrlab1;
@@ -1248,7 +1258,7 @@ yyabortlab:
| yyoverflowlab -- parser overflow comes here. | | yyoverflowlab -- parser overflow comes here. |
`----------------------------------------------*/ `----------------------------------------------*/
yyoverflowlab: yyoverflowlab:
yyerror ("parser stack overflow"); yyerror ("parser stack overflow"]b4_pure_args[);
yyresult = 2; yyresult = 2;
/* Fall through. */ /* Fall through. */
#endif #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 user-defined function on the resulting values to produce an arbitrary
merged result. merged result.
Let's consider an example, vastly simplified from C++. Let's consider an example, vastly simplified from a C++ grammar.
@example @example
%@{ %@{
@@ -706,20 +706,20 @@ stmt : expr ';' %dprec 1
| decl %dprec 2 | decl %dprec 2
; ;
expr : ID @{ printf ("%s ", $$); @} expr : ID @{ printf ("%s ", $$); @}
| TYPENAME '(' expr ')' | TYPENAME '(' expr ')'
@{ printf ("%s <cast> ", $1); @} @{ printf ("%s <cast> ", $1); @}
| expr '+' expr @{ printf ("+ "); @} | expr '+' expr @{ printf ("+ "); @}
| expr '=' expr @{ printf ("= "); @} | expr '=' expr @{ printf ("= "); @}
; ;
decl : TYPENAME declarator ';' decl : TYPENAME declarator ';'
@{ printf ("%s <declare> ", $1); @} @{ printf ("%s <declare> ", $1); @}
| TYPENAME declarator '=' expr ';' | TYPENAME declarator '=' expr ';'
@{ printf ("%s <init-declare> ", $1); @} @{ printf ("%s <init-declare> ", $1); @}
; ;
declarator : ID @{ printf ("\"%s\" ", $1); @} declarator : ID @{ printf ("\"%s\" ", $1); @}
| '(' declarator ')' | '(' declarator ')'
; ;
@end example @end example
@@ -3559,10 +3559,11 @@ accurate parse error messages.
Rename the external symbols used in the parser so that they start with 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 @var{prefix} instead of @samp{yy}. The precise list of symbols renamed
is @code{yyparse}, @code{yylex}, @code{yyerror}, @code{yynerrs}, is @code{yyparse}, @code{yylex}, @code{yyerror}, @code{yynerrs},
@code{yylval}, @code{yychar}, @code{yydebug}, and possible @code{yylval}, @code{yylloc}, @code{yychar}, @code{yydebug}, and
@code{yylloc}. For example, if you use @samp{%name-prefix="c_"}, the possible @code{yylloc}. For example, if you use
names become @code{c_parse}, @code{c_lex}, and so on. @xref{Multiple @samp{%name-prefix="c_"}, the names become @code{c_parse}, @code{c_lex},
Parsers, ,Multiple Parsers in the Same Program}. and so on. @xref{Multiple Parsers, ,Multiple Parsers in the Same
Program}.
@item %no-parser @item %no-parser
Do not include any C code in the parser file; generate tables only. The 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. names that do not conflict.
The precise list of symbols renamed is @code{yyparse}, @code{yylex}, The precise list of symbols renamed is @code{yyparse}, @code{yylex},
@code{yyerror}, @code{yynerrs}, @code{yylval}, @code{yychar} and @code{yyerror}, @code{yynerrs}, @code{yylval}, @code{yylloc},
@code{yydebug}. For example, if you use @samp{-p c}, the names become @code{yychar} and @code{yydebug}. For example, if you use @samp{-p c},
@code{cparse}, @code{clex}, and so on. the names become @code{cparse}, @code{clex}, and so on.
@strong{All the other variables and macros associated with Bison are not @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 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 write an action which directs @code{yyparse} to return immediately
without reading further. without reading further.
@deftypefun int yyparse (void)
The value returned by @code{yyparse} is 0 if parsing was successful (return The value returned by @code{yyparse} is 0 if parsing was successful (return
is due to end-of-input). is due to end-of-input).
The value is 1 if parsing failed (return is due to a syntax error). 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 In an action, you can cause immediate return from @code{yyparse} by using
these macros: these macros:
@table @code @defmac YYACCEPT
@item YYACCEPT
@findex YYACCEPT @findex YYACCEPT
Return immediately with value 0 (to report success). Return immediately with value 0 (to report success).
@end defmac
@item YYABORT @defmac YYABORT
@findex YYABORT @findex YYABORT
Return immediately with value 1 (to report failure). 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 @node Lexical
@section The Lexical Analyzer Function @code{yylex} @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 this case, omit the second argument; @code{yylex} will be called with
only one argument. 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 If you wish to pass the additional parameter data to @code{yylex}, use
address to @code{void *}. The grammar actions can refer to the contents @code{%lex-param} just like @code{%parse-param} (@pxref{Parser
of the object by casting the pointer value back to its proper type and Function}).
then dereferencing it. Here's an example. Write this in the parser:
@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 @example
%@{ %parse-param "int *nastiness" "nastiness"
struct parser_control %lex-param "int *nastiness" "nastiness"
@{ %parse-param "int *randomness" "randomness"
int nastiness;
int randomness;
@};
#define YYPARSE_PARAM parm
%@}
@end example @end example
@noindent @noindent
Then call the parser like this: results in the following signature:
@example @example
struct parser_control int yylex (int *nastiness);
@{ int yyparse (int *nastiness, int *randomness);
int nastiness; @end example
int randomness;
@};
@dots{} If @code{%pure-parser} is added:
@{ @example
struct parser_control foo; int yylex (YYSTYPE *lvalp, int *nastiness);
@dots{} /* @r{Store proper data in @code{foo}.} */ int yyparse (int *nastiness, int *randomness);
value = yyparse ((void *) &foo);
@dots{}
@}
@end example @end example
@noindent @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 @example
((struct parser_control *) parm)->randomness int yylex (YYSTYPE *lvalp, YYLTYPE *llocp, int *nastiness);
int yyparse (int *nastiness, int *randomness);
@end example @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 @node Error Reporting
@section The Error Reporting Function @code{yyerror} @section The Error Reporting Function @code{yyerror}
@cindex error reporting function @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 receives one argument. For a parse error, the string is normally
@w{@code{"parse error"}}. @w{@code{"parse error"}}.
@findex YYERROR_VERBOSE @findex %error-verbose
If you define the macro @code{YYERROR_VERBOSE} in the Bison declarations If you invoke the directive @code{%error-verbose} in the Bison
section (@pxref{Bison Declarations, ,The Bison Declarations Section}), declarations section (@pxref{Bison Declarations, ,The Bison Declarations
then Bison provides a more verbose and specific error message string Section}), then Bison provides a more verbose and specific error message
instead of just plain @w{@code{"parse error"}}. It doesn't matter what string instead of just plain @w{@code{"parse error"}}.
definition you use for @code{YYERROR_VERBOSE}, just whether you define
it.
The parser can detect one other kind of error: stack overflow. This The parser can detect one other kind of error: stack overflow. This
happens when the input contains constructions that are very deeply 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 (@pxref{Error Recovery}). If recovery is impossible, @code{yyparse} will
immediately return 1. 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 @vindex yynerrs
The variable @code{yynerrs} contains the number of syntax errors The variable @code{yynerrs} contains the number of syntax errors
encountered so far. Normally this variable is global; but if you encountered so far. Normally this variable is global; but if you
@@ -5450,9 +5497,9 @@ state 0
$accept -> . exp $ (rule 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 @end example
This reads as follows: ``state 0 corresponds to being at the very This reads as follows: ``state 0 corresponds to being at the very
@@ -5499,7 +5546,7 @@ state 1
exp -> NUM . (rule 5) exp -> NUM . (rule 5)
$default reduce using rule 5 (exp) $default reduce using rule 5 (exp)
@end example @end example
@noindent @noindent
@@ -5517,11 +5564,11 @@ state 2
exp -> exp . '*' exp (rule 3) exp -> exp . '*' exp (rule 3)
exp -> exp . '/' exp (rule 4) exp -> exp . '/' exp (rule 4)
$ shift, and go to state 3 $ shift, and go to state 3
'+' shift, and go to state 4 '+' shift, and go to state 4
'-' shift, and go to state 5 '-' shift, and go to state 5
'*' shift, and go to state 6 '*' shift, and go to state 6
'/' shift, and go to state 7 '/' shift, and go to state 7
@end example @end example
@noindent @noindent
@@ -5540,7 +5587,7 @@ state 3
$accept -> exp $ . (rule 0) $accept -> exp $ . (rule 0)
$default accept $default accept
@end example @end example
@noindent @noindent
@@ -5555,33 +5602,33 @@ state 4
exp -> exp '+' . exp (rule 1) 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 state 5
exp -> exp '-' . exp (rule 2) 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 state 6
exp -> exp '*' . exp (rule 3) 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 state 7
exp -> exp '/' . exp (rule 4) 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 @end example
As was announced in beginning of the report, @samp{State 8 contains 1 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 3)
exp -> exp . '/' exp (rule 4) exp -> exp . '/' exp (rule 4)
'*' shift, and go to state 6 '*' shift, and go to state 6
'/' shift, and go to state 7 '/' shift, and go to state 7
'/' [reduce using rule 1 (exp)] '/' [reduce using rule 1 (exp)]
$default reduce using rule 1 (exp) $default reduce using rule 1 (exp)
@end example @end example
Indeed, there are two actions associated to the lookahead @samp{/}: 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 3)
exp -> exp . '/' exp (rule 4) exp -> exp . '/' exp (rule 4)
'*' shift, and go to state 6 '*' shift, and go to state 6
'/' shift, and go to state 7 '/' shift, and go to state 7
'/' [reduce using rule 2 (exp)] '/' [reduce using rule 2 (exp)]
$default reduce using rule 2 (exp) $default reduce using rule 2 (exp)
state 10 state 10
@@ -5671,10 +5718,10 @@ state 10
exp -> exp '*' exp . (rule 3) exp -> exp '*' exp . (rule 3)
exp -> exp . '/' exp (rule 4) exp -> exp . '/' exp (rule 4)
'/' shift, and go to state 7 '/' shift, and go to state 7
'/' [reduce using rule 3 (exp)] '/' [reduce using rule 3 (exp)]
$default reduce using rule 3 (exp) $default reduce using rule 3 (exp)
state 11 state 11
@@ -5684,16 +5731,16 @@ state 11
exp -> exp . '/' exp (rule 4) exp -> exp . '/' exp (rule 4)
exp -> exp '/' exp . (rule 4) exp -> exp '/' exp . (rule 4)
'+' shift, and go to state 4 '+' shift, and go to state 4
'-' shift, and go to state 5 '-' shift, and go to state 5
'*' shift, and go to state 6 '*' shift, and go to state 6
'/' shift, and go to state 7 '/' 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)]
'*' [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) $default reduce using rule 4 (exp)
@end example @end example
@noindent @noindent
@@ -6171,18 +6218,21 @@ Macro to pretend that a syntax error has just been detected: call
@code{yyparse} return 1. @xref{Error Recovery}. @code{yyparse} return 1. @xref{Error Recovery}.
@item YYERROR_VERBOSE @item YYERROR_VERBOSE
Macro that you define with @code{#define} in the Bison declarations An obsolete macro that you define with @code{#define} in the Bison
section to request verbose, specific error message strings when declarations section to request verbose, specific error message strings
@code{yyerror} is called. 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 @item YYINITDEPTH
Macro for specifying the initial size of the parser stack. Macro for specifying the initial size of the parser stack.
@xref{Stack Overflow}. @xref{Stack Overflow}.
@item YYLEX_PARAM @item YYLEX_PARAM
Macro for specifying an extra argument (or list of extra arguments) for An obsolete macro for specifying an extra argument (or list of extra
@code{yyparse} to pass to @code{yylex}. @xref{Pure Calling,, Calling arguments) for @code{yyparse} to pass to @code{yylex}. he use of this
Conventions for Pure Parsers}. macro is deprecated, and is supported only for Yacc like parsers.
@xref{Pure Calling,, Calling Conventions for Pure Parsers}.
@item YYLTYPE @item YYLTYPE
Macro for the data type of @code{yylloc}; a structure with four 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}. @xref{Stack Overflow}.
@item YYPARSE_PARAM @item YYPARSE_PARAM
Macro for specifying the name of a parameter that @code{yyparse} should An obsolete macro for specifying the name of a parameter that
accept. @xref{Pure Calling,, Calling Conventions for Pure Parsers}. @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 @item YYRECOVERING
Macro whose value indicates whether the parser is recovering from a 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 time to resolve reduce/reduce conflicts. @xref{GLR Parsers, ,Writing
@acronym{GLR} Parsers}. @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}" @item %file-prefix="@var{prefix}"
Bison declaration to set the prefix of the output files. @xref{Decl Bison declaration to set the prefix of the output files. @xref{Decl
Summary}. Summary}.
@@ -6298,6 +6354,11 @@ Parsers, ,Writing @acronym{GLR} Parsers}.
Bison declaration to assign left associativity to token(s). Bison declaration to assign left associativity to token(s).
@xref{Precedence Decl, ,Operator Precedence}. @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 @item %merge
Bison declaration to assign a merging function to a rule. If there is a 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 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 Bison declaration to set the name of the parser file. @xref{Decl
Summary}. 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 @item %prec
Bison declaration to assign a precedence to a specific rule. Bison declaration to assign a precedence to a specific rule.
@xref{Contextual Precedence, ,Context-Dependent Precedence}. @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 # Produce `calc.y'. Don't call this macro directly, because it contains
# some occurrences of `$1' etc. which will be interpreted by m4. So # 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 # 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 [m4_fatal([$0: Invalid arguments: $@])])dnl
AT_DATA([calc.y], AT_DATA([calc.y],
[[/* Infix notation calculator--calc */ [[/* Infix notation calculator--calc */
]$4[
%{ %{
#include <config.h> #include <config.h>
/* We don't need perfect functions for these tests. */ /* 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. */ /* Exercise %union. */
%union %union
{ {
@@ -81,16 +78,14 @@ int global_count = 0;
# define VAL (yylval) # define VAL (yylval)
#endif #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 YYPURE
# if YYLSP_NEEDED # define LEX_FORMALS YYSTYPE *yylval YYLLOC_FORMAL
# define LEX_FORMALS YYSTYPE *yylval, YYLTYPE *yylloc # define LEX_ARGS yylval YYLLOC_ARG
# define LEX_ARGS yylval, yylloc # define USE_LEX_ARGS (void) yylval; USE_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_PRE_FORMALS LEX_FORMALS, # define LEX_PRE_FORMALS LEX_FORMALS,
# define LEX_PRE_ARGS LEX_ARGS, # define LEX_PRE_ARGS LEX_ARGS,
#else #else
@@ -102,7 +97,13 @@ int global_count = 0;
#endif #endif
static int power (int base, int exponent); 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 yylex (LEX_FORMALS);
static int yygetc (LEX_FORMALS); static int yygetc (LEX_FORMALS);
static void yyungetc (LEX_PRE_FORMALS int c); 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 */ %left NEG /* negation--unary minus */
%right '^' /* exponentiation */ %right '^' /* exponentiation */
]$4[
/* Grammar follows */ /* Grammar follows */
%% %%
input: input:
line line
| input line { ++*count; ++global_count; } | input line { ]AT_PARAM_IF([++*count; ++global_count;])[ }
; ;
line: line:
'\n' '\n'
| exp '\n' { *result = global_result = $1; } | exp '\n' { ]AT_PARAM_IF([*result = global_result = $1;])[ }
; ;
exp: exp:
NUM { $$ = $1; } NUM { $$ = $1; }
| exp '=' exp | exp '=' exp
{ {
if ($1 != $3) if ($1 != $3)
fprintf (stderr, "calc: error: %d != %d\n", $1, $3); fprintf (stderr, "calc: error: %d != %d\n", $1, $3);
$$ = $1; $$ = $1;
} }
| exp '+' exp { $$ = $1 + $3; } | exp '+' exp { $$ = $1 + $3; }
| exp '-' exp { $$ = $1 - $3; } | exp '-' exp { $$ = $1 - $3; }
@@ -155,26 +154,28 @@ exp:
FILE *yyin; FILE *yyin;
static void 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: ", fprintf (stderr, "%d.%d-%d.%d: ",
LOC.first_line, LOC.first_column, LOC.first_line, LOC.first_column,
LOC.last_line, LOC.last_column); LOC.last_line, LOC.last_column);
#endif ])[
fprintf (stderr, "%s\n", s); fprintf (stderr, "%s\n", s);
} }
#if YYLSP_NEEDED ]AT_LOCATION_IF([
static YYLTYPE last_yylloc; static YYLTYPE last_yylloc;
#endif ])[
static int static int
yygetc (LEX_FORMALS) yygetc (LEX_FORMALS)
{ {
int res = getc (yyin); int res = getc (yyin);
USE_LEX_ARGS; USE_LEX_ARGS;
#if YYLSP_NEEDED ]AT_LOCATION_IF([
last_yylloc = LOC; last_yylloc = LOC;
if (res == '\n') if (res == '\n')
{ {
@@ -183,7 +184,7 @@ yygetc (LEX_FORMALS)
} }
else else
LOC.last_column++; LOC.last_column++;
#endif ])[
return res; return res;
} }
@@ -192,10 +193,10 @@ static void
yyungetc (LEX_PRE_FORMALS int c) yyungetc (LEX_PRE_FORMALS int c)
{ {
USE_LEX_ARGS; USE_LEX_ARGS;
#if YYLSP_NEEDED ]AT_LOCATION_IF([
/* Wrong when C == `\n'. */ /* Wrong when C == `\n'. */
LOC = last_yylloc; LOC = last_yylloc;
#endif ])[
ungetc (c, yyin); ungetc (c, yyin);
} }
@@ -241,24 +242,24 @@ yylex (LEX_FORMALS)
if (init) if (init)
{ {
init = 0; init = 0;
#if YYLSP_NEEDED ]AT_LOCATION_IF([
LOC.last_column = 1; LOC.last_column = 1;
LOC.last_line = 1; LOC.last_line = 1;
#endif ])[
} }
#if YYLSP_NEEDED ]AT_LOCATION_IF([
LOC.first_column = LOC.last_column; LOC.first_column = LOC.last_column;
LOC.first_line = LOC.last_line; LOC.first_line = LOC.last_line;
#endif ])[
/* Skip white space. */ /* Skip white space. */
while ((c = yygetc (LEX_ARGS)) == ' ' || c == '\t') while ((c = yygetc (LEX_ARGS)) == ' ' || c == '\t')
{ {
#if YYLSP_NEEDED ]AT_LOCATION_IF([
LOC.first_column = LOC.last_column; LOC.first_column = LOC.last_column;
LOC.first_line = LOC.last_line; LOC.first_line = LOC.last_line;
#endif ])[
} }
/* process numbers */ /* process numbers */
@@ -309,7 +310,7 @@ main (int argc, const char **argv)
#if YYDEBUG #if YYDEBUG
yydebug = 1; yydebug = 1;
#endif #endif
yyparse (&result, &count); yyparse (]AT_PARAM_IF([&result, &count])[);
assert (global_result == result); assert (global_result == result);
assert (global_count == count); assert (global_count == count);
@@ -352,8 +353,8 @@ m4_bmatch([$1],
# _AT_CHECK_CALC_ERROR(BISON-OPTIONS, INPUT, [NUM-DEBUG-LINES], # _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. # Run `calc' on INPUT, and expect a `parse error' message.
# #
# If INPUT starts with a slash, it is used as absolute input file name, # If INPUT starts with a slash, it is used as absolute input file name,
@@ -402,7 +403,7 @@ AT_DATA([[expout]],
[$4 [$4
]) ])
# 3. If locations are not used, remove them. # 3. If locations are not used, remove them.
m4_bmatch([$1], [%locations], [], AT_YYERROR_SEES_LOC_IF([],
[[sed 's/^[-0-9.]*: //' expout >at-expout [[sed 's/^[-0-9.]*: //' expout >at-expout
mv at-expout expout]]) mv at-expout expout]])
# 4. If error-verbose is not used, strip the`, unexpected....' part. # 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]) # AT_CHECK_CALC([BISON-OPTIONS])
# ------------------------------ # ------------------------------
# Start a testing chunk which compiles `calc' grammar with # 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. [# We use integers to avoid dependencies upon the precision of doubles.
AT_SETUP([Calculator $1]) AT_SETUP([Calculator $1])
AT_CHECK_PUSHDEFS($[1], $[2], [$1])
AT_DATA_CALC_Y([$1]) AT_DATA_CALC_Y([$1])
# Specify the output files to avoid problems on different file systems. # 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" 1.15-1.16: parse error, unexpected "number"
calc: error: 0 != 1]) calc: error: 0 != 1])
AT_CHECK_POPDEFS
AT_CLEANUP AT_CLEANUP
])# AT_CHECK_CALC ])# 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([%debug])
AT_CHECK_CALC_LALR([%error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc]) 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([%debug])
AT_CHECK_CALC_GLR([%error-verbose %debug %locations %defines %name-prefix="calc" %verbose %yacc]) 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], ]m4_bmatch([$2], [stmtMerge],
[ static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1);])[ [ static YYSTYPE stmtMerge (YYSTYPE x0, YYSTYPE x1);])[
#define YYINITDEPTH 10 #define YYINITDEPTH 10
int yyerror (const char *s); int yyerror (const char *s
#if YYPURE && YYLSP_NEEDED
, YYLTYPE *yylocation
#endif
);
#if YYPURE #if YYPURE
]m4_bmatch([$1], [location], ]m4_bmatch([$1], [location],
@@ -153,8 +157,15 @@ yylex ()
} }
int 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); fprintf (stderr, "%s\n", s);
return 0; return 0;
} }