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","\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_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("执行结果:\n"); new Interpreter(lex.getTokenList()); }catch(Exception ex) { System.out.println(Renderer.paintBrown(ex.getMessage())); ex.printStackTrace(); } } }
感慨:在《Java编程艺术》的指引下,解释器的第一步踏出了。
--2020年5月29日--
分类:
Java.Compiler
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)