package com.kreative.paint.material.shape;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class ExpressionParser {
private final List<Integer> precedences;
private final ExpressionLexer lexer;
public ExpressionParser(String s) {
this(new ExpressionLexer(s));
}
public ExpressionParser(ExpressionLexer lexer) {
this.precedences = new ArrayList<Integer>();
this.precedences.addAll(Operator.operators.keySet());
Collections.sort(this.precedences);
this.lexer = lexer;
}
private Expression parseFactor() {
String s = lexer.getNext();
if (s == null) {
throw ExpressionParserException.expected("factor", s);
} else if (s.equals("(")) {
Expression e = parseExpression();
String z = lexer.getNext();
if (z.equals(")")) return e;
throw ExpressionParserException.expected("\")\"", z);
} else if (s.equals("[")) {
Expression e = parseExpression();
String z = lexer.getNext();
if (z.equals("]")) return e;
throw ExpressionParserException.expected("\"]\"", z);
} else if (s.equals("{")) {
Expression e = parseExpression();
String z = lexer.getNext();
if (z.equals("}")) return e;
throw ExpressionParserException.expected("\"}\"", z);
} else if (Function.functions.containsKey(s.toLowerCase())) {
Function f = Function.functions.get(s.toLowerCase());
Expression e = parseFactor();
return new Expression.Unary(f, e);
} else if (s.equals("\u221E") || s.equalsIgnoreCase("inf") || s.equalsIgnoreCase("infinity")) {
return new Expression.Value(Double.POSITIVE_INFINITY);
} else if (s.equals("\u03A6") || s.equalsIgnoreCase("nan")) {
return new Expression.Value(Double.NaN);
} else if (s.equals("\u03C0") || s.equalsIgnoreCase("pi")) {
return new Expression.Value(Math.PI);
} else if (s.equals("\u212E") || s.equalsIgnoreCase("e")) {
return new Expression.Value(Math.E);
} else if (isNumberPart(s.charAt(0))) {
try {
double d = Double.parseDouble(s);
return new Expression.Value(d);
} catch (NumberFormatException e) {
return new Expression.Binding(s);
}
} else if (isIdentifierPart(s.charAt(0))) {
return new Expression.Binding(s);
} else {
throw ExpressionParserException.expected("factor", s);
}
}
private Expression parseExpressionRA(int precedenceIndex) {
if (precedenceIndex >= precedences.size()) return parseFactor();
int precedence = precedences.get(precedenceIndex);
Map<String,Operator> ops = Operator.operators.get(precedence);
Expression e = parseExpressionRA(precedenceIndex + 1);
if (lexer.hasNext() && ops.containsKey(lexer.lookNext().toLowerCase())) {
Operator op = ops.get(lexer.getNext().toLowerCase());
e = new Expression.Binary(op, e, parseExpressionRA(precedenceIndex));
}
return e;
}
private Expression parseExpressionLA(int precedenceIndex) {
if (precedenceIndex >= precedences.size()) return parseFactor();
int precedence = precedences.get(precedenceIndex);
if (precedence >= Operator.pow.precedence) return parseExpressionRA(precedenceIndex);
Map<String,Operator> ops = Operator.operators.get(precedence);
Expression e = parseExpressionLA(precedenceIndex + 1);
while (lexer.hasNext() && ops.containsKey(lexer.lookNext().toLowerCase())) {
Operator op = ops.get(lexer.getNext().toLowerCase());
e = new Expression.Binary(op, e, parseExpressionLA(precedenceIndex + 1));
}
return e;
}
public Expression parseExpression() {
Expression e = parseExpressionLA(0);
if (lexer.hasNext() && lexer.lookNext().equals("?")) {
lexer.getNext();
Expression t = parseExpression();
if (lexer.hasNext() && lexer.lookNext().equals(":")) {
lexer.getNext();
Expression f = parseExpression();
e = new Expression.Conditional(e, t, f);
} else {
Expression f = new Expression.Value(Double.NaN);
e = new Expression.Conditional(e, t, f);
}
}
return e;
}
public Expression parse() {
Expression e = parseExpression();
if (!lexer.hasNext()) return e;
String s = lexer.lookNext();
throw ExpressionParserException.expected(null, s);
}
private static boolean isNumberPart(char ch) {
return ch == '.' || Character.isDigit(ch);
}
private static boolean isIdentifierPart(char ch) {
return ch == '.' || Character.isDigit(ch) || Character.isLetter(ch);
}
}