parse_expression,parse_term,parse_primary_exp三函数间的递归调用是核心所在.
标记类:
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; } }
分词器类:
package com.heyang; import java.util.ArrayList; 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=='+'){ addDigital2Tokens(swallowed); swallowed=""; tokens.add(new Token(c,Token.TYPE_PLUS)); }else if(c=='-'){ addDigital2Tokens(swallowed); swallowed=""; tokens.add(new Token(c,Token.TYPE_MINUS)); }else if(c=='*'){ addDigital2Tokens(swallowed); swallowed=""; tokens.add(new Token(c,Token.TYPE_MULTI)); }else if(c=='/'){ addDigital2Tokens(swallowed); swallowed=""; tokens.add(new Token(c,Token.TYPE_DIVIDE)); }else if(c=='('){ addDigital2Tokens(swallowed); swallowed=""; tokens.add(new Token(c,Token.TYPE_LEFT_PAREN)); }else if(c==')'){ addDigital2Tokens(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 addDigital2Tokens(String text) throws AnalyzerExp{ if(text.trim().length()>0) { tokens.add(new Token(text,Token.TYPE_DIGITAL)); } } 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 index; public Evaluator(List<Token> tokens) { this.tokens=tokens; index=0; } public double evaluate() throws AnalyzerExp{ return parse_expression(); } private double parse_expression() throws AnalyzerExp{ double left,right; Token currentToken; left=parse_term(); for(;;) { if(index==tokens.size()) { return left; }else { currentToken=tokens.get(index); index++; } if(currentToken.getType()!=Token.TYPE_PLUS && currentToken.getType()!=Token.TYPE_MINUS) { index--; break; } right=parse_term(); if(currentToken.getType()==Token.TYPE_PLUS) { left+= right; }else if(currentToken.getType()==Token.TYPE_MINUS) { left-= right; }else { index--; } } return left; } private double parse_term() throws AnalyzerExp{ double left,right; Token currentToken; left=parse_primary_exp(); for(;;) { if(index==tokens.size()) { return left; }else { currentToken=tokens.get(index); index++; } if(currentToken.getType()!=Token.TYPE_MULTI && currentToken.getType()!=Token.TYPE_DIVIDE) { index--; 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; if(index==tokens.size()) { return retval; }else { token=tokens.get(index); index++; } if(token.getType()==Token.TYPE_DIGITAL) { retval= token.getValue(); return retval; }else if(token.getType()==Token.TYPE_LEFT_PAREN){ retval=parse_expression(); if(index==tokens.size()) { return retval; }else { token=tokens.get(index); index++; } if(token.getType()!=Token.TYPE_RIGHT_PAREN) { throw new AnalyzerExp("missing )"); } return retval; }else { throw new AnalyzerExp(token+" should be a digital."); } } public static void main(String[] args) throws Exception{ String exp="1+(2*3-4)*5-6"; System.out.println("exp="+exp); Lexer lexer=new Lexer(exp); Evaluator e=new Evaluator(lexer.getTokens()); System.out.println(e.evaluate()); } }
代码下载:
https://files.cnblogs.com/files/heyang78/mathexpAnalyzer20200522-1.zip
参考资料:
前桥和弥著<自制编程语言>
--2020年5月22日-