ExpressionParser { static Parser<Expression> arithmetic(Parser<Expression> atom) { Parser.Reference<Expression> reference = Parser.newReference(); Parser<Expression> operand = Parsers.or(paren(reference.lazy()), functionCall(reference.lazy()), atom); Parser<Expression> parser = new OperatorTable<Expression>() .infixl(binary("+", Op.PLUS), 10) .infixl(binary("-", Op.MINUS), 10) .infixl(binary("*", Op.MUL), 20) .infixl(binary("/", Op.DIV), 20) .infixl(binary("%", Op.MOD), 20) .prefix(unary("-", Op.NEG), 50) .build(operand); reference.set(parser); return parser; }    }
@Test public void testArithmetic() { Parser<Expression> parser = ExpressionParser.arithmetic(NUMBER); TerminalParserTest.assertParser(parser, "1", number(1)); TerminalParserTest.assertParser(parser, "((1))", number(1)); TerminalParserTest.assertParser(parser, "1 + 2", new BinaryExpression(number(1), Op.PLUS, number(2))); TerminalParserTest.assertParser(parser, "2 * (1 + (2))", new BinaryExpression(number(2), Op.MUL, new BinaryExpression(number(1), Op.PLUS, number(2)))); TerminalParserTest.assertParser(parser, "2 - 1 / (2)", new BinaryExpression(number(2), Op.MINUS, new BinaryExpression(number(1), Op.DIV, number(2)))); TerminalParserTest.assertParser(parser, "2 * 1 % -2", new BinaryExpression( new BinaryExpression(number(2), Op.MUL, number(1)), Op.MOD, new UnaryExpression(Op.NEG, number(2)))); TerminalParserTest.assertParser(parser, "f(1)", FunctionExpression.of(QualifiedName.of("f"), number(1))); TerminalParserTest.assertParser(parser, "foo.bar(1, 2) + baz(foo.bar(1 / 2))", new BinaryExpression( FunctionExpression.of(QualifiedName.of("foo", "bar"), number(1), number(2)), Op.PLUS, FunctionExpression.of(QualifiedName.of("baz"), FunctionExpression.of(QualifiedName.of("foo", "bar"), new BinaryExpression( number(1), Op.DIV, number(2)))))); }