BasicInterpreter1.00 运行简单Basic脚本 打印变量及字符串

源码下载:https://files.cnblogs.com/files/heyang78/basicInterpreter-20200529-1.rar

脚本:

count=10
print(count)
count=20
print(count)
print(cnt)
print("Hello!Interpreter!")

说明:

count=10      赋值语句,变量count赋值为10,变量count不需定义
print(count)   打印变量count里的值
count=20      赋值语句,变量count赋值为20
print(count)  打印变量count里的值
print(cnt)    打印变量cnt里的值
print("Hello!Interpreter!") 打印字符串"Hello!Interpreter!"

执行结果:

原文=count=10 print(count) count=20 print(count) print(cnt) print("Hello!Interpreter!") 
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                    6                    count                Variable             
8                    2                    =                    =                    
9                    4                    20                   Number               
10                   7                    print                Function             
11                   0                    (                    (                    
12                   6                    count                Variable             
13                   1                    )                    )                    
14                   7                    print                Function             
15                   0                    (                    (                    
16                   6                    cnt                  Variable             
17                   1                    )                    )                    
18                   7                    print                Function             
19                   0                    (                    (                    
20                   5                    "Hello!Interpreter!" String               
21                   1                    )                    )                    

执行结果:

10
20
Variable:'cnt' was not assigned.
"Hello!Interpreter!"

核心程序:

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_EQUAL=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
    
    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_EQUAL) {
            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";
        }
        
        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 jsonTxt) {
        tokens = new ArrayList<Token>();

        String swallowed = "";
        for (int i = 0; i < jsonTxt.length(); i++) {
            char c = jsonTxt.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_EQUAL));
            } else if(c == '"') {
                addTextToList(swallowed);
                swallowed="";
                
                int idx=i+1;
                
                while(idx<jsonTxt.length()) {
                    char cEnd = jsonTxt.charAt(idx);
                    
                    if (cEnd == '"') {
                        break;
                    }
                    
                    idx++;
                }
                
                String sub=jsonTxt.substring(i, idx+1);
                tokens.add(new Token(sub, Token.TYPE_STRING));
                i=idx;
            } else {
                swallowed += c;
            }
        }
        
        setTokenIndexes();
    }
    
    private void addTextToList(String text) {
        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;

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_EQUAL) {
                    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.");
                        }
                    }
                }
            }
        }
    }
    
    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\01.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();
        }
    }
}

感慨:在《Java编程艺术》的指引下,解释器的第一步踏出了。

--2020年5月29日--

原文地址:https://www.cnblogs.com/heyang78/p/12988230.html