basicInterpreter1.01 支持分支语句

源码:https://files.cnblogs.com/files/heyang78/basicInterpreter-20200531-1.rar

输入:

count=10
print(count)
if count==10 then print("count等于10")
if count<20 then print("count小于20")
if count>5 then print("count大于5")
print("程序结束")

输出:

原文=count=10 print(count) if count==10 then print("count等于10") if count<20 then print("count小于20") if count>5 then print("count大于5") print("程序结束") 
Index                Type No              Text                 Type Desc            
------------------------------------------------------------------------------------
0                    6                    count                Variable             
1                    2                    =                    =                    
2                    4                    10                   Number               
3                    7                    print                Function             
4                    0                    (                    (                    
5                    6                    count                Variable             
6                    1                    )                    )                    
7                    9                    if                   if                   
8                    6                    count                Variable             
9                    8                    ==                   ==                   
10                   4                    10                   Number               
11                   10                   then                 then                 
12                   7                    print                Function             
13                   0                    (                    (                    
14                   5                    "count等于10"          String               
15                   1                    )                    )                    
16                   9                    if                   if                   
17                   6                    count                Variable             
18                   10                   <                    then                 
19                   4                    20                   Number               
20                   10                   then                 then                 
21                   7                    print                Function             
22                   0                    (                    (                    
23                   5                    "count小于20"          String               
24                   1                    )                    )                    
25                   9                    if                   if                   
26                   6                    count                Variable             
27                   11                   >                    >                    
28                   4                    5                    Number               
29                   10                   then                 then                 
30                   7                    print                Function             
31                   0                    (                    (                    
32                   5                    "count大于5"           String               
33                   1                    )                    )                    
34                   7                    print                Function             
35                   0                    (                    (                    
36                   5                    "程序结束"               String               
37                   1                    )                    )                    

执行结果:

10
"count等于10"
"count小于20"
"count大于5"
"程序结束"

核心代码:

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;                // >
    
    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 ">";
        }
        
        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(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","\n"));
        sb.append(continuousStar + "\n");
        int index=0;
        for(Token token:tokens) {
            sb.append(String.format(layout, String.valueOf(index),String.valueOf(token.getType()), token.getText(),token.getTypeStr(),"\n"));
            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;

public class Interpreter {
    private List<Token> tokens;
    private int tokenIdx;
    
    public Interpreter(List<Token> tokens) throws Exception{
        this.tokens=tokens;
        this.tokenIdx=0;
        
        execute();
    }
    
    private void execute() throws Exception{
        Map<String,Integer> varmap=new HashMap<String,Integer>();
        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();        
                }
            }
        }
    }
    
    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--;
        }
    }
}

--2020年5月31日--

posted @ 2020-05-31 10:01  逆火狂飙  阅读(161)  评论(1编辑  收藏  举报
生当作人杰 死亦为鬼雄 至今思项羽 不肯过江东