mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +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>
|
2010-06-17 Paul Eggert <eggert@cs.ucla.edu>
|
||||||
|
|
||||||
Update from GFDL GFDL 1.2 to 1.3.
|
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
|
use of the %error-verbose directive is deprecated in favor of
|
||||||
%define parse.error "verbose".
|
%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 (????-??-??):
|
* Changes in version 2.5 (????-??-??):
|
||||||
|
|
||||||
** Named References Support
|
** Named References Support
|
||||||
|
|||||||
@@ -417,6 +417,15 @@ b4_syncline([@oline@], [@ofile@])
|
|||||||
break;])
|
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)
|
# b4_yydestruct_generate(FUNCTION-DECLARATOR)
|
||||||
# -------------------------------------------
|
# -------------------------------------------
|
||||||
# Generate the "yydestruct" function, which declaration is issued using
|
# 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[
|
]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
|
/* YYCONFLP[YYPACT[STATE-NUM]] -- Pointer into YYCONFL of start of
|
||||||
list of conflicting reductions corresponding to action entry for
|
list of conflicting reductions corresponding to action entry for
|
||||||
state STATE-NUM in yytable. 0 means no conflicts. The list in
|
state STATE-NUM in yytable. 0 means no conflicts. The list in
|
||||||
@@ -693,7 +700,7 @@ struct yyGLRState {
|
|||||||
yyStateNum yylrState;
|
yyStateNum yylrState;
|
||||||
/** Preceding state in this stack */
|
/** Preceding state in this stack */
|
||||||
yyGLRState* yypred;
|
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;
|
size_t yyposn;
|
||||||
union {
|
union {
|
||||||
/** First in a chain of alternative reductions producing the
|
/** 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;
|
s = yyvsp[yylow0].yystate.yypred;
|
||||||
for (i = yylow0-1; i >= yylow1; i -= 1)
|
for (i = yylow0-1; i >= yylow1; i -= 1)
|
||||||
{
|
{
|
||||||
YYASSERT (s->yyresolved);
|
#if YYDEBUG
|
||||||
yyvsp[i].yystate.yyresolved = yytrue;
|
yyvsp[i].yystate.yylrState = s->yylrState;
|
||||||
yyvsp[i].yystate.yysemantics.yysval = s->yysemantics.yysval;
|
#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;
|
yyvsp[i].yystate.yyloc = s->yyloc;
|
||||||
s = yyvsp[i].yystate.yypred = s->yypred;
|
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
|
static inline yySymbol
|
||||||
yylhsNonterm (yyRuleNum yyrule)
|
yylhsNonterm (yyRuleNum yyrule)
|
||||||
{
|
{
|
||||||
@@ -958,7 +972,7 @@ yylhsNonterm (yyRuleNum yyrule)
|
|||||||
#define yypact_value_is_default(yystate) \
|
#define yypact_value_is_default(yystate) \
|
||||||
]b4_table_value_equals([[pact]], [[yystate]], [b4_pact_ninf])[
|
]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). */
|
* of token). */
|
||||||
static inline yybool
|
static inline yybool
|
||||||
yyisDefaultedState (yyStateNum yystate)
|
yyisDefaultedState (yyStateNum yystate)
|
||||||
@@ -966,7 +980,7 @@ yyisDefaultedState (yyStateNum yystate)
|
|||||||
return yypact_value_is_default (yypact[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
|
static inline yyRuleNum
|
||||||
yydefaultAction (yyStateNum yystate)
|
yydefaultAction (yyStateNum yystate)
|
||||||
{
|
{
|
||||||
@@ -981,8 +995,8 @@ yydefaultAction (yyStateNum yystate)
|
|||||||
* R < 0: Reduce on rule -R.
|
* R < 0: Reduce on rule -R.
|
||||||
* R = 0: Error.
|
* R = 0: Error.
|
||||||
* R > 0: Shift to state R.
|
* R > 0: Shift to state R.
|
||||||
* Set *CONFLICTS to a pointer into yyconfl to 0-terminated list of
|
* Set *YYCONFLICTS to a pointer into yyconfl to a 0-terminated list
|
||||||
* conflicting reductions.
|
* of conflicting reductions.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
yygetLRActions (yyStateNum yystate, int yytoken,
|
yygetLRActions (yyStateNum yystate, int yytoken,
|
||||||
@@ -1031,9 +1045,10 @@ yyisErrorAction (int yyaction)
|
|||||||
|
|
||||||
/* GLRStates */
|
/* GLRStates */
|
||||||
|
|
||||||
/** Return a fresh GLRStackItem. Callers should call
|
/** Return a fresh GLRStackItem in YYSTACKP. The item is an LR state
|
||||||
* YY_RESERVE_GLRSTACK afterwards to make sure there is sufficient
|
* if YYISSTATE, and otherwise a semantic option. Callers should call
|
||||||
* headroom. */
|
* YY_RESERVE_GLRSTACK afterwards to make sure there is sufficient
|
||||||
|
* headroom. */
|
||||||
|
|
||||||
static inline yyGLRStackItem*
|
static inline yyGLRStackItem*
|
||||||
yynewGLRStackItem (yyGLRStack* yystackp, yybool yyisState)
|
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
|
/** Add a new semantic action that will execute the action for rule
|
||||||
* RULENUM on the semantic values in RHS to the list of
|
* YYRULE on the semantic values in YYRHS to the list of
|
||||||
* alternative actions for STATE. Assumes that RHS comes from
|
* alternative actions for YYSTATE. Assumes that YYRHS comes from
|
||||||
* stack #K of *STACKP. */
|
* stack #YYK of *YYSTACKP. */
|
||||||
static void
|
static void
|
||||||
yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate,
|
yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate,
|
||||||
yyGLRState* yyrhs, yyRuleNum yyrule)
|
yyGLRState* yyrhs, yyRuleNum yyrule)
|
||||||
@@ -1073,7 +1088,7 @@ yyaddDeferredAction (yyGLRStack* yystackp, size_t yyk, yyGLRState* yystate,
|
|||||||
|
|
||||||
/* GLRStacks */
|
/* GLRStacks */
|
||||||
|
|
||||||
/** Initialize SET to a singleton set containing an empty stack. */
|
/** Initialize YYSET to a singleton set containing an empty stack. */
|
||||||
static yybool
|
static yybool
|
||||||
yyinitStateSet (yyGLRStateSet* yyset)
|
yyinitStateSet (yyGLRStateSet* yyset)
|
||||||
{
|
{
|
||||||
@@ -1099,8 +1114,8 @@ static void yyfreeStateSet (yyGLRStateSet* yyset)
|
|||||||
YYFREE (yyset->yylookaheadNeeds);
|
YYFREE (yyset->yylookaheadNeeds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initialize STACK to a single empty stack, with total maximum
|
/** Initialize *YYSTACKP to a single empty stack, with total maximum
|
||||||
* capacity for all stacks of SIZE. */
|
* capacity for all stacks of YYSIZE. */
|
||||||
static yybool
|
static yybool
|
||||||
yyinitGLRStack (yyGLRStack* yystackp, size_t yysize)
|
yyinitGLRStack (yyGLRStack* yystackp, size_t yysize)
|
||||||
{
|
{
|
||||||
@@ -1122,7 +1137,7 @@ yyinitGLRStack (yyGLRStack* yystackp, size_t yysize)
|
|||||||
# define YYRELOC(YYFROMITEMS,YYTOITEMS,YYX,YYTYPE) \
|
# define YYRELOC(YYFROMITEMS,YYTOITEMS,YYX,YYTYPE) \
|
||||||
&((YYTOITEMS) - ((YYFROMITEMS) - (yyGLRStackItem*) (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.
|
stack from outside should be considered invalid after this call.
|
||||||
We always expand when there are 1 or fewer items left AFTER an
|
We always expand when there are 1 or fewer items left AFTER an
|
||||||
allocation, so that we can avoid having external pointers exist
|
allocation, so that we can avoid having external pointers exist
|
||||||
@@ -1192,9 +1207,9 @@ yyfreeGLRStack (yyGLRStack* yystackp)
|
|||||||
yyfreeStateSet (&yystackp->yytops);
|
yyfreeStateSet (&yystackp->yytops);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Assuming that S is a GLRState somewhere on STACK, update the
|
/** Assuming that YYS is a GLRState somewhere on *YYSTACKP, update the
|
||||||
* splitpoint of STACK, if needed, so that it is at least as deep as
|
* splitpoint of *YYSTACKP, if needed, so that it is at least as deep as
|
||||||
* S. */
|
* YYS. */
|
||||||
static inline void
|
static inline void
|
||||||
yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
|
yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
|
||||||
{
|
{
|
||||||
@@ -1202,7 +1217,7 @@ yyupdateSplit (yyGLRStack* yystackp, yyGLRState* yys)
|
|||||||
yystackp->yysplitPoint = yys;
|
yystackp->yysplitPoint = yys;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Invalidate stack #K in STACK. */
|
/** Invalidate stack #YYK in *YYSTACKP. */
|
||||||
static inline void
|
static inline void
|
||||||
yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk)
|
yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk)
|
||||||
{
|
{
|
||||||
@@ -1211,8 +1226,8 @@ yymarkStackDeleted (yyGLRStack* yystackp, size_t yyk)
|
|||||||
yystackp->yytops.yystates[yyk] = NULL;
|
yystackp->yytops.yystates[yyk] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Undelete the last stack that was marked as deleted. Can only be
|
/** Undelete the last stack in *YYSTACKP that was marked as deleted. Can
|
||||||
done once after a deletion, and only when all other stacks have
|
only be done once after a deletion, and only when all other stacks have
|
||||||
been deleted. */
|
been deleted. */
|
||||||
static void
|
static void
|
||||||
yyundeleteLastStack (yyGLRStack* yystackp)
|
yyundeleteLastStack (yyGLRStack* yystackp)
|
||||||
@@ -1261,8 +1276,9 @@ yyremoveDeletes (yyGLRStack* yystackp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Shift to a new state on stack #K of STACK, corresponding to LR state
|
/** Shift to a new state on stack #YYK of *YYSTACKP, corresponding to LR
|
||||||
* LRSTATE, at input position POSN, with (resolved) semantic value SVAL. */
|
* state YYLRSTATE, at input position YYPOSN, with (resolved) semantic
|
||||||
|
* value *YYVALP and source location *YYLOCP. */
|
||||||
static inline void
|
static inline void
|
||||||
yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
|
yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
|
||||||
size_t yyposn,
|
size_t yyposn,
|
||||||
@@ -1281,7 +1297,7 @@ yyglrShift (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
|
|||||||
YY_RESERVE_GLRSTACK (yystackp);
|
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)
|
* state YYLRSTATE, at input position YYPOSN, with the (unresolved)
|
||||||
* semantic value of YYRHS under the action for YYRULE. */
|
* semantic value of YYRHS under the action for YYRULE. */
|
||||||
static inline void
|
static inline void
|
||||||
@@ -1301,11 +1317,51 @@ yyglrShiftDefer (yyGLRStack* yystackp, size_t yyk, yyStateNum yylrState,
|
|||||||
yyaddDeferredAction (yystackp, yyk, yynewState, yyrhs, yyrule);
|
yyaddDeferredAction (yystackp, yyk, yynewState, yyrhs, yyrule);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Pop the symbols consumed by reduction #RULE from the top of stack
|
#if !YYDEBUG
|
||||||
* #K of STACK, and perform the appropriate semantic action on their
|
# 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
|
* semantic values. Assumes that all ambiguities in semantic values
|
||||||
* have been previously resolved. Set *VALP to the resulting value,
|
* have been previously resolved. Set *YYVALP to the resulting value,
|
||||||
* and *LOCP to the computed location (if any). Return value is as
|
* and *YYLOCP to the computed location (if any). Return value is as
|
||||||
* for userAction. */
|
* for userAction. */
|
||||||
static inline YYRESULTTAG
|
static inline YYRESULTTAG
|
||||||
yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
|
yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
|
||||||
@@ -1321,15 +1377,12 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
|
|||||||
yystackp->yynextFree -= yynrhs;
|
yystackp->yynextFree -= yynrhs;
|
||||||
yystackp->yyspaceLeft += yynrhs;
|
yystackp->yyspaceLeft += yynrhs;
|
||||||
yystackp->yytops.yystates[0] = & yystackp->yynextFree[-1].yystate;
|
yystackp->yytops.yystates[0] = & yystackp->yynextFree[-1].yystate;
|
||||||
|
YY_REDUCE_PRINT ((1, yyrhs, yyk, yyrule]b4_user_args[));
|
||||||
return yyuserAction (yyrule, yynrhs, yyrhs,
|
return yyuserAction (yyrule, yynrhs, yyrhs,
|
||||||
yyvalp, yylocp, yystackp]b4_user_args[);
|
yyvalp, yylocp, yystackp]b4_user_args[);
|
||||||
}
|
}
|
||||||
else
|
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;
|
int yyi;
|
||||||
yyGLRState* yys;
|
yyGLRState* yys;
|
||||||
yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
|
yyGLRStackItem yyrhsVals[YYMAXRHS + YYMAXLEFT + 1];
|
||||||
@@ -1345,60 +1398,21 @@ yydoAction (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
|
|||||||
}
|
}
|
||||||
yyupdateSplit (yystackp, yys);
|
yyupdateSplit (yystackp, yys);
|
||||||
yystackp->yytops.yystates[yyk] = 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,
|
return yyuserAction (yyrule, yynrhs, yyrhsVals + YYMAXRHS + YYMAXLEFT - 1,
|
||||||
yyvalp, yylocp, yystackp]b4_user_args[);
|
yyvalp, yylocp, yystackp]b4_user_args[);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !YYDEBUG
|
/** Pop items off stack #YYK of *YYSTACKP according to grammar rule YYRULE,
|
||||||
# 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,
|
|
||||||
* and push back on the resulting nonterminal symbol. Perform the
|
* and push back on the resulting nonterminal symbol. Perform the
|
||||||
* semantic action associated with RULE and store its value with the
|
* semantic action associated with YYRULE and store its value with the
|
||||||
* newly pushed state, if FORCEEVAL or if STACK is currently
|
* newly pushed state, if YYFORCEEVAL or if *YYSTACKP is currently
|
||||||
* unambiguous. Otherwise, store the deferred semantic action with
|
* unambiguous. Otherwise, store the deferred semantic action with
|
||||||
* the new state. If the new state would have an identical input
|
* the new state. If the new state would have an identical input
|
||||||
* position, LR state, and predecessor to an existing state on the stack,
|
* position, LR state, and predecessor to an existing state on the stack,
|
||||||
* it is identified with that existing state, eliminating stack #K from
|
* it is identified with that existing state, eliminating stack #YYK from
|
||||||
* the STACK. In this case, the (necessarily deferred) semantic value is
|
* *YYSTACKP. In this case, the semantic value is
|
||||||
* added to the options for the existing state's semantic value.
|
* added to the options for the existing state's semantic value.
|
||||||
*/
|
*/
|
||||||
static inline YYRESULTTAG
|
static inline YYRESULTTAG
|
||||||
@@ -1409,12 +1423,19 @@ yyglrReduce (yyGLRStack* yystackp, size_t yyk, yyRuleNum yyrule,
|
|||||||
|
|
||||||
if (yyforceEval || yystackp->yysplitPoint == NULL)
|
if (yyforceEval || yystackp->yysplitPoint == NULL)
|
||||||
{
|
{
|
||||||
|
YYRESULTTAG yyflag;
|
||||||
YYSTYPE yysval;
|
YYSTYPE yysval;
|
||||||
YYLTYPE yyloc;
|
YYLTYPE yyloc;
|
||||||
|
|
||||||
YY_REDUCE_PRINT ((yystackp, yyk, yyrule]b4_user_args[));
|
yyflag = yydoAction (yystackp, yyk, yyrule, &yysval,
|
||||||
YYCHK (yydoAction (yystackp, yyk, yyrule, &yysval,
|
&yyloc]b4_user_args[);
|
||||||
&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);
|
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyrule], &yysval, &yyloc);
|
||||||
yyglrShift (yystackp, yyk,
|
yyglrShift (yystackp, yyk,
|
||||||
yyLRgotoState (yystackp->yytops.yystates[yyk]->yylrState,
|
yyLRgotoState (yystackp->yytops.yystates[yyk]->yylrState,
|
||||||
@@ -1508,7 +1529,7 @@ yysplitStack (yyGLRStack* yystackp, size_t yyk)
|
|||||||
return yystackp->yytops.yysize-1;
|
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 is, they represent the same rule applied to RHS symbols
|
||||||
* that produce the same terminal symbols. */
|
* that produce the same terminal symbols. */
|
||||||
static yybool
|
static yybool
|
||||||
@@ -1530,8 +1551,8 @@ yyidenticalOptions (yySemanticOption* yyy0, yySemanticOption* yyy1)
|
|||||||
return yyfalse;
|
return yyfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Assuming identicalOptions (Y0,Y1), destructively merge the
|
/** Assuming identicalOptions (YYY0,YYY1), destructively merge the
|
||||||
* alternative semantic values for the RHS-symbols of Y1 and Y0. */
|
* alternative semantic values for the RHS-symbols of YYY1 and YYY0. */
|
||||||
static void
|
static void
|
||||||
yymergeOptionSets (yySemanticOption* yyy0, yySemanticOption* yyy1)
|
yymergeOptionSets (yySemanticOption* yyy0, yySemanticOption* yyy1)
|
||||||
{
|
{
|
||||||
@@ -1612,11 +1633,11 @@ static YYRESULTTAG yyresolveValue (yyGLRState* yys,
|
|||||||
yyGLRStack* yystackp]b4_user_formals[);
|
yyGLRStack* yystackp]b4_user_formals[);
|
||||||
|
|
||||||
|
|
||||||
/** Resolve the previous N states starting at and including state S. If result
|
/** Resolve the previous YYN states starting at and including state YYS
|
||||||
* != yyok, some states may have been left unresolved possibly with empty
|
* on *YYSTACKP. If result != yyok, some states may have been left
|
||||||
* semantic option chains. Regardless of whether result = yyok, each state
|
* unresolved possibly with empty semantic option chains. Regardless
|
||||||
* has been left with consistent data so that yydestroyGLRState can be invoked
|
* of whether result = yyok, each state has been left with consistent
|
||||||
* if necessary. */
|
* data so that yydestroyGLRState can be invoked if necessary. */
|
||||||
static YYRESULTTAG
|
static YYRESULTTAG
|
||||||
yyresolveStates (yyGLRState* yys, int yyn,
|
yyresolveStates (yyGLRState* yys, int yyn,
|
||||||
yyGLRStack* yystackp]b4_user_formals[)
|
yyGLRStack* yystackp]b4_user_formals[)
|
||||||
@@ -1631,9 +1652,10 @@ yyresolveStates (yyGLRState* yys, int yyn,
|
|||||||
return yyok;
|
return yyok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Resolve the states for the RHS of OPT, perform its user action, and return
|
/** Resolve the states for the RHS of YYOPT on *YYSTACKP, perform its
|
||||||
* the semantic value and location. Regardless of whether result = yyok, all
|
* user action, and return the semantic value and location in *YYVALP
|
||||||
* RHS states have been destroyed (assuming the user action destroys all RHS
|
* and *YYLOCP. Regardless of whether result = yyok, all RHS states
|
||||||
|
* have been destroyed (assuming the user action destroys all RHS
|
||||||
* semantic values if invoked). */
|
* semantic values if invoked). */
|
||||||
static YYRESULTTAG
|
static YYRESULTTAG
|
||||||
yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystackp,
|
yyresolveAction (yySemanticOption* yyopt, yyGLRStack* yystackp,
|
||||||
@@ -1743,9 +1765,9 @@ yyreportAmbiguity (yySemanticOption* yyx0,
|
|||||||
return yyabort;
|
return yyabort;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Starting at and including state S1, resolve the location for each of the
|
/** Resolve the locations for each of the YYN1 states in *YYSTACKP,
|
||||||
* previous N1 states that is unresolved. The first semantic option of a state
|
* ending at YYS1. Has no effect on previously resolved states.
|
||||||
* is always chosen. */
|
* The first semantic option of a state is always chosen. */
|
||||||
static void
|
static void
|
||||||
yyresolveLocations (yyGLRState* yys1, int yyn1,
|
yyresolveLocations (yyGLRState* yys1, int yyn1,
|
||||||
yyGLRStack *yystackp]b4_user_formals[)
|
yyGLRStack *yystackp]b4_user_formals[)
|
||||||
@@ -1801,11 +1823,12 @@ yyresolveLocations (yyGLRState* yys1, int yyn1,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Resolve the ambiguity represented in state S, perform the indicated
|
/** Resolve the ambiguity represented in state YYS in *YYSTACKP,
|
||||||
* actions, and set the semantic value of S. If result != yyok, the chain of
|
* perform the indicated actions, and set the semantic value of YYS.
|
||||||
* semantic options in S has been cleared instead or it has been left
|
* If result != yyok, the chain of semantic options in YYS has been
|
||||||
* unmodified except that redundant options may have been removed. Regardless
|
* cleared instead or it has been left unmodified except that
|
||||||
* of whether result = yyok, S has been left with consistent data so 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. */
|
* yydestroyGLRState can be invoked if necessary. */
|
||||||
static YYRESULTTAG
|
static YYRESULTTAG
|
||||||
yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp]b4_user_formals[)
|
yyresolveValue (yyGLRState* yys, yyGLRStack* yystackp]b4_user_formals[)
|
||||||
@@ -1950,6 +1973,7 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
|
|||||||
int yyaction;
|
int yyaction;
|
||||||
const short int* yyconflicts;
|
const short int* yyconflicts;
|
||||||
yyRuleNum yyrule;
|
yyRuleNum yyrule;
|
||||||
|
YYRESULTTAG yyflag;
|
||||||
|
|
||||||
while (yystackp->yytops.yystates[yyk] != NULL)
|
while (yystackp->yytops.yystates[yyk] != NULL)
|
||||||
{
|
{
|
||||||
@@ -1969,11 +1993,21 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
|
|||||||
yymarkStackDeleted (yystackp, yyk);
|
yymarkStackDeleted (yystackp, yyk);
|
||||||
return yyok;
|
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
|
else
|
||||||
{
|
{
|
||||||
yySymbol yytoken;
|
yySymbol yytoken;
|
||||||
|
|
||||||
yystackp->yytops.yylookaheadNeeds[yyk] = yytrue;
|
yystackp->yytops.yylookaheadNeeds[yyk] = yytrue;
|
||||||
if (yychar == YYEMPTY)
|
if (yychar == YYEMPTY)
|
||||||
{
|
{
|
||||||
@@ -1996,14 +2030,25 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
|
|||||||
|
|
||||||
while (*yyconflicts != 0)
|
while (*yyconflicts != 0)
|
||||||
{
|
{
|
||||||
|
YYRESULTTAG yyflag;
|
||||||
size_t yynewStack = yysplitStack (yystackp, yyk);
|
size_t yynewStack = yysplitStack (yystackp, yyk);
|
||||||
YYDPRINTF ((stderr, "Splitting off stack %lu from %lu.\n",
|
YYDPRINTF ((stderr, "Splitting off stack %lu from %lu.\n",
|
||||||
(unsigned long int) yynewStack,
|
(unsigned long int) yynewStack,
|
||||||
(unsigned long int) yyk));
|
(unsigned long int) yyk));
|
||||||
YYCHK (yyglrReduce (yystackp, yynewStack,
|
yyflag = yyglrReduce (yystackp, yynewStack,
|
||||||
*yyconflicts, yyfalse]b4_user_args[));
|
*yyconflicts,
|
||||||
YYCHK (yyprocessOneStack (yystackp, yynewStack,
|
yyimmediate[*yyconflicts]]b4_user_args[);
|
||||||
yyposn]b4_pure_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;
|
yyconflicts += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2017,8 +2062,19 @@ yyprocessOneStack (yyGLRStack* yystackp, size_t yyk,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
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;
|
return yyok;
|
||||||
@@ -2249,7 +2305,6 @@ yyrecoverSyntaxError (yyGLRStack* yystackp]b4_user_formals[)
|
|||||||
} \
|
} \
|
||||||
} while (YYID (0))
|
} while (YYID (0))
|
||||||
|
|
||||||
|
|
||||||
/*----------.
|
/*----------.
|
||||||
| yyparse. |
|
| yyparse. |
|
||||||
`----------*/
|
`----------*/
|
||||||
|
|||||||
@@ -169,6 +169,13 @@ m4_define([b4_case], [ case $1:
|
|||||||
break;
|
break;
|
||||||
])
|
])
|
||||||
|
|
||||||
|
# b4_predicate_case(LABEL, CONDITIONS)
|
||||||
|
# ------------------------------------
|
||||||
|
m4_define([b4_predicate_case], [ case $1:
|
||||||
|
if (! ($2)) YYERROR;
|
||||||
|
break;
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
## ---------------- ##
|
## ---------------- ##
|
||||||
## Default values. ##
|
## Default values. ##
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ Writing @acronym{GLR} Parsers
|
|||||||
* Simple GLR Parsers:: Using @acronym{GLR} parsers on unambiguous grammars.
|
* Simple GLR Parsers:: Using @acronym{GLR} parsers on unambiguous grammars.
|
||||||
* Merging GLR Parses:: Using @acronym{GLR} parsers to resolve ambiguities.
|
* Merging GLR Parses:: Using @acronym{GLR} parsers to resolve ambiguities.
|
||||||
* GLR Semantic Actions:: Deferred semantic actions have special concerns.
|
* 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.
|
* Compiler Requirements:: @acronym{GLR} parsers require a modern C compiler.
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
@@ -758,6 +759,7 @@ merged result.
|
|||||||
* Simple GLR Parsers:: Using @acronym{GLR} parsers on unambiguous grammars.
|
* Simple GLR Parsers:: Using @acronym{GLR} parsers on unambiguous grammars.
|
||||||
* Merging GLR Parses:: Using @acronym{GLR} parsers to resolve ambiguities.
|
* Merging GLR Parses:: Using @acronym{GLR} parsers to resolve ambiguities.
|
||||||
* GLR Semantic Actions:: Deferred semantic actions have special concerns.
|
* 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.
|
* Compiler Requirements:: @acronym{GLR} parsers require a modern C compiler.
|
||||||
@end menu
|
@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
|
Also, see @ref{Location Default Action, ,Default Action for Locations}, which
|
||||||
describes a special usage of @code{YYLLOC_DEFAULT} in @acronym{GLR} parsers.
|
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
|
@node Compiler Requirements
|
||||||
@subsection Considerations when Compiling @acronym{GLR} Parsers
|
@subsection Considerations when Compiling @acronym{GLR} Parsers
|
||||||
@cindex @code{inline}
|
@cindex @code{inline}
|
||||||
@@ -10610,6 +10671,19 @@ file. @xref{Grammar Outline, ,Outline of a Bison
|
|||||||
Grammar}.
|
Grammar}.
|
||||||
@end deffn
|
@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{}*/
|
@deffn {Construct} /*@dots{}*/
|
||||||
Comment delimiters, as in C.
|
Comment delimiters, as in C.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|||||||
@@ -194,6 +194,7 @@ typedef struct
|
|||||||
|
|
||||||
location location;
|
location location;
|
||||||
bool useful;
|
bool useful;
|
||||||
|
bool is_predicate;
|
||||||
|
|
||||||
const char *action;
|
const char *action;
|
||||||
location action_location;
|
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, |
|
| Prepare the muscles related to the rules: r1, r2, rline, dprec, |
|
||||||
| merger. |
|
| merger, immediate. |
|
||||||
`----------------------------------------------------------------*/
|
`----------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -215,6 +215,7 @@ prepare_rules (void)
|
|||||||
unsigned int *r2 = xnmalloc (nrules, sizeof *r2);
|
unsigned int *r2 = xnmalloc (nrules, sizeof *r2);
|
||||||
int *dprec = xnmalloc (nrules, sizeof *dprec);
|
int *dprec = xnmalloc (nrules, sizeof *dprec);
|
||||||
int *merger = xnmalloc (nrules, sizeof *merger);
|
int *merger = xnmalloc (nrules, sizeof *merger);
|
||||||
|
int *immediate = xnmalloc (nrules, sizeof *immediate);
|
||||||
|
|
||||||
rule_number r;
|
rule_number r;
|
||||||
for (r = 0; r < nrules; ++r)
|
for (r = 0; r < nrules; ++r)
|
||||||
@@ -229,6 +230,8 @@ prepare_rules (void)
|
|||||||
dprec[r] = rules[r].dprec;
|
dprec[r] = rules[r].dprec;
|
||||||
/* Merger-function index (GLR). */
|
/* Merger-function index (GLR). */
|
||||||
merger[r] = rules[r].merger;
|
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);
|
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_unsigned_int_table ("r2", r2, 0, 0, nrules);
|
||||||
muscle_insert_int_table ("dprec", dprec, 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 ("merger", merger, 0, 0, nrules);
|
||||||
|
muscle_insert_int_table ("immediate", immediate, 0, 0, nrules);
|
||||||
|
|
||||||
MUSCLE_INSERT_INT ("rules_number", nrules);
|
MUSCLE_INSERT_INT ("rules_number", nrules);
|
||||||
MUSCLE_INSERT_INT ("max_left_semantic_context", max_left_semantic_context);
|
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)
|
for (r = 0; r < nrules; ++r)
|
||||||
if (rules[r].action)
|
if (rules[r].action)
|
||||||
{
|
{
|
||||||
fprintf (out, "b4_case(%d, [b4_syncline(%d, ", r + 1,
|
fprintf (out, "b4_%scase(%d, [b4_syncline(%d, ",
|
||||||
rules[r].action_location.start.line);
|
rules[r].is_predicate ? "predicate_" : "",
|
||||||
|
r + 1, rules[r].action_location.start.line);
|
||||||
escaped_output (out, rules[r].action_location.start.file);
|
escaped_output (out, rules[r].action_location.start.file);
|
||||||
fprintf (out, ")\n[ %s]])\n\n", rules[r].action);
|
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
|
/* 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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -31,7 +32,7 @@
|
|||||||
version 2.2 of Bison. */
|
version 2.2 of Bison. */
|
||||||
/* "%code requires" blocks. */
|
/* "%code requires" blocks. */
|
||||||
/* Line 1658 of yacc.c */
|
/* Line 1658 of yacc.c */
|
||||||
#line 201 "src/parse-gram.y"
|
#line 202 "src/parse-gram.y"
|
||||||
|
|
||||||
# ifndef PARAM_TYPE
|
# ifndef PARAM_TYPE
|
||||||
# define PARAM_TYPE
|
# define PARAM_TYPE
|
||||||
@@ -46,7 +47,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Line 1658 of yacc.c */
|
/* Line 1658 of yacc.c */
|
||||||
#line 50 "src/parse-gram.h"
|
#line 51 "src/parse-gram.h"
|
||||||
|
|
||||||
/* Tokens. */
|
/* Tokens. */
|
||||||
#ifndef YYTOKENTYPE
|
#ifndef YYTOKENTYPE
|
||||||
@@ -93,21 +94,22 @@
|
|||||||
PERCENT_VERBOSE = 293,
|
PERCENT_VERBOSE = 293,
|
||||||
PERCENT_YACC = 294,
|
PERCENT_YACC = 294,
|
||||||
BRACED_CODE = 295,
|
BRACED_CODE = 295,
|
||||||
BRACKETED_ID = 296,
|
BRACED_PREDICATE = 296,
|
||||||
CHAR = 297,
|
BRACKETED_ID = 297,
|
||||||
EPILOGUE = 298,
|
CHAR = 298,
|
||||||
EQUAL = 299,
|
EPILOGUE = 299,
|
||||||
ID = 300,
|
EQUAL = 300,
|
||||||
ID_COLON = 301,
|
ID = 301,
|
||||||
PERCENT_PERCENT = 302,
|
ID_COLON = 302,
|
||||||
PIPE = 303,
|
PERCENT_PERCENT = 303,
|
||||||
PROLOGUE = 304,
|
PIPE = 304,
|
||||||
SEMICOLON = 305,
|
PROLOGUE = 305,
|
||||||
TAG = 306,
|
SEMICOLON = 306,
|
||||||
TAG_ANY = 307,
|
TAG = 307,
|
||||||
TAG_NONE = 308,
|
TAG_ANY = 308,
|
||||||
PERCENT_PARAM = 309,
|
TAG_NONE = 309,
|
||||||
PERCENT_UNION = 310
|
PERCENT_PARAM = 310,
|
||||||
|
PERCENT_UNION = 311
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
/* Tokens. */
|
/* Tokens. */
|
||||||
@@ -150,21 +152,22 @@
|
|||||||
#define PERCENT_VERBOSE 293
|
#define PERCENT_VERBOSE 293
|
||||||
#define PERCENT_YACC 294
|
#define PERCENT_YACC 294
|
||||||
#define BRACED_CODE 295
|
#define BRACED_CODE 295
|
||||||
#define BRACKETED_ID 296
|
#define BRACED_PREDICATE 296
|
||||||
#define CHAR 297
|
#define BRACKETED_ID 297
|
||||||
#define EPILOGUE 298
|
#define CHAR 298
|
||||||
#define EQUAL 299
|
#define EPILOGUE 299
|
||||||
#define ID 300
|
#define EQUAL 300
|
||||||
#define ID_COLON 301
|
#define ID 301
|
||||||
#define PERCENT_PERCENT 302
|
#define ID_COLON 302
|
||||||
#define PIPE 303
|
#define PERCENT_PERCENT 303
|
||||||
#define PROLOGUE 304
|
#define PIPE 304
|
||||||
#define SEMICOLON 305
|
#define PROLOGUE 305
|
||||||
#define TAG 306
|
#define SEMICOLON 306
|
||||||
#define TAG_ANY 307
|
#define TAG 307
|
||||||
#define TAG_NONE 308
|
#define TAG_ANY 308
|
||||||
#define PERCENT_PARAM 309
|
#define TAG_NONE 309
|
||||||
#define PERCENT_UNION 310
|
#define PERCENT_PARAM 310
|
||||||
|
#define PERCENT_UNION 311
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -173,7 +176,7 @@
|
|||||||
typedef union YYSTYPE
|
typedef union YYSTYPE
|
||||||
{
|
{
|
||||||
/* Line 1658 of yacc.c */
|
/* Line 1658 of yacc.c */
|
||||||
#line 87 "src/parse-gram.y"
|
#line 88 "src/parse-gram.y"
|
||||||
|
|
||||||
assoc assoc;
|
assoc assoc;
|
||||||
char *code;
|
char *code;
|
||||||
@@ -186,13 +189,13 @@ typedef union YYSTYPE
|
|||||||
unsigned char character;
|
unsigned char character;
|
||||||
|
|
||||||
/* Line 1658 of yacc.c */
|
/* Line 1658 of yacc.c */
|
||||||
#line 225 "src/parse-gram.y"
|
#line 226 "src/parse-gram.y"
|
||||||
|
|
||||||
param_type param;
|
param_type param;
|
||||||
|
|
||||||
|
|
||||||
/* Line 1658 of yacc.c */
|
/* Line 1658 of yacc.c */
|
||||||
#line 196 "src/parse-gram.h"
|
#line 199 "src/parse-gram.h"
|
||||||
} YYSTYPE;
|
} YYSTYPE;
|
||||||
# define YYSTYPE_IS_TRIVIAL 1
|
# define YYSTYPE_IS_TRIVIAL 1
|
||||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||||
|
|||||||
@@ -118,7 +118,6 @@ static char const *char_name (char);
|
|||||||
%token PERCENT_DPREC "%dprec"
|
%token PERCENT_DPREC "%dprec"
|
||||||
%token PERCENT_MERGE "%merge"
|
%token PERCENT_MERGE "%merge"
|
||||||
|
|
||||||
|
|
||||||
/*----------------------.
|
/*----------------------.
|
||||||
| Global Declarations. |
|
| Global Declarations. |
|
||||||
`----------------------*/
|
`----------------------*/
|
||||||
@@ -151,6 +150,7 @@ static char const *char_name (char);
|
|||||||
;
|
;
|
||||||
|
|
||||||
%token BRACED_CODE "{...}"
|
%token BRACED_CODE "{...}"
|
||||||
|
%token BRACED_PREDICATE "%?{...}"
|
||||||
%token BRACKETED_ID "[identifier]"
|
%token BRACKETED_ID "[identifier]"
|
||||||
%token CHAR "char"
|
%token CHAR "char"
|
||||||
%token EPILOGUE "epilogue"
|
%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
|
/* braceless is not to be used for rule or symbol actions, as it
|
||||||
calls code_props_plain_init. */
|
calls code_props_plain_init. */
|
||||||
%type <chars> STRING "%{...%}" EPILOGUE braceless content.opt
|
%type <chars> STRING "%{...%}" EPILOGUE braceless content.opt
|
||||||
%type <code> "{...}"
|
%type <code> "{...}" "%?{...}"
|
||||||
%printer { fputs (quotearg_style (c_quoting_style, $$), stderr); }
|
%printer { fputs (quotearg_style (c_quoting_style, $$), stderr); }
|
||||||
STRING
|
STRING
|
||||||
%printer { fprintf (stderr, "{\n%s\n}", $$); }
|
%printer { fprintf (stderr, "{\n%s\n}", $$); }
|
||||||
@@ -586,7 +586,9 @@ rhs:
|
|||||||
| rhs symbol named_ref.opt
|
| rhs symbol named_ref.opt
|
||||||
{ grammar_current_rule_symbol_append ($2, @2, $3); }
|
{ grammar_current_rule_symbol_append ($2, @2, $3); }
|
||||||
| rhs "{...}" named_ref.opt
|
| 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
|
| rhs "%prec" symbol
|
||||||
{ grammar_current_rule_prec_set ($3, @3); }
|
{ grammar_current_rule_prec_set ($3, @3); }
|
||||||
| rhs "%dprec" INT
|
| rhs "%dprec" INT
|
||||||
@@ -601,7 +603,6 @@ named_ref.opt:
|
|||||||
BRACKETED_ID { $$ = named_ref_new($1, @1); }
|
BRACKETED_ID { $$ = named_ref_new($1, @1); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------.
|
/*---------------------------.
|
||||||
| variable and content.opt. |
|
| variable and content.opt. |
|
||||||
`---------------------------*/
|
`---------------------------*/
|
||||||
|
|||||||
@@ -377,7 +377,8 @@ grammar_midrule_action (void)
|
|||||||
code_props_rule_action_init (&midrule->action_props,
|
code_props_rule_action_init (&midrule->action_props,
|
||||||
current_rule->action_props.code,
|
current_rule->action_props.code,
|
||||||
current_rule->action_props.location,
|
current_rule->action_props.location,
|
||||||
midrule, 0);
|
midrule, 0,
|
||||||
|
current_rule->action_props.is_predicate);
|
||||||
code_props_none_init (¤t_rule->action_props);
|
code_props_none_init (¤t_rule->action_props);
|
||||||
|
|
||||||
if (previous_rule_end)
|
if (previous_rule_end)
|
||||||
@@ -468,14 +469,14 @@ grammar_current_rule_symbol_append (symbol *sym, location loc,
|
|||||||
|
|
||||||
void
|
void
|
||||||
grammar_current_rule_action_append (const char *action, location loc,
|
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)
|
if (current_rule->action_props.code)
|
||||||
grammar_midrule_action ();
|
grammar_midrule_action ();
|
||||||
/* After all symbol declarations have been parsed, packgram invokes
|
/* After all symbol declarations have been parsed, packgram invokes
|
||||||
code_props_translate_code. */
|
code_props_translate_code. */
|
||||||
code_props_rule_action_init (¤t_rule->action_props, action, loc,
|
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].useful = true;
|
||||||
rules[ruleno].action = p->action_props.code;
|
rules[ruleno].action = p->action_props.code;
|
||||||
rules[ruleno].action_location = p->action_props.location;
|
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
|
/* 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
|
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,
|
void grammar_current_rule_symbol_append (symbol *sym, location loc,
|
||||||
named_ref *named_ref);
|
named_ref *named_ref);
|
||||||
void grammar_current_rule_action_append (const char *action, location loc,
|
void grammar_current_rule_action_append (const char *action, location loc,
|
||||||
named_ref *named_ref);
|
named_ref *named_ref, bool);
|
||||||
void reader (void);
|
void reader (void);
|
||||||
void free_merger_functions (void);
|
void free_merger_functions (void);
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,13 @@ typedef struct code_props {
|
|||||||
*/
|
*/
|
||||||
bool is_value_used;
|
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. */
|
/** \c NULL iff \c code_props::kind is not \c CODE_PROPS_RULE_ACTION. */
|
||||||
struct symbol_list *rule;
|
struct symbol_list *rule;
|
||||||
|
|
||||||
@@ -80,7 +87,7 @@ void code_props_none_init (code_props *self);
|
|||||||
|
|
||||||
/** Equivalent to \c code_props_none_init. */
|
/** Equivalent to \c code_props_none_init. */
|
||||||
#define 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. */
|
/** Initialized by \c CODE_PROPS_NONE_INIT with no further modification. */
|
||||||
extern code_props const code_props_none;
|
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,
|
void code_props_rule_action_init (code_props *self, char const *code,
|
||||||
location code_loc, struct symbol_list *rule,
|
location code_loc, struct symbol_list *rule,
|
||||||
named_ref *name);
|
named_ref *name, bool is_predicate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \pre
|
* \pre
|
||||||
|
|||||||
@@ -902,7 +902,7 @@ code_props_symbol_action_init (code_props *self, char const *code,
|
|||||||
void
|
void
|
||||||
code_props_rule_action_init (code_props *self, char const *code,
|
code_props_rule_action_init (code_props *self, char const *code,
|
||||||
location code_loc, symbol_list *rule,
|
location code_loc, symbol_list *rule,
|
||||||
named_ref *name)
|
named_ref *name, bool is_predicate)
|
||||||
{
|
{
|
||||||
self->kind = CODE_PROPS_RULE_ACTION;
|
self->kind = CODE_PROPS_RULE_ACTION;
|
||||||
self->code = code;
|
self->code = code;
|
||||||
@@ -910,6 +910,7 @@ code_props_rule_action_init (code_props *self, char const *code,
|
|||||||
self->is_value_used = false;
|
self->is_value_used = false;
|
||||||
self->rule = rule;
|
self->rule = rule;
|
||||||
self->named_ref = name;
|
self->named_ref = name;
|
||||||
|
self->is_predicate = is_predicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -106,11 +106,12 @@ static void unexpected_newline (boundary, char const *);
|
|||||||
/* A complex tag, with nested angles brackets. */
|
/* A complex tag, with nested angles brackets. */
|
||||||
%x SC_TAG
|
%x SC_TAG
|
||||||
|
|
||||||
/* Three types of user code:
|
/* Four types of user code:
|
||||||
- prologue (code between `%{' `%}' in the first section, before %%);
|
- prologue (code between `%{' `%}' in the first section, before %%);
|
||||||
- actions, printers, union, etc, (between braced in the middle section);
|
- actions, printers, union, etc, (between braced in the middle section);
|
||||||
- epilogue (everything after the second %%). */
|
- epilogue (everything after the second %%).
|
||||||
%x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE
|
- predicate (code between `%?{' and `{' in middle section); */
|
||||||
|
%x SC_PROLOGUE SC_BRACED_CODE SC_EPILOGUE SC_PREDICATE
|
||||||
/* C and C++ comments in code. */
|
/* C and C++ comments in code. */
|
||||||
%x SC_COMMENT SC_LINE_COMMENT
|
%x SC_COMMENT SC_LINE_COMMENT
|
||||||
/* Strings and characters in code. */
|
/* Strings and characters in code. */
|
||||||
@@ -285,6 +286,13 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
BEGIN SC_BRACED_CODE;
|
BEGIN SC_BRACED_CODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Semantic predicate. */
|
||||||
|
"%?"[ \f\n\t\v]*"{" {
|
||||||
|
nesting = 0;
|
||||||
|
code_start = loc->start;
|
||||||
|
BEGIN SC_PREDICATE;
|
||||||
|
}
|
||||||
|
|
||||||
/* A type. */
|
/* A type. */
|
||||||
"<*>" return TAG_ANY;
|
"<*>" return TAG_ANY;
|
||||||
"<>" return TAG_NONE;
|
"<>" return TAG_NONE;
|
||||||
@@ -661,7 +669,7 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
| Strings, comments etc. can be found in user code. |
|
| 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;
|
STRING_GROW;
|
||||||
@@ -691,14 +699,32 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------.
|
/*-----------------------------------------------------------.
|
||||||
| Scanning some code in braces (actions). The initial "{" is |
|
| Scanning some code in braces (actions, predicates). The |
|
||||||
| already eaten. |
|
| initial "{" is already eaten. |
|
||||||
`-----------------------------------------------------------*/
|
`-----------------------------------------------------------*/
|
||||||
|
|
||||||
<SC_BRACED_CODE>
|
<SC_BRACED_CODE,SC_PREDICATE>
|
||||||
{
|
{
|
||||||
"{"|"<"{splice}"%" STRING_GROW; nesting++;
|
"{"|"<"{splice}"%" STRING_GROW; nesting++;
|
||||||
"%"{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, '}');
|
obstack_1grow (&obstack_for_string, '}');
|
||||||
|
|
||||||
@@ -712,21 +738,24 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
return BRACED_CODE;
|
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 "%}". |
|
| 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. |
|
| 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_PREDICATE,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>\n STRING_GROW;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user