public SymbolNode(Token token) { assert token.getType() == TokenType.SYMBOL; this.name = token.getString(); this.sourceRange = new SourceRange(token); }
public ConstantNode(Token token, SourceRange range) { // Enum constant from parser this(new EnumValue(ResourceId.valueOf(token.getString()))); this.sourceRange = range; }
private FormulaNode booleanLiteral() { Token token = lexer.next(); assert token.getType() == TokenType.BOOLEAN_LITERAL; boolean value = token.getString().toLowerCase().equals("true"); SourceRange source = new SourceRange(token); return new ConstantNode(value, source); }
private FormulaNode number() { Token token = lexer.next(); double value; try { value = Double.parseDouble(token.getString()); } catch (NumberFormatException e) { throw new FormulaSyntaxException(new SourceRange(token), "Invalid number '" + token.getString() + "': " + e.getMessage()); } return new ConstantNode(value, new SourceRange(token)); }
private FormulaNode stringLiteral() { Token token = lexer.next(); assert token.getType() == TokenType.STRING_LITERAL; return new ConstantNode(token.getString(), new SourceRange(token)); }
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 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 void expect(String string, Token... tokens) { System.out.println("Tokenizing [" + string + "]"); FormulaLexer tokenizer = new FormulaLexer(string); int expectedIndex = 0; while (!tokenizer.isEndOfInput()) { String expectedString; Token expected; if(expectedIndex < tokens.length) { expected = tokens[expectedIndex]; expectedString = expected.toString(); } else { expected = null; expectedString = "<NOTHING>"; } Token actual = tokenizer.next(); System.out.println(String.format("Expected: %15s, got %s", expectedString, actual.toString())); if(expected != null) { assertEquals("tokenStart", expected.getTokenStartColumn(), actual.getTokenStartColumn()); assertEquals("text", expected.getString(), actual.getString()); assertEquals("type", expected.getType(), actual.getType()); if (!expected.equals(actual)) { System.err.println("Unexpected result!"); throw new AssertionError(); } } expectedIndex ++; } }
private FormulaNode primary() { switch (lexer.peek().getType()) { case SYMBOL: if(lexer.peek().getString().matches("t\\d{10}")) { return enumLiteral(); } else { return symbolOrCall(); } case NUMBER: return number(); case BOOLEAN_LITERAL: return booleanLiteral(); case STRING_LITERAL: return stringLiteral(); case PAREN_START: Token openToken = lexer.next(); FormulaNode e = expression(); Token closeToken = expect(TokenType.PAREN_END); return new GroupNode(e, new SourceRange(openToken, closeToken)); default: throw new FormulaSyntaxException(new SourceRange(lexer.peek()), "Expected a symbol, a number, a string, or '('"); } }