rules --> rule, rules ; [].
rule --> name, actual_rule, pragma, [atom('.')].
name --> atom, [atom('@')] ; [].
actual_rule --> simplification_rule.
actual_rule --> propagation_rule.
actual_rule --> simpagation_rule.
simplification_rule --> head, [atom('<=>')], guard, body.
propagation_rule --> head, [atom('==>')], guard, body.
simpagation_rule --> head, [atom('\')], head, [atom('<=>')],
guard, body.
head --> constraints.
constraints --> constraint, constraint_id.
constraints --> constraint, constraint_id,
[atom(',')], constraints.
constraint --> compound_term.
constraint_id --> [].
constraint_id --> [atom('#')], variable.
constraint_id --> [atom('#')], [atom('passive')] .
guard --> [] ; goal, [atom('|')].
body --> goal.
pragma --> [].
pragma --> [atom('pragma')], actual_pragmas.
actual_pragmas --> actual_pragma.
actual_pragmas --> actual_pragma, [atom(',')], actual_pragmas.
actual_pragma --> [atom('passive(')], variable, [atom(')')].
Note that the guard of a rule may not contain any goal that binds a
variable in the head of the rule with a non-variable or with another
variable in the head of the rule. It may, however, bind variables that
do not appear in the head of the rule, e.g. an auxiliary variable
introduced in the guard.