mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 04:13:03 +00:00
Allow specification of semantic predicates.
These changes allow users to prefix an action with %? to indicate that it
is a semantic predicate---an expression that is evaluated immediately (not
deferred, even in GLR nondeterministic mode) and causes a syntax error if
false. In GLR parsers, this has the effect of killing one of a set of
split-off parses, just as would an ordinary syntax error.
Changelog:
* NEWS: Describe new semantic-predicate feature.
* data/c.m4 (b4_predicate_case): New definition.
* data/java.m4 (b4_predicate_case): New definition.
* data/glr.c (yyimmediate): Add definition.
(yydoAction): Remove comment, now obsolete.
Do YY_REDUCE_PRINT here.
(yyglrReduce): Alter comment to indicate that semantic values
need not be deferred.
Remove YY_REDUCE_PRINT from here; done in yydoAction.
(yyprocessOneStack): Pass immediate flag.
Delete stacks rejected by predicates in newly split-off parsers.
Change handling of yyerr so that only current stack gets deleted
when semantic predicate fails.
(yyfillin): Don't crash if a semantic value is unresolved (as may
happen in predicate rules).
Copy lr state as well in debugging mode.
Update comment on setting of yysval to include yyloc as well.
(yy_reduce_print): Add yynormal argument. Perform fillin properly.
Report unresolved RHS values.
(yyimmediate): New table.
* src/gram.h (struct rule): Add is_predicate field.
* src/output.c (user_actions_output): Use b4_predicate_case for
predicates.
(prepare_symbols): Output yyimmediate.
* src/scan-gram.l: Add %? token, SC_PREDICATE state.
* src/scan-code.l (code_props_rule_action_init): Add is_predicate
argument.
* src/scan-code.h (struct code_props): Add is_predicate field.
(code_props_rule_action_init): New interface.
* src/parse-gram.y (%?{...}): New token.
(rhs): Add %?{...} rule.
* src/parse-gram.c: Regenerate.
* src/parse-gram.h: Regenerate.
* src/reader.c (grammar_current_rule_action_append): Add
immediate argument.
(grammar_midrule_action): Use new interface for
code_props_rule_action_init.
(grammar_current_rule_action_append): Ditto.
(packgram): Transfer is_predicate value.
* src/reader.h (grammar_current_rule_action_append): New interface.
* doc/bison.texinfo: Document semantic predicates (%?).
* data/glr.c (yylhsNonterm, yyisDefaultedState,yyDefaultAction)
(yygetLRActions,yynewGLRStackItem,yyaddDeferredAction,yyinitStateSet)
(yyinitGLRStack,yyexpandGLRStack,yyupdateSplit,yymarkStackDeleted)
(yyundeleteLastStack,yyglrShift,yyglrShiftDefer,yydoAction,yyglrReduce)
(yyidenticalOptions,yymergeOptionSets,yyresolveStates,yyresolveAction)
(yyresolveLocations,yyresolveValue,yyreducePrint): Update parameter
names in comments and mention all parameters.
(struct yyGLRState): Fix description of yyposn field.
(yyresolveLocations): Correct comment so as not to imply action when
yyn1==0.
This commit is contained in:
55
ChangeLog
55
ChangeLog
@@ -1,3 +1,58 @@
|
||||
2010-07-23 Paul Hilfinger <hilfingr@EECS.Berkeley.EDU>
|
||||
|
||||
* NEWS: Describe new semantic-predicate feature.
|
||||
* data/c.m4 (b4_predicate_case): New definition.
|
||||
* data/java.m4 (b4_predicate_case): New definition.
|
||||
* data/glr.c (yyimmediate): Add definition.
|
||||
(yydoAction): Remove comment, now obsolete.
|
||||
Do YY_REDUCE_PRINT here.
|
||||
(yyglrReduce): Alter comment to indicate that semantic values
|
||||
need not be deferred.
|
||||
Remove YY_REDUCE_PRINT from here; done in yydoAction.
|
||||
(yyprocessOneStack): Pass immediate flag.
|
||||
Delete stacks rejected by predicates in newly split-off parsers.
|
||||
Change handling of yyerr so that only current stack gets deleted
|
||||
when semantic predicate fails.
|
||||
(yyfillin): Don't crash if a semantic value is unresolved (as may
|
||||
happen in predicate rules).
|
||||
Copy lr state as well in debugging mode.
|
||||
Update comment on setting of yysval to include yyloc as well.
|
||||
(yy_reduce_print): Add yynormal argument. Perform fillin properly.
|
||||
Report unresolved RHS values.
|
||||
(yyimmediate): New table.
|
||||
* src/gram.h (struct rule): Add is_predicate field.
|
||||
* src/output.c (user_actions_output): Use b4_predicate_case for
|
||||
predicates.
|
||||
(prepare_symbols): Output yyimmediate.
|
||||
* src/scan-gram.l: Add %? token, SC_PREDICATE state.
|
||||
* src/scan-code.l (code_props_rule_action_init): Add is_predicate
|
||||
argument.
|
||||
* src/scan-code.h (struct code_props): Add is_predicate field.
|
||||
(code_props_rule_action_init): New interface.
|
||||
* src/parse-gram.y (%?{...}): New token.
|
||||
(rhs): Add %?{...} rule.
|
||||
* src/parse-gram.c: Regenerate.
|
||||
* src/parse-gram.h: Regenerate.
|
||||
* src/reader.c (grammar_current_rule_action_append): Add
|
||||
immediate argument.
|
||||
(grammar_midrule_action): Use new interface for
|
||||
code_props_rule_action_init.
|
||||
(grammar_current_rule_action_append): Ditto.
|
||||
(packgram): Transfer is_predicate value.
|
||||
* src/reader.h (grammar_current_rule_action_append): New interface.
|
||||
* doc/bison.texinfo: Document semantic predicates (%?).
|
||||
|
||||
* data/glr.c (yylhsNonterm, yyisDefaultedState,yyDefaultAction)
|
||||
(yygetLRActions,yynewGLRStackItem,yyaddDeferredAction,yyinitStateSet)
|
||||
(yyinitGLRStack,yyexpandGLRStack,yyupdateSplit,yymarkStackDeleted)
|
||||
(yyundeleteLastStack,yyglrShift,yyglrShiftDefer,yydoAction,yyglrReduce)
|
||||
(yyidenticalOptions,yymergeOptionSets,yyresolveStates,yyresolveAction)
|
||||
(yyresolveLocations,yyresolveValue,yyreducePrint): Update parameter
|
||||
names in comments and mention all parameters.
|
||||
(struct yyGLRState): Fix description of yyposn field.
|
||||
(yyresolveLocations): Correct comment so as not to imply action when
|
||||
yyn1==0.
|
||||
|
||||
2010-06-17 Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
Update from GFDL GFDL 1.2 to 1.3.
|
||||
|
||||
9
NEWS
9
NEWS
@@ -51,6 +51,15 @@ Bison News
|
||||
use of the %error-verbose directive is deprecated in favor of
|
||||
%define parse.error "verbose".
|
||||
|
||||
** Semantic predicates
|
||||
|
||||
The new, experimental, semantic-predicate feature allows actions of
|
||||
the form %?{ BOOLEAN-EXPRESSION }, which cause syntax errors (as for
|
||||
YYERROR) if the expression evaluates to 0, and are evaluated immediately
|
||||
in GLR parsers, rather than being deferred. The result is that they
|
||||
allow the programmer to prune possible parses based on the values of
|
||||
runtime expressions.
|
||||
|
||||
* Changes in version 2.5 (????-??-??):
|
||||
|
||||
** Named References Support
|
||||
|
||||
@@ -417,6 +417,15 @@ b4_syncline([@oline@], [@ofile@])
|
||||
break;])
|
||||
|
||||
|
||||
# b4_predicate_case(LABEL, CONDITIONS)
|
||||
# ------------------------------------
|
||||
m4_define([b4_predicate_case],
|
||||
[ case $1:
|
||||
if (! ($2)) YYERROR;
|
||||
b4_syncline([@oline@], [@ofile@])
|
||||
break;])
|
||||
|
||||
|
||||
# b4_yydestruct_generate(FUNCTION-DECLARATOR)
|
||||
# -------------------------------------------
|
||||
# Generate the "yydestruct" function, which declaration is issued using
|
||||
|
||||
277
data/glr.c
277
data/glr.c
@@ -402,6 +402,13 @@ static const ]b4_int_type_for([b4_merger])[ yymerger[] =
|
||||
]b4_merger[
|
||||
};
|
||||
|
||||
/* YYIMMEDIATE[RULE-NUM] -- True iff rule #RULE-NUM is not to be deferred, as
|
||||
in the case of predicates. */
|
||||
static const yybool yyimmediate[] =
|
||||
{
|
||||
]b4_immediate[
|
||||
};
|
||||
|
||||
/* YYCONFLP[YYPACT[STATE-NUM]] -- Pointer into YYCONFL of start of
|
||||
list of conflicting reductions corresponding to action entry for
|
||||
state STATE-NUM in yytable. 0 means no conflicts. The list in
|
||||
@@ -693,7 +700,7 @@ struct yyGLRState {
|
||||
yyStateNum yylrState;
|
||||
/** Preceding state in this stack */
|
||||
yyGLRState* yypred;
|
||||
/** Source position of the first token produced by my symbol */
|
||||
/** Source position of the last token produced by my symbol */
|
||||
size_t yyposn;
|
||||
union {
|
||||
/** First in a chain of alternative reductions producing the
|
||||
@@ -806,9 +813,16 @@ yyfillin (yyGLRStackItem *yyvsp, int yylow0, int yylow1)
|
||||
s = yyvsp[yylow0].yystate.yypred;
|
||||
for (i = yylow0-1; i >= yylow1; i -= 1)
|
||||
{
|
||||
YYASSERT (s->yyresolved);
|
||||
yyvsp[i].yystate.yyresolved = yytrue;
|
||||
yyvsp[i].yystate.yysemantics.yysval = s->yysemantics.yysval;
|
||||
#if YYDEBUG
|
||||
yyvsp[i].yystate.yylrState = s->yylrState;
|
||||
#endif
|
||||
yyvsp[i].yystate.yyresolved = s->yyresolved;
|
||||
if (s->yyresolved)
|
||||
yyvsp[i].yystate.yysemantics.yysval = s->yysemantics.yysval;
|
||||
else
|
||||
/* The effect of using yysval or yyloc (in an immediate rule) is
|
||||
* undefined. */
|
||||
yyvsp[i].yystate.yysemantics.yyfirstVal = NULL;
|
||||
yyvsp[i].yystate.yyloc = s->yyloc;
|
||||
s = yyvsp[i].yystate.yypred = s->yypred;
|
||||
}
|
||||
@@ -948,7 +962,7 @@ yydestroyGLRState (char const *yymsg, yyGLRState *yys]b4_user_formals[)
|
||||
}
|
||||
}
|
||||
|
||||
/** Left-hand-side symbol for rule #RULE. */
|
||||
/** Left-hand-side symbol for rule #YYRULE. */
|
||||
static inline yySymbol
|
||||
yylhsNonterm (yyRuleNum yyrule)
|
||||
{
|
||||
@@ -958,7 +972,7 @@ yylhsNonterm (yyRuleNum yyrule)
|
||||
#define yypact_value_is_default(yystate) \
|
||||
]b4_table_value_equals([[pact]], [[yystate]], [b4_pact_ninf])[
|
||||
|
||||
/** True iff LR state STATE has only a default reduction (regardless
|
||||
/** True iff LR state YYSTATE has only a default reduction (regardless
|
||||
* of token). */
|
||||
static inline yybool
|
||||
yyisDefaultedState (yyStateNum yystate)
|
||||
@@ -966,7 +980,7 @@ yyisDefaultedState (yyStateNum yystate)
|
||||
return yypact_value_is_default (yypact[yystate]);
|
||||
}
|
||||
|
||||
/** The default reduction for STATE, assuming it has one. */
|
||||
/** The default reduction for YYSTATE, assuming it has one. */
|
||||
static inline yyRuleNum
|
||||
yydefaultAction (yyStateNum yystate)
|
||||
{
|
||||
@@ -981,8 +995,8 @@ yydefaultAction (yyStateNum yystate)
|
||||
* R < 0: Reduce on rule -R.
|
||||
* R = 0: Error.
|
||||
* R > 0: Shift to state R.
|
||||
* Set *CONFLICTS to a pointer into yyconfl to 0-terminated list of
|
||||
* conflicting reductions.
|
||||
* Set *YYCONFLICTS to a pointer into yyconfl to a 0-terminated list
|
||||
* of conflicting reductions.
|
||||
*/
|
||||
static inline void
|
||||
yygetLRActions (yyStateNum yystate, int yytoken,
|
||||
@@ -1031,9 +1045,10 @@ yyisErrorAction (int yyaction)
|
||||
|
||||
/* GLRStates */
|
||||
|
||||
/** Return a fresh GLRStackItem. Callers should call
|
||||
* YY_RESERVE_GLRSTACK afterwards to make sure there is sufficient
|
||||
* headroom. */
|
||||
/** Return a fresh GLRStackItem in YYSTACKP. The item is an LR state
|
||||
* if YYISSTATE, and otherwise a semantic option. Callers should call
|
||||
* YY_RESERVE_GLRSTACK afterwards to make sure there is sufficient
|
||||
* headroom. */
|
||||
|
||||
static inline yyGLRStackItem*
|
||||
yynewGLRStackItem (yyGLRStack* yystackp, yybool yyisState)
|
||||
@@ -1046,9 +1061,9 @@ yynewGLRStackItem (yyGLRStack* yystackp, yybool yyisState)
|
||||
}
|
||||
|
||||
/** Add a new semantic action that will execute the action for rule
|
||||
* RULENUM on the semantic values in RHS to the list of
|
||||
* alternative actions for STATE. Assumes that RHS comes from
|
||||
* stack #K of *STACKP. */
|
||||
* YYRULE on the semantic values in YYRHS to the list of
|
||||
* alternative actions for YYSTATE. Assumes that YYRHS comes from
|
||||
* stack #YYK of *YYSTACKP. */
|
||||
static void
|
||||
yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate,
|
||||
yyGLRState* yyrhs, yyRuleNum yyrule)
|
||||
@@ -1073,7 +1088,7 @@ yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate,
|
||||
|
||||
/* GLRStacks */
|
||||
|
||||
/** Initialize SET to a singleton set containing an empty stack. */
|
||||
/** Initialize YYSET to a singleton set containing an empty stack. */
|
||||
static yybool
|
||||
yyinitStateSet (yyGLRStateSet* yyset)
|
||||
{
|
||||
@@ -1099,8 +1114,8 @@ static void yyfreeStateSet (yyGLRStateSet* yyset)
|
||||
YYFREE (yyset->yylookaheadNeeds);
|
||||
}
|
||||
|
||||
/** Initialize STACK to a single empty stack, with total maximum
|
||||
* capacity for all stacks of SIZE. */
|
||||
/** Initialize *YYSTACKP to a single empty stack, with total maximum
|
||||
* capacity for all stacks of YYSIZE. */
|
||||
static yybool
|
||||
yyinitGLRStack (yyGLRStack* yystackp, size_t yysize)
|
||||
{
|
||||
@@ -1122,7 +1137,7 @@ yyinitGLRStack (yyGLRStack* yystackp, size_t yysize)
|
||||
# define YYRELOC(YYFROMITEMS,YYTOITEMS,YYX,YYTYPE) \
|
||||
&((YYTOITEMS) - ((YYFROMITEMS) - (yyGLRStackItem*) (YYX)))->YYTYPE
|
||||
|
||||
/** If STACK is expandable, extend it. WARNING: Pointers into the
|
||||
/** If *YYSTACKP is expandable, extend it. WARNING: Pointers into the
|
||||
stack from outside should be considered invalid after this call.
|
||||
We always expand when there are 1 or fewer items left AFTER an
|
||||
allocation, so that we can avoid having external pointers exist
|
||||
@@ -1192,9 +1207,9 @@ yyfreeGLRStack (yyGLRStack* yystackp)
|
||||
yyfreeStateSet (&yystackp->yytops);
|
||||
}
|
||||
|
||||
/** Assuming that S is a GLRState somewhere on STACK, update the
|
||||
* splitpoint of STACK, if needed, so that it is at least as deep as
|
||||
* S. */
|
||||
/** Assuming that YYS is a GLRState somewhere on *YYSTACKP, update the
|
||||
* splitpoint of *YYSTACKP, if needed, so that it is at least as deep as
|
||||
* YYS. */
|
||||
static inline void
|
||||
yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
|
||||
{
|
||||
@@ -1202,7 +1217,7 @@ yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
|
||||
yystackp->yysplitPoint = yys;
|
||||
}
|
||||
|
||||
/** Invalidate stack #K in STACK. */
|
||||
/** Invalidate stack #YYK in *YYSTACKP. */
|
||||
static inline void
|
||||
yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk)
|
||||
{
|
||||
@@ -1211,8 +1226,8 @@ yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk)
|
||||
yystackp->yytops.yystates[yyk] = NULL;
|
||||
}
|
||||
|
||||
/** Undelete the last stack that was marked as deleted. Can only be
|
||||
done once after a deletion, and only when all other stacks have
|
||||
/** Undelete the last stack in *YYSTACKP that was marked as deleted. Can
|
||||
only be done once after a deletion, and only when all other stacks have
|
||||
been deleted. */
|
||||
static void
|
||||
yyundeleteLastStack (yyGLRStack* yystackp)
|
||||
@@ -1261,8 +1276,9 @@ yyremoveDeletes (yyGLRStack* yystackp)
|
||||
}
|
||||
}
|
||||
|
||||
/** Shift to a new state on stack #K of STACK, corresponding to LR state
|
||||
* LRSTATE, at input position POSN, with (resolved) semantic value SVAL. */
|
||||
/** Shift to a new state on stack #YYK of *YYSTACKP, corresponding to LR
|
||||
* state YYLRSTATE, at input position YYPOSN, with (resolved) semantic
|
||||
* value *YYVALP and source location *YYLOCP. */
|
||||
static inline void
|
||||
yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
|
||||
size_t yyposn,
|
||||
@@ -1281,7 +1297,7 @@ yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
|
||||
YY_RESERVE_GLRSTACK (yystackp);
|
||||
}
|
||||
|
||||
/** Shift stack #K of YYSTACK, to a new state corresponding to LR
|
||||
/** Shift stack #YYK of *YYSTACKP, to a new state corresponding to LR
|
||||
* state YYLRSTATE, at input position YYPOSN, with the (unresolved)
|
||||
* semantic value of YYRHS under the action for YYRULE. */
|
||||
static inline void
|
||||
@@ -1301,11 +1317,51 @@ yyglrShiftDefer (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
|
||||
yyaddDeferredAction (yystackp, yyk, yynewState, yyrhs, yyrule);
|
||||
}
|
||||
|
||||
/** Pop the symbols consumed by reduction #RULE from the top of stack
|
||||
* #K of STACK, and perform the appropriate semantic action on their
|
||||
#if !YYDEBUG
|
||||
# define YY_REDUCE_PRINT(Args)
|
||||
#else
|
||||
# define YY_REDUCE_PRINT(Args) \
|
||||
do { \
|
||||
if (yydebug) \
|
||||
yy_reduce_print Args; \
|
||||
} while (YYID (0))
|
||||
|
||||
/*----------------------------------------------------------------------.
|
||||
| Report that stack #YYK of *YYSTACKP is going to be reduced by YYRULE. |
|
||||
`----------------------------------------------------------------------*/
|
||||
|
||||
/*ARGSUSED*/ static inline void
|
||||
yy_reduce_print (int yynormal, yyGLRStackItem* yyrhsVals, size_t yyk, yyRuleNum yyrule]b4_user_formals[)
|
||||
{
|
||||
int yynrhs = yyrhsLength (yyrule);
|
||||
int yyi;
|
||||
]b4_parse_param_use[]dnl
|
||||
[ YYFPRINTF (stderr, "Reducing stack %lu by rule %d (line %lu):\n",
|
||||
(unsigned long int) yyk, yyrule - 1,
|
||||
(unsigned long int) yyrline[yyrule]);
|
||||
if (! yynormal)
|
||||
yyfillin (yyrhsVals, 1, -yynrhs);
|
||||
/* The symbols being reduced. */
|
||||
for (yyi = 0; yyi < yynrhs; yyi++)
|
||||
{
|
||||
YYFPRINTF (stderr, " $%d = ", yyi + 1);
|
||||
yy_symbol_print (stderr,
|
||||
yystos[yyrhsVals[yyi - yynrhs + 1].yystate.yylrState],
|
||||
&yyrhsVals[yyi - yynrhs + 1].yystate.yysemantics.yysval
|
||||
]b4_locations_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
|
||||
b4_user_args[);
|
||||
if (!yyrhsVals[yyi - yynrhs + 1].yystate.yyresolved)
|
||||
YYFPRINTF (stderr, " (unresolved)");
|
||||
YYFPRINTF (stderr, "\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Pop the symbols consumed by reduction #YYRULE from the top of stack
|
||||
* #YYK of *YYSTACKP, and perform the appropriate semantic action on their
|
||||
* semantic values. Assumes that all ambiguities in semantic values
|
||||
* have been previously resolved. Set *VALP to the resulting value,
|
||||
* and *LOCP to the computed location (if any). Return value is as
|
||||
* have been previously resolved. Set *YYVALP to the resulting value,
|
||||
* and *YYLOCP to the computed location (if any). Return value is as
|
||||
* for userAction. */
|
||||
static inline YYRESULTTAG
|
||||
yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
|
||||
@@ -1321,15 +1377,12 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
|
||||
yystackp->yynextFree -= yynrhs;
|
||||
yystackp->yyspaceLeft += yynrhs;
|
||||
yystackp->yytops.yystates[0] = & yystackp->yynextFree[-1].yystate;
|
||||
YY_REDUCE_PRINT ((1, yyrhs, yyk, yyrule]b4_user_args[));
|
||||
return yyuserAction (yyrule, yynrhs, yyrhs,
|
||||
yyvalp, yylocp, yystackp]b4_user_args[);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* At present, doAction is never called in nondeterministic
|
||||
* mode, so this branch is never taken. It is here in
|
||||
* anticipation of a future feature that will allow immediate
|
||||
* evaluation of selected actions in nondeterministic mode. */
|
||||
int yyi;
|
||||
yyGLRState* yys;
|
||||
yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
|
||||
@@ -1345,60 +1398,21 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
|
||||
}
|
||||
yyupdateSplit (yystackp, yys);
|
||||
yystackp->yytops.yystates[yyk] = yys;
|
||||
YY_REDUCE_PRINT ((0, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1, yyk, yyrule]b4_user_args[));
|
||||
return yyuserAction (yyrule, yynrhs, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
|
||||
yyvalp, yylocp, yystackp]b4_user_args[);
|
||||
}
|
||||
}
|
||||
|
||||
#if !YYDEBUG
|
||||
# define YY_REDUCE_PRINT(Args)
|
||||
#else
|
||||
# define YY_REDUCE_PRINT(Args) \
|
||||
do { \
|
||||
if (yydebug) \
|
||||
yy_reduce_print Args; \
|
||||
} while (YYID (0))
|
||||
|
||||
/*----------------------------------------------------------.
|
||||
| Report that the RULE is going to be reduced on stack #K. |
|
||||
`----------------------------------------------------------*/
|
||||
|
||||
/*ARGSUSED*/ static inline void
|
||||
yy_reduce_print (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule]b4_user_formals[)
|
||||
{
|
||||
int yynrhs = yyrhsLength (yyrule);
|
||||
yybool yynormal __attribute__ ((__unused__)) =
|
||||
(yystackp->yysplitPoint == NULL);
|
||||
yyGLRStackItem* yyvsp = (yyGLRStackItem*) yystackp->yytops.yystates[yyk];
|
||||
int yylow = 1;
|
||||
int yyi;
|
||||
]b4_parse_param_use[]dnl
|
||||
[ YYFPRINTF (stderr, "Reducing stack %lu by rule %d (line %lu):\n",
|
||||
(unsigned long int) yyk, yyrule - 1,
|
||||
(unsigned long int) yyrline[yyrule]);
|
||||
/* The symbols being reduced. */
|
||||
for (yyi = 0; yyi < yynrhs; yyi++)
|
||||
{
|
||||
YYFPRINTF (stderr, " $%d = ", yyi + 1);
|
||||
yy_symbol_print (stderr,
|
||||
]yystos@{b4_rhs_data(yynrhs, yyi + 1).yylrState@}[,
|
||||
&]b4_rhs_value(yynrhs, yyi + 1)[
|
||||
]b4_locations_if([, &]b4_rhs_location(yynrhs, yyi + 1))[]dnl
|
||||
b4_user_args[);
|
||||
YYFPRINTF (stderr, "\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Pop items off stack #K of STACK according to grammar rule RULE,
|
||||
/** Pop items off stack #YYK of *YYSTACKP according to grammar rule YYRULE,
|
||||
* and push back on the resulting nonterminal symbol. Perform the
|
||||
* semantic action associated with RULE and store its value with the
|
||||
* newly pushed state, if FORCEEVAL or if STACK is currently
|
||||
* semantic action associated with YYRULE and store its value with the
|
||||
* newly pushed state, if YYFORCEEVAL or if *YYSTACKP is currently
|
||||
* unambiguous. Otherwise, store the deferred semantic action with
|
||||
* the new state. If the new state would have an identical input
|
||||
* position, LR state, and predecessor to an existing state on the stack,
|
||||
* it is identified with that existing state, eliminating stack #K from
|
||||
* the STACK. In this case, the (necessarily deferred) semantic value is
|
||||
* it is identified with that existing state, eliminating stack #YYK from
|
||||
* *YYSTACKP. In this case, the semantic value is
|
||||
* added to the options for the existing state's semantic value.
|
||||
*/
|
||||
static inline YYRESULTTAG
|
||||
@@ -1409,12 +1423,19 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
|
||||
|
||||
if (yyforceEval || yystackp->yysplitPoint == NULL)
|
||||
{
|
||||
YYRESULTTAG yyflag;
|
||||
YYSTYPE yysval;
|
||||
YYLTYPE yyloc;
|
||||
|
||||
YY_REDUCE_PRINT ((yystackp, yyk, yyrule]b4_user_args[));
|
||||
YYCHK (yydoAction (yystackp, yyk, yyrule, &yysval,
|
||||
&yyloc]b4_user_args[));
|
||||
yyflag = yydoAction (yystackp, yyk, yyrule, &yysval,
|
||||
&yyloc]b4_user_args[);
|
||||
if (yyflag == yyerr)
|
||||
{
|
||||
YYDPRINTF ((stderr, "Parse on stack %lu rejected by rule #%d.\n",
|
||||
(unsigned long int) yyk, yyrule - 1));
|
||||
}
|
||||
if (yyflag != yyok)
|
||||
return yyflag;
|
||||
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyrule], &yysval, &yyloc);
|
||||
yyglrShift (yystackp, yyk,
|
||||
yyLRgotoState (yystackp->yytops.yystates[yyk]->yylrState,
|
||||
@@ -1508,7 +1529,7 @@ yysplitStack (yyGLRStack* yystackp, size_t yyk)
|
||||
return yystackp->yytops.yysize-1;
|
||||
}
|
||||
|
||||
/** True iff Y0 and Y1 represent identical options at the top level.
|
||||
/** True iff YYY0 and YYY1 represent identical options at the top level.
|
||||
* That is, they represent the same rule applied to RHS symbols
|
||||
* that produce the same terminal symbols. */
|
||||
static yybool
|
||||
@@ -1530,8 +1551,8 @@ yyidenticalOptions (yySemanticOption* yyy0, yySemanticOption* yyy1)
|
||||
return yyfalse;
|
||||
}
|
||||
|
||||
/** Assuming identicalOptions (Y0,Y1), destructively merge the
|
||||
* alternative semantic values for the RHS-symbols of Y1 and Y0. */
|
||||
/** Assuming identicalOptions (YYY0,YYY1), destructively merge the
|
||||
* alternative semantic values for the RHS-symbols of YYY1 and YYY0. */
|
||||
static void
|
||||
yymergeOptionSets (yySemanticOption* yyy0, yySemanticOption* yyy1)
|
||||
{
|
||||
@@ -1612,11 +1633,11 @@ static YYRESULTTAG yyresolveValue (yyGLRState* yys,
|
||||
yyGLRStack* yystackp]b4_user_formals[);
|
||||
|
||||
|
||||
/** Resolve the previous N states starting at and including state S. If result
|
||||
* != yyok, some states may have been left unresolved possibly with empty
|
||||
* semantic option chains. Regardless of whether result = yyok, each state
|
||||
* has been left with consistent data so that yydestroyGLRState can be invoked
|
||||
* if necessary. */
|
||||
/** Resolve the previous YYN states starting at and including state YYS
|
||||
* on *YYSTACKP. If result != yyok, some states may have been left
|
||||
* unresolved possibly with empty semantic option chains. Regardless
|
||||
* of whether result = yyok, each state has been left with consistent
|
||||
* data so that yydestroyGLRState can be invoked if necessary. */
|
||||
static YYRESULTTAG
|
||||
yyresolveStates (yyGLRState* yys, int yyn,
|
||||
yyGLRStack* yystackp]b4_user_formals[)
|
||||
@@ -1631,9 +1652,10 @@ yyresolveStates (yyGLRState* yys, int yyn,
|
||||
return yyok;
|
||||
}
|
||||
|
||||
/** Resolve the states for the RHS of OPT, perform its user action, and return
|
||||
* the semantic value and location. Regardless of whether result = yyok, all
|
||||
* RHS states have been destroyed (assuming the user action destroys all RHS
|
||||
/** Resolve the states for the RHS of YYOPT on *YYSTACKP, perform its
|
||||
* user action, and return the semantic value and location in *YYVALP
|
||||
* and *YYLOCP. Regardless of whether result = yyok, all RHS states
|
||||
* have been destroyed (assuming the user action destroys all RHS
|
||||
* semantic values if invoked). */
|
||||
static YYRESULTTAG
|
||||
yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystackp,
|
||||
@@ -1743,9 +1765,9 @@ yyreportAmbiguity (yySemanticOption* yyx0,
|
||||
return yyabort;
|
||||
}
|
||||
|
||||
/** Starting at and including state S1, resolve the location for each of the
|
||||
* previous N1 states that is unresolved. The first semantic option of a state
|
||||
* is always chosen. */
|
||||
/** Resolve the locations for each of the YYN1 states in *YYSTACKP,
|
||||
* ending at YYS1. Has no effect on previously resolved states.
|
||||
* The first semantic option of a state is always chosen. */
|
||||
static void
|
||||
yyresolveLocations (yyGLRState* yys1, int yyn1,
|
||||
yyGLRStack *yystackp]b4_user_formals[)
|
||||
@@ -1801,11 +1823,12 @@ yyresolveLocations (yyGLRState* yys1, int yyn1,
|
||||
}
|
||||
}
|
||||
|
||||
/** Resolve the ambiguity represented in state S, perform the indicated
|
||||
* actions, and set the semantic value of S. If result != yyok, the chain of
|
||||
* semantic options in S has been cleared instead or it has been left
|
||||
* unmodified except that redundant options may have been removed. Regardless
|
||||
* of whether result = yyok, S has been left with consistent data so that
|
||||
/** Resolve the ambiguity represented in state YYS in *YYSTACKP,
|
||||
* perform the indicated actions, and set the semantic value of YYS.
|
||||
* If result != yyok, the chain of semantic options in YYS has been
|
||||
* cleared instead or it has been left unmodified except that
|
||||
* redundant options may have been removed. Regardless of whether
|
||||
* result = yyok, YYS has been left with consistent data so that
|
||||
* yydestroyGLRState can be invoked if necessary. */
|
||||
static YYRESULTTAG
|
||||
yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp]b4_user_formals[)
|
||||
@@ -1950,6 +1973,7 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
|
||||
int yyaction;
|
||||
const short int* yyconflicts;
|
||||
yyRuleNum yyrule;
|
||||
YYRESULTTAG yyflag;
|
||||
|
||||
while (yystackp->yytops.yystates[yyk] != NULL)
|
||||
{
|
||||
@@ -1969,11 +1993,21 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
|
||||
yymarkStackDeleted (yystackp, yyk);
|
||||
return yyok;
|
||||
}
|
||||
YYCHK (yyglrReduce (yystackp, yyk, yyrule, yyfalse]b4_user_args[));
|
||||
yyflag = yyglrReduce (yystackp, yyk, yyrule, yyimmediate[yyrule]]b4_user_args[);
|
||||
if (yyflag == yyerr)
|
||||
{
|
||||
YYDPRINTF ((stderr, "Stack %lu dies (predicate failure or explicit user error).\n",
|
||||
(unsigned long int) yyk));
|
||||
yymarkStackDeleted (yystackp, yyk);
|
||||
return yyok;
|
||||
}
|
||||
if (yyflag != yyok)
|
||||
return yyflag;
|
||||
}
|
||||
else
|
||||
{
|
||||
yySymbol yytoken;
|
||||
|
||||
yystackp->yytops.yylookaheadNeeds[yyk] = yytrue;
|
||||
if (yychar == YYEMPTY)
|
||||
{
|
||||
@@ -1996,14 +2030,25 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
|
||||
|
||||
while (*yyconflicts != 0)
|
||||
{
|
||||
YYRESULTTAG yyflag;
|
||||
size_t yynewStack = yysplitStack (yystackp, yyk);
|
||||
YYDPRINTF ((stderr, "Splitting off stack %lu from %lu.\n",
|
||||
(unsigned long int) yynewStack,
|
||||
(unsigned long int) yyk));
|
||||
YYCHK (yyglrReduce (yystackp, yynewStack,
|
||||
*yyconflicts, yyfalse]b4_user_args[));
|
||||
YYCHK (yyprocessOneStack (yystackp, yynewStack,
|
||||
yyposn]b4_pure_args[));
|
||||
yyflag = yyglrReduce (yystackp, yynewStack,
|
||||
*yyconflicts,
|
||||
yyimmediate[*yyconflicts]]b4_user_args[);
|
||||
if (yyflag == yyok)
|
||||
YYCHK (yyprocessOneStack (yystackp, yynewStack,
|
||||
yyposn]b4_pure_args[));
|
||||
else if (yyflag == yyerr)
|
||||
{
|
||||
YYDPRINTF ((stderr, "Stack %lu dies.\n",
|
||||
(unsigned long int) yynewStack));
|
||||
yymarkStackDeleted (yystackp, yynewStack);
|
||||
}
|
||||
else
|
||||
return yyflag;
|
||||
yyconflicts += 1;
|
||||
}
|
||||
|
||||
@@ -2017,8 +2062,19 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
|
||||
break;
|
||||
}
|
||||
else
|
||||
YYCHK (yyglrReduce (yystackp, yyk, -yyaction,
|
||||
yyfalse]b4_user_args[));
|
||||
{
|
||||
yyflag = yyglrReduce (yystackp, yyk, -yyaction,
|
||||
yyimmediate[-yyaction]]b4_user_args[);
|
||||
if (yyflag == yyerr)
|
||||
{
|
||||
YYDPRINTF ((stderr, "Stack %lu dies (predicate failure or explicit user error).\n",
|
||||
(unsigned long int) yyk));
|
||||
yymarkStackDeleted (yystackp, yyk);
|
||||
break;
|
||||
}
|
||||
else if (yyflag != yyok)
|
||||
return yyflag;
|
||||
}
|
||||
}
|
||||
}
|
||||
return yyok;
|
||||
@@ -2249,7 +2305,6 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
|
||||
} \
|
||||
} while (YYID (0))
|
||||
|
||||
|
||||
/*----------.
|
||||
| yyparse. |
|
||||
`----------*/
|
||||
|
||||
@@ -169,6 +169,13 @@ m4_define([b4_case], [ case $1:
|
||||
break;
|
||||
])
|
||||
|
||||
# b4_predicate_case(LABEL, CONDITIONS)
|
||||
# ------------------------------------
|
||||
m4_define([b4_predicate_case], [ case $1:
|
||||
if (! ($2)) YYERROR;
|
||||
break;
|
||||
])
|
||||
|
||||
|
||||
## ---------------- ##
|
||||
## Default values. ##
|
||||
|
||||
@@ -136,6 +136,7 @@ Writing @acronym{GLR} Parsers
|
||||
* Simple GLR Parsers:: Using @acronym{GLR} parsers on unambiguous grammars.
|
||||
* Merging GLR Parses:: Using @acronym{GLR} parsers to resolve ambiguities.
|
||||
* GLR Semantic Actions:: Deferred semantic actions have special concerns.
|
||||
* Semantic Predicates:: Controlling a parse with arbitrary computations.
|
||||
* Compiler Requirements:: @acronym{GLR} parsers require a modern C compiler.
|
||||
|
||||
Examples
|
||||
@@ -758,6 +759,7 @@ merged result.
|
||||
* Simple GLR Parsers:: Using @acronym{GLR} parsers on unambiguous grammars.
|
||||
* Merging GLR Parses:: Using @acronym{GLR} parsers to resolve ambiguities.
|
||||
* GLR Semantic Actions:: Deferred semantic actions have special concerns.
|
||||
* Semantic Predicates:: Controlling a parse with arbitrary computations.
|
||||
* Compiler Requirements:: @acronym{GLR} parsers require a modern C compiler.
|
||||
@end menu
|
||||
|
||||
@@ -1163,6 +1165,65 @@ In a deferred semantic action, its effect is undefined.
|
||||
Also, see @ref{Location Default Action, ,Default Action for Locations}, which
|
||||
describes a special usage of @code{YYLLOC_DEFAULT} in @acronym{GLR} parsers.
|
||||
|
||||
@node Semantic Predicates
|
||||
@subsection Controlling a Parse with Arbitrary Predicates
|
||||
@findex %?
|
||||
@cindex Semantic predicates in @acronym{GLR} parsers
|
||||
|
||||
In addition to the @code{%dprec} and @code{%merge} directives,
|
||||
@acronym{GLR} parsers
|
||||
allow you to reject parses on the basis of arbitrary computations executed
|
||||
in user code, without having Bison treat this rejection as an error
|
||||
if there are alternative parses. (This feature is experimental and may
|
||||
evolve. We welcome user feedback.) For example,
|
||||
|
||||
@smallexample
|
||||
widget :
|
||||
%?@{ new_syntax @} "widget" id new_args @{ $$ = f($3, $4); @}
|
||||
| %?@{ !new_syntax @} "widget" id old_args @{ $$ = f($3, $4); @}
|
||||
;
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
is one way to allow the same parser to handle two different syntaxes for
|
||||
widgets. The clause preceded by @code{%?} is treated like an ordinary
|
||||
action, except that its text is treated as an expression and is always
|
||||
evaluated immediately (even when in nondeterministic mode). If the
|
||||
expression yields 0 (false), the clause is treated as a syntax error,
|
||||
which, in a nondeterministic parser, causes the stack in which it is reduced
|
||||
to die. In a deterministic parser, it acts like YYERROR.
|
||||
|
||||
As the example shows, predicates otherwise look like semantic actions, and
|
||||
therefore you must be take them into account when determining the numbers
|
||||
to use for denoting the semantic values of right-hand side symbols.
|
||||
Predicate actions, however, have no defined value, and may not be given
|
||||
labels.
|
||||
|
||||
There is a subtle difference between semantic predicates and ordinary
|
||||
actions in nondeterministic mode, since the latter are deferred.
|
||||
For example, we could try to rewrite the previous example as
|
||||
|
||||
@smallexample
|
||||
widget :
|
||||
@{ if (!new_syntax) YYERROR; @} "widget" id new_args @{ $$ = f($3, $4); @}
|
||||
| @{ if (new_syntax) YYERROR; @} "widget" id old_args @{ $$ = f($3, $4); @}
|
||||
;
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
(reversing the sense of the predicate tests to cause an error when they are
|
||||
false). However, this
|
||||
does @emph{not} have the same effect if @code{new_args} and @code{old_args}
|
||||
have overlapping syntax.
|
||||
Since the mid-rule actions testing @code{new_syntax} are deferred,
|
||||
a @acronym{GLR} parser first encounters the unresolved ambiguous reduction
|
||||
for cases where @code{new_args} and @code{old_args} recognize the same string
|
||||
@emph{before} performing the tests of @code{new_syntax}. It therefore
|
||||
reports an error.
|
||||
|
||||
Finally, be careful in writing predicates: deferred actions have not been
|
||||
evaluated, so that using them in a predicate will have undefined effects.
|
||||
|
||||
@node Compiler Requirements
|
||||
@subsection Considerations when Compiling @acronym{GLR} Parsers
|
||||
@cindex @code{inline}
|
||||
@@ -10610,6 +10671,19 @@ file. @xref{Grammar Outline, ,Outline of a Bison
|
||||
Grammar}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Directive} %?@{@var{expression}@}
|
||||
Predicate actions. This is a type of action clause that may appear in
|
||||
rules. The expression is evaluated, and if false, causes a syntax error. In
|
||||
@acronym{GLR} parsers during nondeterministic operation,
|
||||
this silently causes an alternative parse to die. During deterministic
|
||||
operation, it is the same as the effect of YYERROR.
|
||||
@xref{Semantic Predicates}.
|
||||
|
||||
This feature is experimental.
|
||||
More user feedback will help to determine whether it should become a permanent
|
||||
feature.
|
||||
@end deffn
|
||||
|
||||
@deffn {Construct} /*@dots{}*/
|
||||
Comment delimiters, as in C.
|
||||
@end deffn
|
||||
|
||||
@@ -194,6 +194,7 @@ typedef struct
|
||||
|
||||
location location;
|
||||
bool useful;
|
||||
bool is_predicate;
|
||||
|
||||
const char *action;
|
||||
location action_location;
|
||||
|
||||
11
src/output.c
11
src/output.c
@@ -204,7 +204,7 @@ prepare_symbols (void)
|
||||
|
||||
/*----------------------------------------------------------------.
|
||||
| Prepare the muscles related to the rules: r1, r2, rline, dprec, |
|
||||
| merger. |
|
||||
| merger, immediate. |
|
||||
`----------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
@@ -215,6 +215,7 @@ prepare_rules (void)
|
||||
unsigned int *r2 = xnmalloc (nrules, sizeof *r2);
|
||||
int *dprec = xnmalloc (nrules, sizeof *dprec);
|
||||
int *merger = xnmalloc (nrules, sizeof *merger);
|
||||
int *immediate = xnmalloc (nrules, sizeof *immediate);
|
||||
|
||||
rule_number r;
|
||||
for (r = 0; r < nrules; ++r)
|
||||
@@ -229,6 +230,8 @@ prepare_rules (void)
|
||||
dprec[r] = rules[r].dprec;
|
||||
/* Merger-function index (GLR). */
|
||||
merger[r] = rules[r].merger;
|
||||
/* Immediate reduction flags (GLR). */
|
||||
immediate[r] = rules[r].is_predicate;
|
||||
}
|
||||
|
||||
muscle_insert_unsigned_int_table ("rline", rline, 0, 0, nrules);
|
||||
@@ -236,6 +239,7 @@ prepare_rules (void)
|
||||
muscle_insert_unsigned_int_table ("r2", r2, 0, 0, nrules);
|
||||
muscle_insert_int_table ("dprec", dprec, 0, 0, nrules);
|
||||
muscle_insert_int_table ("merger", merger, 0, 0, nrules);
|
||||
muscle_insert_int_table ("immediate", immediate, 0, 0, nrules);
|
||||
|
||||
MUSCLE_INSERT_INT ("rules_number", nrules);
|
||||
MUSCLE_INSERT_INT ("max_left_semantic_context", max_left_semantic_context);
|
||||
@@ -349,8 +353,9 @@ user_actions_output (FILE *out)
|
||||
for (r = 0; r < nrules; ++r)
|
||||
if (rules[r].action)
|
||||
{
|
||||
fprintf (out, "b4_case(%d, [b4_syncline(%d, ", r + 1,
|
||||
rules[r].action_location.start.line);
|
||||
fprintf (out, "b4_%scase(%d, [b4_syncline(%d, ",
|
||||
rules[r].is_predicate ? "predicate_" : "",
|
||||
r + 1, rules[r].action_location.start.line);
|
||||
escaped_output (out, rules[r].action_location.start.file);
|
||||
fprintf (out, ")\n[ %s]])\n\n", rules[r].action);
|
||||
}
|
||||
|
||||
939
src/parse-gram.c
939
src/parse-gram.c
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,9 @@
|
||||
/* A Bison parser, made by GNU Bison 2.4.483-4ad39-dirty. */
|
||||
/* A Bison parser, made by GNU Bison 2.4.516-804e. */
|
||||
|
||||
/* Interface for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
|
||||
2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -31,7 +32,7 @@
|
||||
version 2.2 of Bison. */
|
||||
/* "%code requires" blocks. */
|
||||
/* Line 1658 of yacc.c */
|
||||
#line 201 "src/parse-gram.y"
|
||||
#line 202 "src/parse-gram.y"
|
||||
|
||||
# ifndef PARAM_TYPE
|
||||
# define PARAM_TYPE
|
||||
@@ -46,7 +47,7 @@
|
||||
|
||||
|
||||
/* Line 1658 of yacc.c */
|
||||
#line 50 "src/parse-gram.h"
|
||||
#line 51 "src/parse-gram.h"
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
@@ -93,21 +94,22 @@
|
||||
PERCENT_VERBOSE = 293,
|
||||
PERCENT_YACC = 294,
|
||||
BRACED_CODE = 295,
|
||||
BRACKETED_ID = 296,
|
||||
CHAR = 297,
|
||||
EPILOGUE = 298,
|
||||
EQUAL = 299,
|
||||
ID = 300,
|
||||
ID_COLON = 301,
|
||||
PERCENT_PERCENT = 302,
|
||||
PIPE = 303,
|
||||
PROLOGUE = 304,
|
||||
SEMICOLON = 305,
|
||||
TAG = 306,
|
||||
TAG_ANY = 307,
|
||||
TAG_NONE = 308,
|
||||
PERCENT_PARAM = 309,
|
||||
PERCENT_UNION = 310
|
||||
BRACED_PREDICATE = 296,
|
||||
BRACKETED_ID = 297,
|
||||
CHAR = 298,
|
||||
EPILOGUE = 299,
|
||||
EQUAL = 300,
|
||||
ID = 301,
|
||||
ID_COLON = 302,
|
||||
PERCENT_PERCENT = 303,
|
||||
PIPE = 304,
|
||||
PROLOGUE = 305,
|
||||
SEMICOLON = 306,
|
||||
TAG = 307,
|
||||
TAG_ANY = 308,
|
||||
TAG_NONE = 309,
|
||||
PERCENT_PARAM = 310,
|
||||
PERCENT_UNION = 311
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
@@ -150,21 +152,22 @@
|
||||
#define PERCENT_VERBOSE 293
|
||||
#define PERCENT_YACC 294
|
||||
#define BRACED_CODE 295
|
||||
#define BRACKETED_ID 296
|
||||
#define CHAR 297
|
||||
#define EPILOGUE 298
|
||||
#define EQUAL 299
|
||||
#define ID 300
|
||||
#define ID_COLON 301
|
||||
#define PERCENT_PERCENT 302
|
||||
#define PIPE 303
|
||||
#define PROLOGUE 304
|
||||
#define SEMICOLON 305
|
||||
#define TAG 306
|
||||
#define TAG_ANY 307
|
||||
#define TAG_NONE 308
|
||||
#define PERCENT_PARAM 309
|
||||
#define PERCENT_UNION 310
|
||||
#define BRACED_PREDICATE 296
|
||||
#define BRACKETED_ID 297
|
||||
#define CHAR 298
|
||||
#define EPILOGUE 299
|
||||
#define EQUAL 300
|
||||
#define ID 301
|
||||
#define ID_COLON 302
|
||||
#define PERCENT_PERCENT 303
|
||||
#define PIPE 304
|
||||
#define PROLOGUE 305
|
||||
#define SEMICOLON 306
|
||||
#define TAG 307
|
||||
#define TAG_ANY 308
|
||||
#define TAG_NONE 309
|
||||
#define PERCENT_PARAM 310
|
||||
#define PERCENT_UNION 311
|
||||
|
||||
|
||||
|
||||
@@ -173,7 +176,7 @@
|
||||
typedef union YYSTYPE
|
||||
{
|
||||
/* Line 1658 of yacc.c */
|
||||
#line 87 "src/parse-gram.y"
|
||||
#line 88 "src/parse-gram.y"
|
||||
|
||||
assoc assoc;
|
||||
char *code;
|
||||
@@ -186,13 +189,13 @@ typedef union YYSTYPE
|
||||
unsigned char character;
|
||||
|
||||
/* Line 1658 of yacc.c */
|
||||
#line 225 "src/parse-gram.y"
|
||||
#line 226 "src/parse-gram.y"
|
||||
|
||||
param_type param;
|
||||
|
||||
|
||||
/* Line 1658 of yacc.c */
|
||||
#line 196 "src/parse-gram.h"
|
||||
#line 199 "src/parse-gram.h"
|
||||
} YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
|
||||
@@ -118,7 +118,6 @@ static char const *char_name (char);
|
||||
%token PERCENT_DPREC "%dprec"
|
||||
%token PERCENT_MERGE "%merge"
|
||||
|
||||
|
||||
/*----------------------.
|
||||
| Global Declarations. |
|
||||
`----------------------*/
|
||||
@@ -151,6 +150,7 @@ static char const *char_name (char);
|
||||
;
|
||||
|
||||
%token BRACED_CODE "{...}"
|
||||
%token BRACED_PREDICATE "%?{...}"
|
||||
%token BRACKETED_ID "[identifier]"
|
||||
%token CHAR "char"
|
||||
%token EPILOGUE "epilogue"
|
||||
@@ -171,7 +171,7 @@ static char const *char_name (char);
|
||||
/* braceless is not to be used for rule or symbol actions, as it
|
||||
calls code_props_plain_init. */
|
||||
%type <chars> STRING "%{...%}" EPILOGUE braceless content.opt
|
||||
%type <code> "{...}"
|
||||
%type <code> "{...}" "%?{...}"
|
||||
%printer { fputs (quotearg_style (c_quoting_style, $$), stderr); }
|
||||
STRING
|
||||
%printer { fprintf (stderr, "{\n%s\n}", $$); }
|
||||
@@ -586,7 +586,9 @@ rhs:
|
||||
| rhs symbol named_ref.opt
|
||||
{ grammar_current_rule_symbol_append ($2, @2, $3); }
|
||||
| rhs "{...}" named_ref.opt
|
||||
{ grammar_current_rule_action_append ($2, @2, $3); }
|
||||
{ grammar_current_rule_action_append ($2, @2, $3, false); }
|
||||
| rhs "%?{...}"
|
||||
{ grammar_current_rule_action_append ($2, @2, NULL, true); }
|
||||
| rhs "%prec" symbol
|
||||
{ grammar_current_rule_prec_set ($3, @3); }
|
||||
| rhs "%dprec" INT
|
||||
@@ -601,7 +603,6 @@ named_ref.opt:
|
||||
BRACKETED_ID { $$ = named_ref_new($1, @1); }
|
||||
;
|
||||
|
||||
|
||||
/*---------------------------.
|
||||
| variable and content.opt. |
|
||||
`---------------------------*/
|
||||
|
||||
@@ -377,7 +377,8 @@ grammar_midrule_action (void)
|
||||
code_props_rule_action_init (&midrule->action_props,
|
||||
current_rule->action_props.code,
|
||||
current_rule->action_props.location,
|
||||
midrule, 0);
|
||||
midrule, 0,
|
||||
current_rule->action_props.is_predicate);
|
||||
code_props_none_init (¤t_rule->action_props);
|
||||
|
||||
if (previous_rule_end)
|
||||
@@ -468,14 +469,14 @@ grammar_current_rule_symbol_append (symbol *sym, location loc,
|
||||
|
||||
void
|
||||
grammar_current_rule_action_append (const char *action, location loc,
|
||||
named_ref *name)
|
||||
named_ref *name, bool is_predicate)
|
||||
{
|
||||
if (current_rule->action_props.code)
|
||||
grammar_midrule_action ();
|
||||
/* After all symbol declarations have been parsed, packgram invokes
|
||||
code_props_translate_code. */
|
||||
code_props_rule_action_init (¤t_rule->action_props, action, loc,
|
||||
current_rule, name);
|
||||
current_rule, name, is_predicate);
|
||||
}
|
||||
|
||||
|
||||
@@ -516,6 +517,7 @@ packgram (void)
|
||||
rules[ruleno].useful = true;
|
||||
rules[ruleno].action = p->action_props.code;
|
||||
rules[ruleno].action_location = p->action_props.location;
|
||||
rules[ruleno].is_predicate = p->action_props.is_predicate;
|
||||
|
||||
/* If the midrule's $$ is set or its $n is used, remove the `$' from the
|
||||
symbol name so that it's a user-defined symbol so that the default
|
||||
|
||||
@@ -53,7 +53,7 @@ void grammar_current_rule_merge_set (uniqstr name, location loc);
|
||||
void grammar_current_rule_symbol_append (symbol *sym, location loc,
|
||||
named_ref *named_ref);
|
||||
void grammar_current_rule_action_append (const char *action, location loc,
|
||||
named_ref *named_ref);
|
||||
named_ref *named_ref, bool);
|
||||
void reader (void);
|
||||
void free_merger_functions (void);
|
||||
|
||||
|
||||
@@ -63,6 +63,13 @@ typedef struct code_props {
|
||||
*/
|
||||
bool is_value_used;
|
||||
|
||||
/**
|
||||
* \c true iff this code is an action that is not to be deferred in
|
||||
* a non-deterministic parser.
|
||||
*/
|
||||
bool is_predicate;
|
||||
|
||||
|
||||
/** \c NULL iff \c code_props::kind is not \c CODE_PROPS_RULE_ACTION. */
|
||||
struct symbol_list *rule;
|
||||
|
||||
@@ -80,7 +87,7 @@ void code_props_none_init (code_props *self);
|
||||
|
||||
/** Equivalent to \c code_props_none_init. */
|
||||
#define CODE_PROPS_NONE_INIT \
|
||||
{CODE_PROPS_NONE, NULL, EMPTY_LOCATION_INIT, false, NULL, NULL}
|
||||
{CODE_PROPS_NONE, NULL, EMPTY_LOCATION_INIT, false, false, NULL, NULL}
|
||||
|
||||
/** Initialized by \c CODE_PROPS_NONE_INIT with no further modification. */
|
||||
extern code_props const code_props_none;
|
||||
@@ -134,7 +141,7 @@ void code_props_symbol_action_init (code_props *self, char const *code,
|
||||
*/
|
||||
void code_props_rule_action_init (code_props *self, char const *code,
|
||||
location code_loc, struct symbol_list *rule,
|
||||
named_ref *name);
|
||||
named_ref *name, bool is_predicate);
|
||||
|
||||
/**
|
||||
* \pre
|
||||
|
||||
@@ -902,7 +902,7 @@ code_props_symbol_action_init (code_props *self, char const *code,
|
||||
void
|
||||
code_props_rule_action_init (code_props *self, char const *code,
|
||||
location code_loc, symbol_list *rule,
|
||||
named_ref *name)
|
||||
named_ref *name, bool is_predicate)
|
||||
{
|
||||
self->kind = CODE_PROPS_RULE_ACTION;
|
||||
self->code = code;
|
||||
@@ -910,6 +910,7 @@ code_props_rule_action_init (code_props *self, char const *code,
|
||||
self->is_value_used = false;
|
||||
self->rule = rule;
|
||||
self->named_ref = name;
|
||||
self->is_predicate = is_predicate;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -106,11 +106,12 @@ static void unexpected_newline (boundary, char const *);
|
||||
/* A complex tag, with nested angles brackets. */
|
||||
%x SC_TAG
|
||||
|
||||
/* Three types of user code:
|
||||
/* Four types of user code:
|
||||
- prologue (code between `%{' `%}' in the first section, before %%);
|
||||
- actions, printers, union, etc, (between braced in the middle section);
|
||||
- epilogue (everything after the second %%). */
|
||||
%x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE
|
||||
- epilogue (everything after the second %%).
|
||||
- predicate (code between `%?{' and `{' in middle section); */
|
||||
%x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE SC_PREDICATE
|
||||
/* C and C++ comments in code. */
|
||||
%x SC_COMMENT SC_LINE_COMMENT
|
||||
/* Strings and characters in code. */
|
||||
@@ -285,6 +286,13 @@ splice (\\[ \f\t\v]*\n)*
|
||||
BEGIN SC_BRACED_CODE;
|
||||
}
|
||||
|
||||
/* Semantic predicate. */
|
||||
"%?"[ \f\n\t\v]*"{" {
|
||||
nesting = 0;
|
||||
code_start = loc->start;
|
||||
BEGIN SC_PREDICATE;
|
||||
}
|
||||
|
||||
/* A type. */
|
||||
"<*>" return TAG_ANY;
|
||||
"<>" return TAG_NONE;
|
||||
@@ -661,7 +669,7 @@ splice (\\[ \f\t\v]*\n)*
|
||||
| Strings, comments etc. can be found in user code. |
|
||||
`---------------------------------------------------*/
|
||||
|
||||
<SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>
|
||||
<SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE,SC_PREDICATE>
|
||||
{
|
||||
"'" {
|
||||
STRING_GROW;
|
||||
@@ -691,14 +699,32 @@ splice (\\[ \f\t\v]*\n)*
|
||||
|
||||
|
||||
/*-----------------------------------------------------------.
|
||||
| Scanning some code in braces (actions). The initial "{" is |
|
||||
| already eaten. |
|
||||
| Scanning some code in braces (actions, predicates). The |
|
||||
| initial "{" is already eaten. |
|
||||
`-----------------------------------------------------------*/
|
||||
|
||||
<SC_BRACED_CODE>
|
||||
<SC_BRACED_CODE,SC_PREDICATE>
|
||||
{
|
||||
"{"|"<"{splice}"%" STRING_GROW; nesting++;
|
||||
"%"{splice}">" STRING_GROW; nesting--;
|
||||
|
||||
/* Tokenize `<<%' correctly (as `<<' `%') rather than incorrrectly
|
||||
(as `<' `<%'). */
|
||||
"<"{splice}"<" STRING_GROW;
|
||||
|
||||
<<EOF>> {
|
||||
int token = (YY_START == SC_BRACED_CODE) ? BRACED_CODE : BRACED_PREDICATE;
|
||||
unexpected_eof (code_start, "}");
|
||||
STRING_FINISH;
|
||||
loc->start = code_start;
|
||||
val->code = last_string;
|
||||
BEGIN INITIAL;
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
<SC_BRACED_CODE>
|
||||
{
|
||||
"}" {
|
||||
obstack_1grow (&obstack_for_string, '}');
|
||||
|
||||
@@ -712,21 +738,24 @@ splice (\\[ \f\t\v]*\n)*
|
||||
return BRACED_CODE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tokenize `<<%' correctly (as `<<' `%') rather than incorrrectly
|
||||
(as `<' `<%'). */
|
||||
"<"{splice}"<" STRING_GROW;
|
||||
|
||||
<<EOF>> {
|
||||
unexpected_eof (code_start, "}");
|
||||
STRING_FINISH;
|
||||
loc->start = code_start;
|
||||
val->code = last_string;
|
||||
BEGIN INITIAL;
|
||||
return BRACED_CODE;
|
||||
}
|
||||
}
|
||||
|
||||
<SC_PREDICATE>
|
||||
{
|
||||
"}" {
|
||||
--nesting;
|
||||
if (nesting < 0)
|
||||
{
|
||||
STRING_FINISH;
|
||||
loc->start = code_start;
|
||||
val->code = last_string;
|
||||
BEGIN INITIAL;
|
||||
return BRACED_PREDICATE;
|
||||
}
|
||||
else
|
||||
obstack_1grow (&obstack_for_string, '}');
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------.
|
||||
| Scanning some prologue: from "%{" (already scanned) to "%}". |
|
||||
@@ -774,8 +803,8 @@ splice (\\[ \f\t\v]*\n)*
|
||||
| By default, grow the string obstack with the input. |
|
||||
`-----------------------------------------------------*/
|
||||
|
||||
<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE,SC_STRING,SC_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>. |
|
||||
<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PROLOGUE,SC_EPILOGUE>\n STRING_GROW;
|
||||
<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PREDICATE,SC_PROLOGUE,SC_EPILOGUE,SC_STRING,SC_CHARACTER,SC_ESCAPED_STRING,SC_ESCAPED_CHARACTER>. |
|
||||
<SC_COMMENT,SC_LINE_COMMENT,SC_BRACED_CODE,SC_PREDICATE,SC_PROLOGUE,SC_EPILOGUE>\n STRING_GROW;
|
||||
|
||||
%%
|
||||
|
||||
|
||||
Reference in New Issue
Block a user