本文代码下载:https://files.cnblogs.com/files/heyang78/MathAnalyzer2-20200523-1.zip
新版代码出炉了:
Token类:
package com.heyang; public class Token { public static final int TYPE_PLUS=1; public static final int TYPE_MINUS=2; public static final int TYPE_MULTI=3; public static final int TYPE_DIVIDE=4; public static final int TYPE_LEFT_PAREN=5; public static final int TYPE_RIGHT_PAREN=6; public static final int TYPE_DIGITAL=7; private int type; private String text; private double value; public Token(String text,int type) throws AnalyzerExp{ this.text=text; this.type=type; try { this.value=Double.parseDouble(this.text); }catch(NumberFormatException ex) { throw new AnalyzerExp(String.format("Can not convert text:%s to double.", this.text)); } } public Token(char c,int type) { this.text=String.valueOf(c); this.type=type; } public String toString() { if(this.type<TYPE_DIGITAL) { return this.text; }else { return String.valueOf(this.value); } } public int getType() { return type; } public double getValue() { return value; } public String getText() { return text; } public String getTypeStr() { if(type==TYPE_PLUS) { return "+"; }else if(type==TYPE_MINUS){ return "-"; }else if(type==TYPE_MULTI){ return "*"; }else if(type==TYPE_DIVIDE){ return "/"; }else if(type==TYPE_LEFT_PAREN){ return "("; }else if(type==TYPE_RIGHT_PAREN){ return ")"; }else if(type==TYPE_DIGITAL){ return String.valueOf(value); }else { return "Unknown"; } } }
分词器类:
package com.heyang; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Lexer { private List<Token> tokens; public Lexer(String mathExp) throws AnalyzerExp{ String swallowed=""; tokens=new ArrayList<Token>(); for(int i=0;i<mathExp.length();i++){ char c=mathExp.charAt(i); if(Character.isWhitespace(c)){ swallowed=""; }else if(c=='+'){ addText2Tokens(swallowed); swallowed=""; tokens.add(new Token(c,Token.TYPE_PLUS)); }else if(c=='-'){ addText2Tokens(swallowed); swallowed=""; tokens.add(new Token(c,Token.TYPE_MINUS)); }else if(c=='*'){ addText2Tokens(swallowed); swallowed=""; tokens.add(new Token(c,Token.TYPE_MULTI)); }else if(c=='/'){ addText2Tokens(swallowed); swallowed=""; tokens.add(new Token(c,Token.TYPE_DIVIDE)); }else if(c=='('){ addText2Tokens(swallowed); swallowed=""; tokens.add(new Token(c,Token.TYPE_LEFT_PAREN)); }else if(c==')'){ addText2Tokens(swallowed); swallowed=""; tokens.add(new Token(c,Token.TYPE_RIGHT_PAREN)); }else { swallowed+=c; } } if(swallowed.length()>0) { tokens.add(new Token(swallowed,Token.TYPE_DIGITAL)); } } private void addText2Tokens(String text) throws AnalyzerExp{ if(text.trim().length()>0) { tokens.add(new Token(text,Token.TYPE_DIGITAL)); } } private static String createRepeatedStr(String seed, int n) { return String.join("", Collections.nCopies(n, seed)); } public void printTokenList() { final String layout = "%-20s %-20s %-20s %-20s %s"; StringBuilder sb = new StringBuilder(); sb.append("Token list "); sb.append(String.format(layout, "Index", "Type No","Text","Type Desc"," ")); final String continuousStar = createRepeatedStr("-", 84); sb.append(continuousStar + " "); int index=0; for(Token token:tokens) { sb.append(String.format(layout, String.valueOf(index),String.valueOf(token.getType()), token.getText(),token.getTypeStr()," ")); index++; } System.out.println(sb.toString()); } public List<Token> getTokens(){ return tokens; } public static void main(String[] args) throws Exception{ Lexer lexer=new Lexer("3+(2*5)"); List<Token> tokens=lexer.getTokens(); for(Token t:tokens) { System.out.print(t); } } }
计算类:
package com.heyang; import java.util.List; public class Evaluator { private List<Token> tokens; private int tokenIdx; public Evaluator(List<Token> tokens) { this.tokens=tokens; this.tokenIdx=0; } public double getResult() throws AnalyzerExp{ return parse_expression(); } private double parse_expression() throws AnalyzerExp{ double left,right; Token currentToken; left=parse_term(); for(;;) { currentToken=fetchToken(); if(currentToken==null) { return left; } if(currentToken.getType()!=Token.TYPE_PLUS && currentToken.getType()!=Token.TYPE_MINUS) { returnToken(); break; } right=parse_term(); if(currentToken.getType()==Token.TYPE_PLUS) { left+= right; }else if(currentToken.getType()==Token.TYPE_MINUS) { left-= right; }else { returnToken(); } } return left; } private double parse_term() throws AnalyzerExp{ double left,right; Token currentToken; left=parse_primary_exp(); for(;;) { currentToken=fetchToken(); if(currentToken==null) { return left; } if(currentToken.getType()!=Token.TYPE_MULTI && currentToken.getType()!=Token.TYPE_DIVIDE) { returnToken(); break; } right=parse_primary_exp(); if(currentToken.getType()==Token.TYPE_MULTI) { left*= right; }else if(currentToken.getType()==Token.TYPE_DIVIDE) { left/= right; } } return left; } private double parse_primary_exp() throws AnalyzerExp{ Token token; double retval=0.0; token=fetchToken(); if(token==null) { return 0; } if(token.getType()==Token.TYPE_DIGITAL) { retval= token.getValue(); return retval; }else if(token.getType()==Token.TYPE_LEFT_PAREN){ retval=parse_expression(); token=fetchToken(); if(token==null) { return retval; } if(token.getType()!=Token.TYPE_RIGHT_PAREN) { throw new AnalyzerExp("missing )"); } return retval; }else { throw new AnalyzerExp(token+" should be a digital."); } } private Token fetchToken() { if(tokenIdx>=tokens.size()) { return null; }else { Token t=tokens.get(tokenIdx); tokenIdx++; return t; } } private void returnToken() { if(tokenIdx>0) { tokenIdx--; } } }
调用:
package com.heyang; import com.heyang.util.BracketChecker; import com.heyang.util.Renderer; public class EntryPoint { public static void main(String[] args) throws Exception{ final String mathExp="(8+9)*7-2*(4+5)"; // brackets is balanced BracketChecker checker=new BracketChecker(); boolean isBalanced=checker.isBalanced(mathExp); if(isBalanced==false) { System.out.println(Renderer.paintBrown(checker.getErrMsg())); return; } // Split expression into tokens Lexer lexer=new Lexer(mathExp); // lexer.printTokenList(); // Evaluate Evaluator evlt=new Evaluator(lexer.getTokens()); System.out.println(mathExp+"="+evlt.getResult()); // TreeBuilder builder=new TreeBuilder(lexer.getTokens()); Node root=builder.getRoot(); TreeOperation.show(root); //root=null; } }
输出:
(8+9)*7-2*(4+5)=101.0 - / * * / / + 7 2 + / / 8 9 4 5
--2020年5月23日--