Add a constrained negation to transliteration, e.g.
a } !([:M:]*[:L:]*) > X
The constraints are to designed to make it easy to implement and predict. They
are:
A negation can only be leading or trailing. That is, you can't have anything
before a negation in the BEFORE context, and nothing after a negation in the
source or AFTER context.
!a b { c d } e !f > X ; # valid
!a b { c d } !(e f) > X ; # valid
!a b { c !d } > X ; # valid
!a b { !c } > X ; # valid
!a b { c d } !e f > X ; # invalid
a !b { c d } e !f > X ; # invalid
!a b { c !d } e f > X ; # invalid
The implementation is to
(a) disallow any invalids
(b) for all valid cases, set a flag on the node. When the match is made,
true/false are switched when returning from that node.
(c) if the negation affects the first character of the source, then the rule is
put into the inverse set of buckets (from what it would normally be put in).