private FormulaFunction function() { Token token = lexer.next(); return function(token); }
private FormulaNode relational() { FormulaNode left = term(); while(lexer.hasNext() && lexer.peek().isRelationalOperator()) { FormulaFunction op = function(); FormulaNode right = term(); left = binaryInfixCall(op, left, right); } return left; }
private FormulaNode conjunction() { FormulaNode left = equality(); while(lexer.hasNext() && lexer.peek().isAndOperator()) { FormulaFunction op = function(); FormulaNode right = equality(); left = binaryInfixCall(op, left, right); } return left; }
private FormulaNode equality() { FormulaNode left = relational(); while(lexer.hasNext() && lexer.peek().isEqualityOperator()) { FormulaFunction op = function(); FormulaNode right = relational(); left = binaryInfixCall(op, left, right); } return left; }
private FormulaNode term() { // <term> ::= <factor> | <term> + <factor> | <term> - <factor> FormulaNode left = factor(); while (lexer.hasNext() && lexer.peek().isAdditiveOperator()) { FormulaFunction op = function(); FormulaNode right = factor(); left = binaryInfixCall(op, left, right); } return left; }
private FormulaNode disjunction() { FormulaNode left = conjunction(); while(lexer.hasNext() && lexer.peek().isOrOperator()) { FormulaFunction op = function(); FormulaNode right = conjunction(); left = binaryInfixCall(op, left, right); } return left; }
public FormulaNode factor() { // <factor> ::= <unary> | <factor> * <unary> | <factor> / <unary> FormulaNode left = unary(); while(lexer.hasNext() && lexer.peek().isMultiplicativeOperator()) { FormulaFunction function = function(); FormulaNode right = unary(); left = binaryInfixCall(function, left, right); } return left; }
private FormulaNode unary2() { if(!lexer.hasNext()) { throw new FormulaSyntaxException("Unexpected end of formula"); } Token token = lexer.peek(); if(token.getType() == TokenType.OPERATOR) { if(token.getString().equals("!")) { Token opToken = lexer.next(); FormulaFunction op = function(opToken); FormulaNode operand = primary(); SourceRange sourceRange = new SourceRange(opToken.getStart(), operand.getSourceRange().getEnd()); return new FunctionCallNode(op, singletonList(operand), sourceRange); } } return primary(); }
private FormulaNode unary() { // <unary> ::= + <unary> | - <unary> | <unary2> if(!lexer.hasNext()) { throw new FormulaSyntaxException("Unexpected end of formula"); } Token token = lexer.peek(); if(token.getType() == TokenType.OPERATOR) { if(token.getString().equals("-") || token.getString().equals("+")) { Token opToken = lexer.next(); FormulaFunction op = function(opToken); FormulaNode operand = unary(); SourceRange sourceRange = new SourceRange(opToken.getStart(), operand.getSourceRange().getEnd()); return new FunctionCallNode(op, singletonList(operand), sourceRange); } } return unary2(); }
private FormulaNode call(Token functionToken) { FormulaFunction function = function(functionToken); expect(TokenType.PAREN_START); List<FormulaNode> arguments = new ArrayList<>(); while(true) { if (!lexer.hasNext()) { throw new FormulaSyntaxException("Unexpected end of formula"); } TokenType nextToken = lexer.peek().getType(); if (nextToken == TokenType.COMMA) { // Consume comma and parse next argument lexer.next(); continue; } if (nextToken == TokenType.PAREN_END) { // consume paren and complete argument list Token closingParen = lexer.next(); return new FunctionCallNode(function, arguments, new SourceRange(functionToken, closingParen)); } // Otherwise parse the next argument arguments.add(expression()); } }