源码下载: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日--