/**************************************************************************************** * Copyright (c) 2014 Michael Goldbach <michael@wildplot.com> * * * * This program is free software; you can redistribute it and/or modify it under * * the terms of the GNU General Public License as published by the Free Software * * Foundation; either version 3 of the License, or (at your option) any later * * version. * * * * This program is distributed in the hope that it will be useful, but WITHOUT ANY * * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * * PARTICULAR PURPOSE. See the GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License along with * * this program. If not, see <http://www.gnu.org/licenses/>. * ****************************************************************************************/ package com.wildplot.android.parsing; import com.wildplot.android.rendering.interfaces.Function2D; import com.wildplot.android.rendering.interfaces.Function3D; import java.util.HashMap; import java.util.Random; import java.util.regex.Pattern; public class TopLevelParser implements Function2D, Function3D, Cloneable{ Random random = new Random(); private HashMap<String, TopLevelParser> parserRegister; private HashMap<String, Double> varMap = new HashMap<>(); private double x = 0.0, y = 0.0; private Expression expression = null; private boolean isValid = false; private String expressionString; private String xName = "x", yName = "y"; private String funcName = "f" +random.nextInt(); public TopLevelParser(String expressionString, HashMap<String, TopLevelParser> parserRegister){ initVarMap(); this.parserRegister = parserRegister; this.expressionString = expressionString; boolean isValidExpressionString = initExpressionString(); this.expression = new Expression(this.expressionString, this); this.isValid = (expression.getExpressionType() != Expression.ExpressionType.INVALID) && isValidExpressionString; } private void initVarMap(){ varMap.put("e", Math.E); varMap.put("pi", Math.PI); } private boolean initExpressionString(){ this.expressionString = expressionString.replace(" ", ""); int equalPosition = expressionString.indexOf("="); if(equalPosition >= 1){ String leftStatement = expressionString.substring(0, equalPosition); this.expressionString = expressionString.substring(equalPosition+1, expressionString.length()); int commaPos = leftStatement.indexOf(","); int leftBracketPos = leftStatement.indexOf("("); int rightBracketPos = leftStatement.indexOf(")"); if(leftBracketPos > 0 && rightBracketPos > leftBracketPos +1){ String funcName = leftStatement.substring(0, leftBracketPos); Pattern p = Pattern.compile("[^a-zA-Z0-9]"); boolean hasSpecialChar = p.matcher(funcName).find(); if(hasSpecialChar){ return false; } if(commaPos == -1){ String xVarName = leftStatement.substring(leftBracketPos+1, rightBracketPos); hasSpecialChar = p.matcher(xVarName).find(); if(hasSpecialChar){ return false; } this.xName = xVarName; } else { String xVarName = leftStatement.substring(leftBracketPos+1, commaPos); hasSpecialChar = p.matcher(xVarName).find(); if(hasSpecialChar){ return false; } String yVarName = leftStatement.substring(commaPos+1, rightBracketPos); hasSpecialChar = p.matcher(yVarName).find(); if(hasSpecialChar){ return false; } this.xName = xVarName; this.yName = yVarName; } this.funcName = funcName; }else { return false; } } return true; } public double getVarVal(String varName){ return varMap.get(varName); } public void setVarVal(String varName, String varVal){ varMap.put(varName, Double.parseDouble(varVal)); } public void setVarVal(String varName, double varVal){ varMap.put(varName, varVal); } public double getX() { return x; } public void setX(double x) { this.x = x; } public double getY() { return y; } public void setY(double y) { this.y = y; } @Override public double f(double x) { this.x = x; if(isValid) return expression.getValue(); else throw new ExpressionFormatException("illegal Expression, cannot parse and return value"); } public boolean isValid() { return isValid; } @Override public double f(double x, double y) { this.x = x; this.y = y; if(isValid) return expression.getValue(); else throw new ExpressionFormatException("illegal Expression, cannot parse and return value"); } public TopLevelParser createCopy(){ HashMap<String, TopLevelParser> newParserRegister = new HashMap<>(); for(String key : parserRegister.keySet()){ newParserRegister.put(key, parserRegister.get(key).createCopy(newParserRegister)); } return newParserRegister.get(this.funcName); } public TopLevelParser createCopy(HashMap<String, TopLevelParser> newParserRegister){ return new TopLevelParser(this.expressionString, newParserRegister); } public double getFuncVal(String funcName, double xVal){ TopLevelParser funcParser = this.parserRegister.get(funcName); return funcParser.f(xVal); } public double getFuncVal(String funcName, double xVal, double yVal){ TopLevelParser funcParser = this.parserRegister.get(funcName); return funcParser.f(xVal, yVal); } public String getxName() { return xName; } public String getyName() { return yName; } public String getFuncName() { return funcName; } public static boolean stringHasValidBrackets(String string){ int finalBracketCheck = string.replaceAll("\\(", "").length()- string.replaceAll("\\)", "").length(); if(finalBracketCheck != 0) return false; int bracketOpeningCheck = 0; for(int i = 0; i<string.length(); i++){ if(string.charAt(i) == '('){ bracketOpeningCheck++; } if(string.charAt(i) == ')'){ bracketOpeningCheck--; } if(bracketOpeningCheck <0){ return false; } } return true; } }