@@ -358,6 +358,47 @@ class OpTreeContext(parser: Expr[Parser])(using Quotes) {
358
358
}
359
359
}
360
360
361
+ case class NotPredicate (op : OpTree ) extends OpTree {
362
+
363
+ def render (wrapped : Boolean ): Expr [Boolean ] = {
364
+ def unwrappedExpr (setMatchEnd : Option [Expr [Int ] => Expr [Unit ]]): Expr [Boolean ] = ' {
365
+ val mark = $parser.__saveState
366
+ val saved = $parser.__enterNotPredicate()
367
+ val matched = $ { op.render(wrapped) }
368
+ $parser.__exitNotPredicate(saved)
369
+ $ {
370
+ setMatchEnd match {
371
+ case Some (matchEndSetter) => matchEndSetter(' { $parser.cursor })
372
+ case None => ' {}
373
+ }
374
+ }
375
+ $parser.__restoreState(mark)
376
+ ! matched
377
+ }
378
+
379
+ if (wrapped) {
380
+ val base = op match {
381
+ case x : TerminalOpTree => ' { RuleTrace .NotPredicate .Terminal ($ { x.ruleTraceTerminal }) }
382
+ case x : RuleCall => ' { RuleTrace .NotPredicate .RuleCall ($ { x.calleeNameTree }) }
383
+ case x : StringMatch => ' { RuleTrace .NotPredicate .Named (s " \" ${$ { x.stringTree }}\" " ) }
384
+ case x : IgnoreCaseString => ' { RuleTrace .NotPredicate .Named (s " \" ${$ { x.stringTree }}\" " ) }
385
+ // case x: Named => '{RuleTrace.NotPredicate.Named(s"\"${${x.stringTree}}\"")}
386
+ case _ => ' { RuleTrace .NotPredicate .Anonymous }
387
+ }
388
+ ' {
389
+ var matchEnd = 0
390
+ try $ { unwrappedExpr(Some (v => ' { matchEnd = $v })) } || $parser.__registerMismatch()
391
+ catch {
392
+ case Parser .StartTracingException =>
393
+ $parser.__bubbleUp {
394
+ RuleTrace .NotPredicate ($base, matchEnd - $parser.cursor)
395
+ }
396
+ }
397
+ }
398
+ } else unwrappedExpr(None )
399
+ }
400
+ }
401
+
361
402
private case class Action (body : Term , ts : List [TypeTree ]) extends DefaultNonTerminalOpTree {
362
403
def ruleTraceNonTerminalKey = ' { RuleTrace .Action }
363
404
@@ -762,6 +803,7 @@ class OpTreeContext(parser: Expr[Parser])(using Quotes) {
762
803
Sequence (rec(base), Action (body, ts))
763
804
764
805
case Apply (Select (_, " &" ), List (arg)) => AndPredicate (rec(arg))
806
+ case Select (arg, " unary_!" ) => NotPredicate (rec(arg))
765
807
766
808
case Apply (
767
809
Select (Apply (TypeApply (Select (_, " rule2WithSeparatedBy" ), _), List (base)), " separatedBy" ),
0 commit comments