27 March 2000 Release 2.22 Notes for New Users of PCCTS Version 1.33MR22
32
;
The problem is that isTypeName() isn't on the leading edge of castExpr because of the LP which precedes it. Thus
it will not be hoisted into the prediction expression for castExpr. The
first
attempt to fix it is:
castExpr : <<isTypeName(LT(2))>>? LP typeName RP
| ....
;
Unfortunately, this won't work because it ignores the problem of STRUCT. The solution is to apply isTypeName()
in castExpr if LA(2) is an ID and don't apply it when LA(2) is STRUCT:
castExpr : (LP ID)? => <<isTypeName(LT(2))>>? LP typeName RP
| ....
;
In conclusion, the "=>" style guarded predicate is useful when:
a. The tokens required for the predicate are not on the leading edge.
b. there are alternatives in the expression selected by the predicate for which the predicate is inappropriate.
If (b) were false, then one could use a simple predicate (assuming "-prc on"):
castExpr : <<isTypeName(LT(2))>>? LP typeName RP
| ....
;
typeName : <<isTypeName(LT(1))>>? ID
;
So, when do you use the "&&" style guarded predicate ? The new-style "&&" predicate should always be used with
predicate context. The context guard is in
addition
to the automatically computed context. Thus it useful for
predicates which depend on the token type for reasons other than context.
The following example is contributed by Reinier van den Born.
This grammar has two ways to call functions:
A "standard" call syntax with parens and comma separated arguments.
A shell command like syntax (no parens and spaces separate arguments).
The former allows a variable to hold the name of the function, the latter can be used to call external commands. The
grammar (simplified) looks like this:
fun_call : ID "(" { expr ("," expr)* } ")"
/* ID is function name */
| "@" ID "(" { expr ("," expr)* } ")"
/* ID is var containing fun name */
;
command : ID expr* /* ID is function name */
| path expr* /* path is external command name */
;
path : ID /* left out slashes and such */
| "@" ID /* ID is environment var */
;
expr : ....
| "(" expr ")";
call : fun_call
| command
;
Obviously the call is wildly ambiguous. This is more or less how this is to be resolved:
A call begins with an ID or an "@" followed by an ID.