The Project

Chapter 7. Predicates

Predicates provide the user with a mechanism for altering the control flow in a manner that terminals alone cannot do.

During the factorisation process, rules that begin with predicates are expanded if necessary to ensure that predicates that may be used to select which alternative to go down always begin the alternative, e.g.:

rule1 = {
	rule2 ;
	/* .... */
||
	/* .... */
} ;

rule2 = {
	? = <predicate> ;
	/* .... */
||
	/* .... */
} ;

would be expanded into:

rule1 = {
	? = predicate ;
	/* .... */
	/* .... */
||
	/* .... */
	/* .... */
||
	/* .... */
} ;

Also, if a predicate is used to select which alternative to use, it must be the first thing in the alternative, so the following would not be allowed:

rule = {
	<action> ;
	? = <predicate> ;
	/* .... */
||
	/* .... */
} ;

When predicates begin a rule, they are executed (in some arbitrary order) until one of them returns true. The alternative that this predicate begins is then selected. If no predicates return true, then one of the remaining alternatives is selected based upon the current terminal (or an error occurs).

It is important that predicates do not contain dependencies upon the order of evaluation. In practice, predicates are likely to be simple, so this shouldn't be a problem.

When predicates are used within an alternative, they behave like terminals. If they evaluate to true, then parsing continues. If they evaluate to false, then an exception is raised.