27 March 2000 Release 2.22 Notes for New Users of PCCTS Version 1.33MR22
28
The code generated (with one ambiguity warning) resembles:
if (LA(1)==ID && isU) {
upper();
} else if (LA(1)==ID && isL) {
lower();
} else if (LA(1)==Number) {
number();
...
Now the need for a non-trivial prediction expression is introduced:
parent : statement
| ID
;
statement
: upper
| number
;
Running
ANTLR
causes one ambiguity warning. The code for "statement" resembles:
if ( (LA(1)==ID || LA(1)==Number) && isU) {
statement();
} else if (LA(1)==ID) {
...
Even if LA(1) is a Number the semantic predicate isU() will be evaluated. Depending on the way that isU is written
it may or may not be meaningful. This is exactly the problem addressed by predicate computation. With "­prc on"
one receives two ambiguity warnings and the code for "statement" resembles:
The important thing to notice is the call to isU() is guarded by a test that insures that the token is indeed an ID.
The following does not change anything because
ANTLR
already knows that the lookahead context for the semantic
predicates can only be "ID":
upper : (ID)? => <<isU(LT(1)->getText())>>? ID ;
#139. Another example of predicate hoisting
Consider the following grammar fragment which uses semantic predicates to disambiguate an ID in rules ca and cb:
a : ( { b | X } Eol)* "@" ; /* a1 */
b : c ID ; /* a2 */
c : {ca} {cb} ; /* a3 */
ca: <<pa(LT(1)->getText())>>? ID; /* a4 */
cb: <<pb(LT(1)->getText())>>? ID; /* a5 */
The code generated for rule c resembles:
if (LA(1)==ID) && pa(...)) { /* b1 */
ca(); /* b2 */
} else { /* b3 */
goto exit; /* b4 */
}; /* b5 */
The test of "pb" does not even appear. The problem is that the element "{cb}" is not at the left edge of rule c ­ even
though "{ca}" is an optional element. Although "ca" may match epsilon, its presence in rule c still blocks the
Code ­prc on
Outline format ­prc on
if ( (LA(1)==ID ||
LA(1)==Number) &&
( !(LA(1)==ID) ||
(LA(1)==ID && isU)) {
statement();
} else if (LA(1)==ID) {
...
&&
||
LA(1)==ID
LA(1)==Number
||
! <===== not ...
LA(1)==ID <===== an ID
isU(LT(1)->getText())