Search code examples
rascal

What does the syntax condition `!` (labelled "except") do?


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?


Solution

  • 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.

    • The benefit here is that you do not have to introduce yet another non-terminal which also logically represents expressions.
    • The pitfall is that the ! operator is a hard restriction and thus may make the accepted language actually smaller: use of ! may lead to unexpected parse errors if not used carefully.

    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.