private void negate(RENode.CharacterClassExpr negated) throws RuntimeException {
   if (negated instanceof RENode.CharacterClassExpr.Not) {
     RENode.CharacterClassExpr nested = ((RENode.CharacterClassExpr.Not) negated).getNegated();
     if (nested != null) {
       nested.accept(this);
     }
   } else if (negated instanceof RENode.CharacterClassExpr.Or) {
     RENode.CharacterClassExpr.Or or = (RENode.CharacterClassExpr.Or) negated;
     negate(or.getLeft());
     Solver left = solver;
     negate(or.getRight());
     Solver right = solver;
     solver = new Solver.And(left, right);
   } else if (negated instanceof RENode.CharacterClassExpr.And) {
     RENode.CharacterClassExpr.And or = (RENode.CharacterClassExpr.And) negated;
     negate(or.getLeft());
     Solver left = solver;
     negate(or.getRight());
     Solver right = solver;
     solver = new Solver.Or(left, right);
   } else {
     char from;
     char to;
     if (negated instanceof RENode.CharacterClassExpr.Char) {
       from = to = ((RENode.CharacterClassExpr.Char) negated).getValue();
     } else if (negated instanceof RENode.CharacterClassExpr.Range) {
       RENode.CharacterClassExpr.Range range = (RENode.CharacterClassExpr.Range) negated;
       from = range.getFrom().getValue();
       to = range.getTo().getValue();
     } else {
       throw new UnsupportedOperationException();
     }
     Solver.Range left = null;
     Character c = prevValid(--from);
     if (c != null) {
       left = new Solver.Range(' ', c);
     }
     Solver.Range right = null;
     c = nextValid(++to);
     if (c != null) {
       right = new Solver.Range(c, Character.MAX_VALUE);
     }
     if (left == null) {
       if (right != null) {
         solver = right;
       }
     } else {
       if (right == null) {
         solver = left;
       } else {
         solver = new Solver.Or(left, right);
       }
     }
   }
 }
 @Override
 protected void visit(RENode.CharacterClassExpr.Range expr) throws RuntimeException {
   RENode.CharacterClassExpr.Char from = expr.getFrom();
   RENode.CharacterClassExpr.Char to = expr.getTo();
   solver = new Solver.Range(from.getValue(), to.getValue());
 }