class Result { public double acc; public String rest; public Result(double v, String r) { this.acc = v; this.rest = r; } }
public class MatchParserPlusMinus { public MatchParserPlusMinus(){} public double Parse(String s) throws Exception { Result result = PlusMinus(s); if (!result.rest.isEmpty()) { System.err.println("Error: can't full parse"); System.err.println("rest: " + result.rest); } return result.acc; } private Result PlusMinus(String s) throws Exception { Result current = Num(s); double acc = current.acc; while (current.rest.length() > 0) { if (!(current.rest.charAt(0) == '+' || current.rest.charAt(0) == '-')) break; char sign = current.rest.charAt(0); String next = current.rest.substring(1); acc = current.acc; current = Num(next); if (sign == '+') { acc += current.acc; } else { acc -= current.acc; } current.acc = acc; } return new Result(current.acc, current.rest); } private Result Num(String s) throws Exception { int i = 0; int dot_cnt = 0; boolean negative = false; // if( s.charAt(0) == '-' ){ negative = true; s = s.substring( 1 ); } // while (i < s.length() && (Character.isDigit(s.charAt(i)) || s.charAt(i) == '.')) { // , ! if (s.charAt(i) == '.' && ++dot_cnt > 1) { throw new Exception("not valid number '" + s.substring(0, i + 1) + "'"); } i++; } if( i == 0 ){ // - throw new Exception( "can't get valid number in '" + s + "'" ); } double dPart = Double.parseDouble(s.substring(0, i)); if( negative ) dPart = -dPart; String restPart = s.substring(i); return new Result(dPart, restPart); } }
MatchParserPlusMinus pm = new MatchParserPlusMinus(); String f = "10-8+2+6"; try{ System.out.println( "PlusMinus: " + pm.Parse(f) ); }catch(Exception e){ System.err.println( "Error while parsing '"+f+"' with message: " + e.getMessage() ); }
PlusMinus: 10.0
public class MatchParser { private HashMap<String, Double> variables; public MatchParser() { variables = new HashMap<String, Double>(); } public void setVariable(String variableName, Double variableValue) { variables.put(variableName, variableValue); } public Double getVariable(String variableName) { if (!variables.containsKey(variableName)) { System.err.println( "Error: Try get unexists variable '"+variableName+"'" ); return 0.0; } return variables.get(variableName); } public double Parse(String s) throws Exception { Result result = PlusMinus(s); if (!result.rest.isEmpty()) { System.err.println("Error: can't full parse"); System.err.println("rest: " + result.rest); } return result.acc; } private Result PlusMinus(String s) throws Exception { Result current = MulDiv(s); double acc = current.acc; while (current.rest.length() > 0) { if (!(current.rest.charAt(0) == '+' || current.rest.charAt(0) == '-')) break; char sign = current.rest.charAt(0); String next = current.rest.substring(1); current = MulDiv(next); if (sign == '+') { acc += current.acc; } else { acc -= current.acc; } } return new Result(acc, current.rest); } private Result Bracket(String s) throws Exception { char zeroChar = s.charAt(0); if (zeroChar == '(') { Result r = PlusMinus(s.substring(1)); if (!r.rest.isEmpty() && r.rest.charAt(0) == ')') { r.rest = r.rest.substring(1); } else { System.err.println("Error: not close bracket"); } return r; } return FunctionVariable(s); } private Result FunctionVariable(String s) throws Exception { String f = ""; int i = 0; // // while (i < s.length() && (Character.isLetter(s.charAt(i)) || ( Character.isDigit(s.charAt(i)) && i > 0 ) )) { f += s.charAt(i); i++; } if (!f.isEmpty()) { // - if ( s.length() > i && s.charAt( i ) == '(') { // - Result r = Bracket(s.substring(f.length())); return processFunction(f, r); } else { // - return new Result(getVariable(f), s.substring(f.length())); } } return Num(s); } private Result MulDiv(String s) throws Exception { Result current = Bracket(s); double acc = current.acc; while (true) { if (current.rest.length() == 0) { return current; } char sign = current.rest.charAt(0); if ((sign != '*' && sign != '/')) return current; String next = current.rest.substring(1); Result right = Bracket(next); if (sign == '*') { acc *= right.acc; } else { acc /= right.acc; } current = new Result(acc, right.rest); } } private Result Num(String s) throws Exception { int i = 0; int dot_cnt = 0; boolean negative = false; // if( s.charAt(0) == '-' ){ negative = true; s = s.substring( 1 ); } // while (i < s.length() && (Character.isDigit(s.charAt(i)) || s.charAt(i) == '.')) { // , ! if (s.charAt(i) == '.' && ++dot_cnt > 1) { throw new Exception("not valid number '" + s.substring(0, i + 1) + "'"); } i++; } if( i == 0 ){ // - throw new Exception( "can't get valid number in '" + s + "'" ); } double dPart = Double.parseDouble(s.substring(0, i)); if( negative ) dPart = -dPart; String restPart = s.substring(i); return new Result(dPart, restPart); } // , private Result processFunction(String func, Result r) { if (func.equals("sin")) { return new Result(Math.sin(Math.toRadians(r.acc)), r.rest); } else if (func.equals("cos")) { return new Result(Math.cos(Math.toRadians(r.acc)), r.rest); } else if (func.equals("tan")) { return new Result(Math.tan(Math.toRadians(r.acc)), r.rest); } else { System.err.println("function '" + func + "' is not defined"); } return r; } }
String[] formulas = new String[] { "2+2*2", "2+X*2", "sin(90)+4-cos(0)", "2--4", "2**3*5-----7", "3.5.6-2" }; MatchParser p = new MatchParser(); p.setVariable("X", 2.0 ); for( int i = 0; i < formulas.length; i++){ try{ System.out.println( formulas[i] + "=" + p.Parse( formulas[i] ) ); }catch(Exception e){ System.err.println( "Error while parsing '"+formulas[i]+"' with message: " + e.getMessage() ); } }
2+2*2=6.0
2+X*2=6.0
sin(90)+4-cos(0)=4.0
2--4=6.0
Error while parsing '2**3*5-----7' with message: can't get valid number in '*3*5-----7'
Error while parsing '3.5.6-2' with message: not valid number '3.5.'
Source: https://habr.com/ru/post/122397/
All Articles