The Rascal grammar contains a production for syntax rules that's not documented:
| except: Sym symbol "!" NonterminalLabel
It acts syntactically like a follow condition and is in a section commented as "conditional". I see that it's used in the Rascal grammar itself. The NonterminalLabel
is for individual production rules (not a production with all its alternates). So what does this condition do?
if ‘E ! add’ occurs in a rule then it simply means E but the rule labeled "add" for E will be as-if not existing. This restriction goes only one level deep, so recursive E's will have the "add" rule again.
For example:
syntax E
= id: Id
| app: E "(" {E!comma ","}* ")"
> left mul: E "*" E
> left add: E "+" E
> right comma: E "," E
;
The E
in {E ","}*
of the function application rule is restricted to not be the comma expression, in order to avoid syntactic ambiguity.
Side note: The ! operator is the primitive constraint type used to model the priority (>) and associative (left, right) semantics as well, but those are transitive and checked for safety, etc. This on the other hand is a brutal removal of a definition and thus may change the accepted sentences of your language.