### Question:
PrecedenceClimbingParser { public SpecialOp special( Object o, int leftPrec, int rightPrec, Special special ) { return new SpecialOp( o, leftPrec * 2, rightPrec * 2, special ); } private  PrecedenceClimbingParser( List<Token> tokens ); Token atom( Object o ); Call call( Op op, ImmutableList<Token> args ); Op infix( Object o, int precedence, boolean left ); Op prefix( Object o, int precedence ); Op postfix( Object o, int precedence ); SpecialOp special( Object o, int leftPrec, int rightPrec, Special special ); Token parse(); void partialParse(); @Override String toString(); List<Token> all(); String print( Token token ); PrecedenceClimbingParser copy( int start, Predicate<Token> predicate );  }### Answer:
@Test public void testSpecial() { final PrecedenceClimbingParser p = new PrecedenceClimbingParser.Builder() .atom( "price" ) .infix( ">", 4, true ) .atom( "5" ) .infix( "and", 2, true ) .atom( "price" ) .special( "between", 3, 3, ( parser, op ) -> new PrecedenceClimbingParser.Result( op.previous, op.next.next.next, parser.call( op, ImmutableList.of( op.previous, op.next, op.next.next.next ) ) ) ) .atom( "1" ) .infix( "+", 5, true ) .atom( "2" ) .infix( "and", 2, true ) .atom( "3" ) .infix( "*", 6, true ) .atom( "4" ) .infix( "and", 2, true ) .atom( "price" ) .postfix( "is null", 4 ) .build(); final PrecedenceClimbingParser.Token token = p.parse(); assertThat( p.print( token ), is( "(((price > 5) and between(price, (1 + 2), (3 * 4))) and (price is null))" ) ); }