• 递归向下解析算术表达式(二)


    本文代码下载: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日--

  • 相关阅读:
    Nodejs中的流
    Openstack Havana的两个排错过程
    Mongoose入门
    Promise
    CSS3中的动画
    MySql学习笔记(一)--安装配置
    应用Dubbo框架打造仿猫眼项目(二) 影片模块开发
    应用Dubbo框架打造仿猫眼项目(一) 用户模块开发
    4种事务的隔离级别
    JAVA面试题解惑系列(一)——类的初始化顺序
  • 原文地址:https://www.cnblogs.com/heyang78/p/12942420.html
Copyright © 2020-2023  润新知