27 March 2000 Release 2.22 Notes for New Users of PCCTS Version 1.33MR22
40
You should only use #
pragma
approx
when you are certain what is causing the problem, and there is no more
specific way (such as predicates) to fix it.
c. Use the ambiguity aid options to locate rules which are contributing to the ambiguity that is driving
ANTLR
out
of resources (
Item c added for 2.22 by THM)
.
d. Selectively disable or remove rules until the problem goes away. The purpose of this is to identify rules that
participate in the ambiguity that is driving
ANTLR
out of resources. If you remove or disable a rule and the
problem goes away, then the rule has
something
to do with the problem, although it requires more thought to
diagnose the exact ambiguity. I sometimes create a special token that is never matched and use it in the grammar
for the purpose of removing a rule from any potentially ambiguous interaction with other rules. For example, to
remove rule "a" from consideration (in a certain sense), change:
a : b c (d)* ;
to:
a : Unmatched b c (d)* ;
where
Unmatched
is a token that is never generated. This will point out if the leading set of "a" is conflicting
with other rules and causing problems.
Here's an example of something that drove me crazy in the C++ grammar. A fully-qualified identifier can have
template arguments: this declares "x" to be a specialization of "A":
A<3> x;
The relevant part of the grammar was "qualified id", which matches a series of A::B::C:: followed by an ID:
scope_override //A::B::C::...
id:ID
(
"<"
template_arguments
">"
|
// empty
)
However, this was getting confused with relational expressions such as:
(A<3) > x;
The first task was identifying this as the problem.
ANTLR
actually blew up in an entirely different place, one that
followed this rule sequentially in some productions. It took some selective disabling and rearrangement of rules to
identify this rule as a culprit.
When this finally was pinpointed as an ambiguity, I couldn't see how this was, because "A" was a type, and types
can't participate in relational expressions. However, after some more searching I dug up this case:
operator A < 3 > x;
The problem is that the type identifier "A" can be used as the "optor" for an operator function specification, so in
that context (which is semantically invalid but permitted by the grammar), a type followed by "<" can be either a
template specifier or a relational expression. There were a whole family of cases, all involving "operator", which
allowed type names to show up where types were not allowed (or so I thought). The final solution was twofold:
First, a semantic predicate had to categorize an identifier as "templated". Second,
#pragma
approx
was used to
avoid the complex processing that was bogging
ANTLR
down:
scope_override //A::B::C::...
id:ID
#pragma approx
(
<<isTemplatedName($id->getText())>>?
"<"
template_arguments
">"
|
// empty
)