• basicInterpreter1.02 增加对for循环的支持


    源码下载:https://files.cnblogs.com/files/heyang78/basicInterpreter102-20200531-2.rar

    输入:

    for x=1 to 10
        print(x)
    next
    
    print("")
    
    for y=10 to 20
        print(y)
    next
    
    print("程序结束")

    输出:

    原文=  for x=1 to 10     print(x) next  print("")  for y=10 to 20     print(y) next  print("程序结束") 
    Index                Type No              Text                 Type Desc            
    ------------------------------------------------------------------------------------
    0                    12                   for                  for                  
    1                    6                    x                    Variable             
    2                    2                    =                    =                    
    3                    4                    1                    Number               
    4                    13                   to                   to                   
    5                    4                    10                   Number               
    6                    7                    print                Function             
    7                    0                    (                    (                    
    8                    6                    x                    Variable             
    9                    1                    )                    )                    
    10                   14                   next                 next                 
    11                   7                    print                Function             
    12                   0                    (                    (                    
    13                   5                    ""                   String               
    14                   1                    )                    )                    
    15                   12                   for                  for                  
    16                   6                    y                    Variable             
    17                   2                    =                    =                    
    18                   4                    10                   Number               
    19                   13                   to                   to                   
    20                   4                    20                   Number               
    21                   7                    print                Function             
    22                   0                    (                    (                    
    23                   6                    y                    Variable             
    24                   1                    )                    )                    
    25                   14                   next                 next                 
    26                   7                    print                Function             
    27                   0                    (                    (                    
    28                   5                    "程序结束"               String               
    29                   1                    )                    )                    
    
    执行结果:
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ""
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    "程序结束"

    以下是核心类:

    Token类:

    package com.heyang;
    
    public class Token {
        public static final int TYPE_OPEN_PARENTHESIS=0;        // (
        public static final int TYPE_CLOSE_PARENTHESIS=1;        // (
        public static final int TYPE_ASSIGN=2;                    // =
        public static final int TYPE_NUMBER=4;                    // d+
        public static final int TYPE_STRING=5;                    // w+
        public static final int TYPE_VARIABLE=6;                // Variable
        public static final int TYPE_FUNCTION=7;                // Function
        public static final int TYPE_EQUAL=8;                    // ==
        public static final int TYPE_IF=9;                        // if
        public static final int TYPE_THEN=10;                    // then
        public static final int TYPE_LESSTHAN=10;                // <
        public static final int TYPE_BIGGERTHAN=11;                // >
        public static final int TYPE_FOR=12;                    // For
        public static final int TYPE_TO=13;                        // To
        public static final int TYPE_NEXT=14;                    // Next
        
        private int type;
        private String text;
        private int index;// Used to remember location
        
        public Token(char c,int type) {
            this.text=String.valueOf(c);
            this.type=type;
        }
        
        public Token(String word,int type) {
            this.text=word;
            this.type=type;
        }
        
        public String toString() {
            return String.format("token(text=%s,type=%s,index=%d)", text,getTypeStr(),index);
        }
        
        public String getTypeStr() {
            if(type==TYPE_OPEN_PARENTHESIS) {
                return "(";
            }else if(type==TYPE_CLOSE_PARENTHESIS) {
                return ")";
            }else if(type==TYPE_ASSIGN) {
                return "=";
            }else if(type==TYPE_NUMBER) {
                return "Number";
            }else if(type==TYPE_STRING) {
                return "String";
            }else if(type==TYPE_VARIABLE) {
                return "Variable";
            }else if(type==TYPE_FUNCTION) {
                return "Function";
            }else if(type==TYPE_EQUAL) {
                return "==";
            }else if(type==TYPE_IF) {
                return "if";
            }else if(type==TYPE_THEN) {
                return "then";
            }else if(type==TYPE_LESSTHAN) {
                return "<";
            }else if(type==TYPE_BIGGERTHAN) {
                return ">";
            }else if(type==TYPE_FOR) {
                return "for";
            }else if(type==TYPE_TO) {
                return "to";
            }else if(type==TYPE_NEXT) {
                return "next";
            }
            
            return null;
        }
    
        public int getType() {
            return type;
        }
    
        public void setType(int type) {
            this.type = type;
        }
    
        public String getText() {
            return text;
        }
    
        public void setText(String text) {
            this.text = text;
        }
    
        public int getIndex() {
            return index;
        }
    
        public void setIndex(int index) {
            this.index = index;
        }
    }

    Lexer类:

    package com.heyang;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.regex.Pattern;
    
    /**
     * Parse json string to tokens
     * @author Heyang
     *
     */
    public class Lexer {
        private List<Token> tokens;
    
        public Lexer(String text) {
            tokens = new ArrayList<Token>();
    
            String swallowed = "";
            for (int i = 0; i < text.length(); i++) {
                char c = text.charAt(i);
    
                if (Character.isWhitespace(c)) {
                    addTextToList(swallowed);
                    swallowed="";
                    continue;
                } else if (c == '(') {
                    addTextToList(swallowed);
                    swallowed="";
                    
                    tokens.add(new Token(c, Token.TYPE_OPEN_PARENTHESIS));
                } else if (c == ')') {
                    addTextToList(swallowed);
                    swallowed="";
                    
                    tokens.add(new Token(c, Token.TYPE_CLOSE_PARENTHESIS));
                }else if (c == '>') {
                    addTextToList(swallowed);
                    swallowed="";
                    
                    tokens.add(new Token(c, Token.TYPE_BIGGERTHAN));
                }else if (c == '<') {
                    addTextToList(swallowed);
                    swallowed="";
                    
                    tokens.add(new Token(c, Token.TYPE_LESSTHAN));
                } else if (c == '=') {
                    int next=i+1;
                    if(next<text.length() && text.charAt(next)=='=') {
                        // ==
                        addTextToList(swallowed);
                        swallowed="";
                        tokens.add(new Token("==",Token.TYPE_EQUAL));
                        i++;
                    }else {
                        // =
                        addTextToList(swallowed);
                        swallowed="";
                        tokens.add(new Token(c, Token.TYPE_ASSIGN));
                    }
                } else if(c == '"') {
                    addTextToList(swallowed);
                    swallowed="";
                    
                    int idx=i+1;
                    
                    while(idx<text.length()) {
                        char cEnd = text.charAt(idx);
                        
                        if (cEnd == '"') {
                            break;
                        }
                        
                        idx++;
                    }
                    
                    String sub=text.substring(i, idx+1);
                    tokens.add(new Token(sub, Token.TYPE_STRING));
                    i=idx;
                } else {
                    swallowed += c;
                }
            }
            
            setTokenIndexes();
        }
        
        private void addTextToList(String text) {
            if("if".equalsIgnoreCase(text)) {
                tokens.add(new Token(text, Token.TYPE_IF));
            }else if("then".equalsIgnoreCase(text)) {
                tokens.add(new Token(text, Token.TYPE_THEN));
            }else if("for".equalsIgnoreCase(text)) {
                tokens.add(new Token(text, Token.TYPE_FOR));
            }else if("to".equalsIgnoreCase(text)) {
                tokens.add(new Token(text, Token.TYPE_TO));
            }else if("next".equalsIgnoreCase(text)) {
                tokens.add(new Token(text, Token.TYPE_NEXT));
            }else if(isFunction(text)) {
                tokens.add(new Token(text, Token.TYPE_FUNCTION));
            }else if(isNumber(text)) {
                tokens.add(new Token(text, Token.TYPE_NUMBER));
            }else if(isVarable(text)) {
                tokens.add(new Token(text, Token.TYPE_VARIABLE));
            } 
        }
        
        private boolean isFunction(String text) {
            if("print".equalsIgnoreCase(text)) {
                return true;
            }
            
            return false;
        }
        
        private boolean isNumber(String code) {
            final String patternStr = "\d+";
            return Pattern.matches(patternStr, code);
        }
        
        private boolean isVarable(String code) {
            final String patternStr = "([a-zA-Z_])\w*";
            return Pattern.matches(patternStr, code);
        }
        
        public void printTokens() {
            final String continuousStar = createRepeatedStr("-", 84);
            final String layout = "%-20s %-20s %-20s %-20s %s";
            StringBuilder sb = new StringBuilder();
    
            sb.append(String.format(layout, "Index", "Type No","Text","Type Desc","
    "));
            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());
        }
        
        private static String createRepeatedStr(String seed, int n) {
            return String.join("", Collections.nCopies(n, seed));
        }
    
        public void setTokenIndexes() {
            int idx = 0;
            for (Token t : tokens) {
                idx++;
                t.setIndex(idx);
            }
        }
        
        public String getCompactJsonTxt() {
            StringBuilder sb=new StringBuilder();
            
            for (Token t : tokens) {
                sb.append(t.getText());
            }
            
            return sb.toString();
        }
        
        public List<Token> getTokenList() {
            return tokens;
        }
    }

    Interpreter类:

    package com.heyang;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Stack;
    
    class LoopInfo{
        public LoopInfo(String loopValueName,int limit,int startLocation) {
            this.loopValueName=loopValueName;
            this.limit=limit;
            this.startLocation=startLocation;
        }
        
        String loopValueName;
        int limit;
        int startLocation;
    }
    public class Interpreter {
        private List<Token> tokens;
        private int tokenIdx;
        private Map<String,Integer> varmap;
        private Stack<LoopInfo> loopStack;
        
        public Interpreter(List<Token> tokens) throws Exception{
            this.tokens=tokens;
            this.tokenIdx=0;
            varmap=new HashMap<String,Integer>();
            loopStack=new Stack<LoopInfo>();
            
            execute();
        }
        
        private void execute() throws Exception{
            
            Token token;
            for(;;) {
                token=fetchToken();
                if(token==null) {
                    return;
                }
                
                if(token.getType()==Token.TYPE_VARIABLE) {
                    String varibleName=token.getText();
                    
                    token=fetchToken();
                    if(token.getType()==Token.TYPE_ASSIGN) {
                        token=fetchToken();
                        
                        if(token.getType()==Token.TYPE_NUMBER) {
                            int variableValue=Integer.parseInt(token.getText());
                            
                            // 赋值核心语句
                            varmap.put(varibleName, variableValue);
                        }
                    }else {
                        throw new Exception("Expected:'=' actual:"+token.getText()+" "+token);
                    }
                }else if(token.getType()==Token.TYPE_FUNCTION) {
                    String functionName=token.getText();
                    
                    if("print".equalsIgnoreCase(functionName)) {
                        token=fetchToken();
                        if(token.getType()!=Token.TYPE_OPEN_PARENTHESIS) {
                            throw new Exception("Expected:'(' actual:"+token.getText()+" "+token);
                        }
                        
                        token=fetchToken();
                        if(token.getType()==Token.TYPE_STRING) {
                            // 打印字符串
                            String str=token.getText();
                            System.out.println(str);
                        }else if(token.getType()==Token.TYPE_VARIABLE) {
                            String varibleName=token.getText();
                            
                            // 打印变量
                            if(varmap.containsKey(varibleName)) {
                                int value=varmap.get(varibleName);
                                System.out.println(value);
                            }else {
                                System.out.println("Variable:'"+varibleName+"' was not assigned.");
                            }
                        }
                    }
                }else if(token.getType()==Token.TYPE_IF) {
                    int vLeft,vRight;
                    String oprand;
                    
                    // get left value
                    token=fetchToken();                
                    if(token.getType()==Token.TYPE_VARIABLE) {
                        String varibleName=token.getText();
                        
                        if(varmap.containsKey(varibleName)) {
                            vLeft=varmap.get(varibleName);
                        }else {
                            throw new Exception("Variable:'"+varibleName+"' was not assigned.");
                        }
                    }else if(token.getType()==Token.TYPE_NUMBER) {
                        vLeft=Integer.parseInt(token.getText());
                    }else {
                        throw new Exception("Expected:number/variable actual:"+token.getText()+" "+token);
                    }
                    
                    // get ==,<,>
                    token=fetchToken();                
                    if(token.getType()!=Token.TYPE_EQUAL && token.getType()!=Token.TYPE_LESSTHAN && token.getType()!=Token.TYPE_BIGGERTHAN) {
                        throw new Exception("Expected:'== or > or <' actual:"+token.getText()+" "+token);
                    }
                    oprand=token.getText();
                    
                    // get right
                    token=fetchToken();                
                    if(token.getType()==Token.TYPE_VARIABLE) {
                        String varibleName=token.getText();
                        
                        if(varmap.containsKey(varibleName)) {
                            vRight=varmap.get(varibleName);
                        }else {
                            throw new Exception("Variable:'"+varibleName+"' was not assigned.");
                        }
                    }else if(token.getType()==Token.TYPE_NUMBER) {
                        vRight=Integer.parseInt(token.getText());
                    }else {
                        throw new Exception("Expected:number/variable actual:"+token.getText()+" "+token);
                    }
                    
                    // Compare
                    if(compare(vLeft,oprand,vRight)) {
                        // get then
                        token=fetchToken();                
                        if(token.getType()!=Token.TYPE_THEN) {
                            throw new Exception("Expected:'then' actual:"+token.getText()+" "+token);
                        }
                    }else {
                        // 跳过两个token(then及后面的dosth)
                        fetchToken();        
                        fetchToken();        
                    }
                }
                else if(token.getType()==Token.TYPE_FOR) {
                    token=fetchToken();
                    if(token.getType()!=Token.TYPE_VARIABLE) {
                        throw new Exception("Expected:variable actual:"+token.getText()+" "+token);
                    }
                    String varibleName=token.getText();
                    
                    token=fetchToken();
                    if(token.getType()==Token.TYPE_ASSIGN) {
                        token=fetchToken();
                        
                        if(token.getType()==Token.TYPE_NUMBER) {
                            int variableValue=Integer.parseInt(token.getText());
                            
                            // 赋值核心语句
                            varmap.put(varibleName, variableValue);
                        }
                    }else {
                        throw new Exception("Expected:'=' actual:"+token.getText()+" "+token);
                    }
                    
                    token=fetchToken();
                    if(token.getType()!=Token.TYPE_TO) {
                        throw new Exception("Expected:to actual:"+token.getText()+" "+token);
                    }
                    
                    token=fetchToken();
                    if(token.getType()!=Token.TYPE_NUMBER) {
                        throw new Exception("Expected:number actual:"+token.getText()+" "+token);
                    }
                    
                    int limit=Integer.parseInt(token.getText());
                    int variableValue=varmap.get(varibleName);
                    
                    if(variableValue<=limit) {
                        loopStack.push(new LoopInfo(varibleName,limit,tokenIdx));
                    }else {
                        fetchToken();
                    }
    
                }
                else if(token.getType()==Token.TYPE_NEXT) {
                    doNext();
                }
            }
        }
                
        private void doNext() {
            LoopInfo info=loopStack.pop();
            int variableValue=varmap.get(info.loopValueName)+1;
            varmap.put(info.loopValueName, variableValue);
            
            if(variableValue>info.limit) {
                //
            }else {
                loopStack.push(info);
                tokenIdx=info.startLocation;
            }
        }
        
        private boolean compare(int vLeft,String oprand,int vRight) throws Exception{
            if("==".equals(oprand)) {
                return vLeft==vRight;
            }else if(">".equals(oprand)) {
                return vLeft>vRight;
            }else if("<".equals(oprand)) {
                return vLeft<vRight;
            }else {
                throw new Exception("oprand should be == or > or < but not.");
            }
        }
        
        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.CommonUtil;
    import com.heyang.util.Renderer;
    
    public class EntryPoint {
        public static void main(String[] args) {
            try {
                // Read context from file
                String text=CommonUtil.readTextFromFile("C:\hy\files\basic\05.basic");
                System.out.println("原文="+text);
                
                // Is brackets balanced
                BracketChecker checker=new BracketChecker();
                boolean isBalanced=checker.isBalanced(text);
                if(isBalanced==false) {
                    System.out.println(Renderer.paintBrown(checker.getErrMsg()));
                    return;
                }
                
                // lex text to tokens
                Lexer lex=new Lexer(text);
                lex.printTokens();
                
                // Execute
                System.out.println("执行结果:
    ");
                new Interpreter(lex.getTokenList());
            }catch(Exception ex) {
                System.out.println(Renderer.paintBrown(ex.getMessage()));
                ex.printStackTrace();
            }
        }
    }

    --2020年5月31日--

  • 相关阅读:
    向MySql中插入中文时出现乱码
    MySql插入记录时判断
    SuperGridControl 使用小技巧
    Winform开发中常见界面的DevExpress处理操作
    mysql优化之索引建立的规则
    App性能优化浅谈
    AndroidManifest具体解释之Application(有图更好懂)
    算法——递归思想解决排列组合问题
    Windows App开发之集合控件与数据绑定
    table行随鼠标变色
  • 原文地址:https://www.cnblogs.com/heyang78/p/13021451.html
Copyright © 2020-2023  润新知