源码: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"," ")); 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_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日--