/** * Parses the expression in <tt>input</tt> * * @return the parsed expression * @throws ParseException if the expression contains one or more errors */ protected Expression parse() throws ParseException { Expression result = expression().simplify(); if (tokenizer.current().isNotEnd()) { Token token = tokenizer.consume(); errors.add(ParseError.error(token, String.format("Unexpected token: '%s'. Expected an expression.", token.getSource()))); } if (!errors.isEmpty()) { throw ParseException.create(errors); } return result; }
/** * Parses the expression in <tt>input</tt> * * @return the parsed expression * @throws ParseException if the expression contains one or more errors */ protected Expression parse() throws ParseException { Expression result = expression().simplify(); if (tokenizer.current().isNotEnd()) { Token token = tokenizer.consume(); errors.add(ParseError.error(token, String.format("Unexpected token: '%s'. Expected an expression.", token.getSource()))); } if (!errors.isEmpty()) { throw ParseException.create(errors); } return result; }
/** * Signals that the given token is expected. * <p> * If the current input is pointing at the specified token, it will be consumed. If not, an error will be added * to the error list and the input remains unchanged. * * @param type the type of the expected token * @param trigger the trigger of the expected token */ protected void expect(Token.TokenType type, String trigger) { if (tokenizer.current().matches(type, trigger)) { tokenizer.consume(); } else { errors.add(ParseError.error(tokenizer.current(), String.format("Unexpected token '%s'. Expected: '%s'", tokenizer.current().getSource(), trigger))); } } }
/** * Signals that the given token is expected. * <p> * If the current input is pointing at the specified token, it will be consumed. If not, an error will be added * to the error list and the input remains unchanged. * * @param type the type of the expected token * @param trigger the trigger of the expected token */ protected void expect(Token.TokenType type, String trigger) { if (tokenizer.current().matches(type, trigger)) { tokenizer.consume(); } else { errors.add(ParseError.error(tokenizer.current(), String.format("Unexpected token '%s'. Expected: '%s'", tokenizer.current().getSource(), trigger))); } } }
/** * Consumes the current token, expecting it to be as <tt>SYMBOL</tt> with the given content * * @param symbol the expected trigger of the current token */ public void consumeExpectedSymbol(String symbol) { if (current().matches(Token.TokenType.SYMBOL, symbol)) { consume(); } else { addError(current(), "Unexpected token: '%s'. Expected: '%s'", current().getSource(), symbol); } }
/** * Consumes the current token, expecting it to be as <tt>KEYWORD</tt> with the given content * * @param keyword the expected content of the current token */ public void consumeExpectedKeyword(String keyword) { if (current().matches(Token.TokenType.KEYWORD, keyword)) { consume(); } else { addError(current(), "Unexpected token: '%s'. Expected: '%s'", current().getSource(), keyword); } }
/** * Consumes the current token, expecting it to be as <tt>KEYWORD</tt> with the given content * * @param keyword the expected content of the current token */ public void consumeExpectedKeyword(String keyword) { if (current().matches(Token.TokenType.KEYWORD, keyword)) { consume(); } else { addError(current(), "Unexpected token: '%s'. Expected: '%s'", current().getSource(), keyword); } }
/** * Consumes the current token, expecting it to be as <tt>SYMBOL</tt> with the given content * * @param symbol the expected trigger of the current token */ public void consumeExpectedSymbol(String symbol) { if (current().matches(Token.TokenType.SYMBOL, symbol)) { consume(); } else { addError(current(), "Unexpected token: '%s'. Expected: '%s'", current().getSource(), symbol); } }
/** * Parser rule for parsing an expression. * <p> * This is the root rule. An expression is a <tt>relationalExpression</tt> which might be followed by a logical * operator (&& or ||) and another <tt>expression</tt>. * * @return an expression parsed from the given input */ protected Expression expression() { Expression left = relationalExpression(); if (tokenizer.current().isSymbol("&&")) { tokenizer.consume(); Expression right = expression(); return reOrder(left, right, BinaryOperation.Op.AND); } if (tokenizer.current().isSymbol("||")) { tokenizer.consume(); Expression right = expression(); return reOrder(left, right, BinaryOperation.Op.OR); } return left; }
/** * Parser rule for parsing an expression. * <p> * This is the root rule. An expression is a <tt>relationalExpression</tt> which might be followed by a logical * operator (&& or ||) and another <tt>expression</tt>. * * @return an expression parsed from the given input */ protected Expression expression() { Expression left = relationalExpression(); if (tokenizer.current().isSymbol("&&")) { tokenizer.consume(); Expression right = expression(); return reOrder(left, right, BinaryOperation.Op.AND); } if (tokenizer.current().isSymbol("||")) { tokenizer.consume(); Expression right = expression(); return reOrder(left, right, BinaryOperation.Op.OR); } return left; }
/** * Parser rule for parsing a product. * <p> * A product is a <tt>power</tt> which might be followed by *, / or % as operator and another <tt>product</tt>. * * @return a product parsed from the given input */ protected Expression product() { Expression left = power(); if (tokenizer.current().isSymbol("*")) { tokenizer.consume(); Expression right = product(); return reOrder(left, right, BinaryOperation.Op.MULTIPLY); } if (tokenizer.current().isSymbol("/")) { tokenizer.consume(); Expression right = product(); return reOrder(left, right, BinaryOperation.Op.DIVIDE); } if (tokenizer.current().isSymbol("%")) { tokenizer.consume(); Expression right = product(); return reOrder(left, right, BinaryOperation.Op.MODULO); } return left; }
/** * Parser rule for parsing a product. * <p> * A product is a <tt>power</tt> which might be followed by *, / or % as operator and another <tt>product</tt>. * * @return a product parsed from the given input */ protected Expression product() { Expression left = power(); if (tokenizer.current().isSymbol("*")) { tokenizer.consume(); Expression right = product(); return reOrder(left, right, BinaryOperation.Op.MULTIPLY); } if (tokenizer.current().isSymbol("/")) { tokenizer.consume(); Expression right = product(); return reOrder(left, right, BinaryOperation.Op.DIVIDE); } if (tokenizer.current().isSymbol("%")) { tokenizer.consume(); Expression right = product(); return reOrder(left, right, BinaryOperation.Op.MODULO); } return left; }
Expression left = term(); if (tokenizer.current().isSymbol("<")) { tokenizer.consume(); Expression right = relationalExpression(); return reOrder(left, right, BinaryOperation.Op.LT); tokenizer.consume(); Expression right = relationalExpression(); return reOrder(left, right, BinaryOperation.Op.LT_EQ); tokenizer.consume(); Expression right = relationalExpression(); return reOrder(left, right, BinaryOperation.Op.EQ); tokenizer.consume(); Expression right = relationalExpression(); return reOrder(left, right, BinaryOperation.Op.GT_EQ); tokenizer.consume(); Expression right = relationalExpression(); return reOrder(left, right, BinaryOperation.Op.GT); tokenizer.consume(); Expression right = relationalExpression(); return reOrder(left, right, BinaryOperation.Op.NEQ);
Expression left = term(); if (tokenizer.current().isSymbol("<")) { tokenizer.consume(); Expression right = relationalExpression(); return reOrder(left, right, BinaryOperation.Op.LT); tokenizer.consume(); Expression right = relationalExpression(); return reOrder(left, right, BinaryOperation.Op.LT_EQ); tokenizer.consume(); Expression right = relationalExpression(); return reOrder(left, right, BinaryOperation.Op.EQ); tokenizer.consume(); Expression right = relationalExpression(); return reOrder(left, right, BinaryOperation.Op.GT_EQ); tokenizer.consume(); Expression right = relationalExpression(); return reOrder(left, right, BinaryOperation.Op.GT); tokenizer.consume(); Expression right = relationalExpression(); return reOrder(left, right, BinaryOperation.Op.NEQ);
/** * Parser rule for parsing a power. * <p> * A power is an <tt>atom</tt> which might be followed by ^ or ** as operator and another <tt>power</tt>. * * @return a power parsed from the given input */ protected Expression power() { Expression left = atom(); if (tokenizer.current().isSymbol("^") || tokenizer.current().isSymbol("**")) { tokenizer.consume(); Expression right = power(); return reOrder(left, right, BinaryOperation.Op.POWER); } return left; }
/** * Parser rule for parsing a power. * <p> * A power is an <tt>atom</tt> which might be followed by ^ or ** as operator and another <tt>power</tt>. * * @return a power parsed from the given input */ protected Expression power() { Expression left = atom(); if (tokenizer.current().isSymbol("^") || tokenizer.current().isSymbol("**")) { tokenizer.consume(); Expression right = power(); return reOrder(left, right, BinaryOperation.Op.POWER); } return left; }
/** * Parser rule for parsing a term. * <p> * A term is a <tt>product</tt> which might be followed by + or - as operator and another <tt>term</tt>. * * @return a term parsed from the given input */ protected Expression term() { Expression left = product(); if (tokenizer.current().isSymbol("+")) { tokenizer.consume(); Expression right = term(); return reOrder(left, right, BinaryOperation.Op.ADD); } if (tokenizer.current().isSymbol("-")) { tokenizer.consume(); Expression right = term(); return reOrder(left, right, BinaryOperation.Op.SUBTRACT); } if (tokenizer.current().isNumber()) { if (tokenizer.current().getContents().startsWith("-")) { Expression right = term(); return reOrder(left, right, BinaryOperation.Op.ADD); } } return left; }
/** * Parser rule for parsing a term. * <p> * A term is a <tt>product</tt> which might be followed by + or - as operator and another <tt>term</tt>. * * @return a term parsed from the given input */ protected Expression term() { Expression left = product(); if (tokenizer.current().isSymbol("+")) { tokenizer.consume(); Expression right = term(); return reOrder(left, right, BinaryOperation.Op.ADD); } if (tokenizer.current().isSymbol("-")) { tokenizer.consume(); Expression right = term(); return reOrder(left, right, BinaryOperation.Op.SUBTRACT); } if (tokenizer.current().isNumber()) { if (tokenizer.current().getContents().startsWith("-")) { Expression right = term(); return reOrder(left, right, BinaryOperation.Op.ADD); } } return left; }