源码下载:https://files.cnblogs.com/files/heyang78/basicInterpreter102-20200531-2.rar

输入:

for x= to
print(x)
next print("") for y= to
print(y)
next print("程序结束")

输出:

原文=  for x= to      print(x) next  print("")  for y= to      print(y) next  print("程序结束")
Index Type No Text Type Desc
------------------------------------------------------------------------------------
for for
x Variable
= =
Number
to to
Number
print Function
( (
x Variable
) )
next next
print Function
( (
"" String
) )
for for
y Variable
= =
Number
to to
Number
print Function
( (
y Variable
) )
next next
print Function
( (
"程序结束" String
) ) 执行结果: "" "程序结束"

以下是核心类:

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; // >
public static final int TYPE_FOR=12; // For
public static final int TYPE_TO=13; // To
public static final int TYPE_NEXT=14; // Next 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 ">";
}else if(type==TYPE_FOR) {
return "for";
}else if(type==TYPE_TO) {
return "to";
}else if(type==TYPE_NEXT) {
return "next";
} 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("for".equalsIgnoreCase(text)) {
tokens.add(new Token(text, Token.TYPE_FOR));
}else if("to".equalsIgnoreCase(text)) {
tokens.add(new Token(text, Token.TYPE_TO));
}else if("next".equalsIgnoreCase(text)) {
tokens.add(new Token(text, Token.TYPE_NEXT));
}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;
import java.util.Stack; class LoopInfo{
public LoopInfo(String loopValueName,int limit,int startLocation) {
this.loopValueName=loopValueName;
this.limit=limit;
this.startLocation=startLocation;
} String loopValueName;
int limit;
int startLocation;
}
public class Interpreter {
private List<Token> tokens;
private int tokenIdx;
private Map<String,Integer> varmap;
private Stack<LoopInfo> loopStack; public Interpreter(List<Token> tokens) throws Exception{
this.tokens=tokens;
this.tokenIdx=0;
varmap=new HashMap<String,Integer>();
loopStack=new Stack<LoopInfo>(); execute();
} private void execute() throws Exception{ 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();
}
}
else if(token.getType()==Token.TYPE_FOR) {
token=fetchToken();
if(token.getType()!=Token.TYPE_VARIABLE) {
throw new Exception("Expected:variable actual:"+token.getText()+" "+token);
}
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);
} token=fetchToken();
if(token.getType()!=Token.TYPE_TO) {
throw new Exception("Expected:to actual:"+token.getText()+" "+token);
} token=fetchToken();
if(token.getType()!=Token.TYPE_NUMBER) {
throw new Exception("Expected:number actual:"+token.getText()+" "+token);
} int limit=Integer.parseInt(token.getText());
int variableValue=varmap.get(varibleName); if(variableValue<=limit) {
loopStack.push(new LoopInfo(varibleName,limit,tokenIdx));
}else {
fetchToken();
} }
else if(token.getType()==Token.TYPE_NEXT) {
doNext();
}
}
} private void doNext() {
LoopInfo info=loopStack.pop();
int variableValue=varmap.get(info.loopValueName)+1;
varmap.put(info.loopValueName, variableValue); if(variableValue>info.limit) {
//
}else {
loopStack.push(info);
tokenIdx=info.startLocation;
}
} 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--;
}
}
}

入口类:

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\\05.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();
}
}
}

--2020年5月31日--

basicInterpreter1.02 增加对for循环的支持的更多相关文章

  1. MWeb 1.3.7 发布!增加发布到 Wordpress 等支持 MetaWeblog API 的服务,如:Wordpress 博客、新浪博客、cnblogs、oschina。

    MWeb 1.3.7 版的新功能 增加发布到 Wordpress 等支持 Metaweblog API 的服务,目前经测试过的有: Wordpress 博客.新浪博客.cnblogs.oschina. ...

  2. AndroidInject项目使用动态代理增加对网络请求的支持

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3540427.html AndroidInject项目是我写的一 ...

  3. 在内核中增加对yaffs文件系统的支持

    自己最近在搞一些内核以及根文件系统的移植,就涉及到了需要在内核中增加对yaffs文件系统的支持.在网上找了一些文档后,自己将具体的操作过程做了一个总结,方便以后查询使用: 1.获取yaffs源码 YA ...

  4. NGINX 加载动态模块(NGINX 1.9.11开始增加加载动态模块支持)

    NGINX 1.9.11开始增加加载动态模块支持,从此不再需要替换nginx文件即可增加第三方扩展.目前官方只有几个模块支持动态加载,第三方模块需要升级支持才可编译成模块. tinywan@tinyw ...

  5. dubbo/dubbox 增加原生thrift及avro支持

    (facebook) thrift / (hadoop) avro / (google) probuf(grpc)是近几年来比较抢眼的高效序列化/rpc框架,dubbo框架虽然有thrift的支持,但 ...

  6. cocos2d-x编译到android平台后,增加返回键和菜单键支持

    在头文件中增加函数 virtual void keyBackClicked();//android返回键 virtual void keyMenuClicked();//android菜单键 在ini ...

  7. subilme增加对markdown的高亮支持

    sublime2对markdown原生主题支持都没有, 需要通过插件补充 1.插件安装 通过Package Control安装下列插件: Markdown Extended Monokai Exten ...

  8. Touch Punch在移动设备上面增加jQuery UI的触摸支持|Jquery UI 支持移动端 触摸滑动等

    jQuery UI是我们前台开发常用的UI前端类库,但是目前的jQuery UI用户界面类库在互动和widget上并不支持touch事件.这意味着你在桌面上设计的优雅的UI可能在触摸设备,例如,ipa ...

  9. 增加响应header让ajax支持跨域

    ajax请求数据步骤 发送请求--->浏览器接受响应--->判断是否是同域下 是的话,就把响应数据返回给ajax.不是的话就提醒禁止跨域请求. 现在可以在响应头重增加 header(&qu ...

随机推荐

  1. C# BackGroundWorker实现窗体不卡死 进度条功能

    网上的例子少了好多属性的配置,改好了一个能直接用的: using System; using System.Collections.Generic; using System.ComponentMod ...

  2. DB2 分组查询语句ROW_NUMBER() OVER() (转载)

    说起 DB2 在线分析处理,可以用很好很强大来形容.这项功能特别适用于各种统计查询,这些查询用通常的SQL很难实现,或者根本就无发实现.首先,我们从一个简单的例子开始,来一步一步揭开它神秘的面纱,请看 ...

  3. MySQL数据的增删改查查查查查查查查查查查查查查查查(查是真的多)

    一 数据的增加 主要是运用insert  into 语句. 格式: insert  into 表名称 values(数据,数据,数据)(要按顺序来,有没有数据的可以加null) 只增加某些字段里数据的 ...

  4. CF 1383B GameGame

    传送门 题目:给定长度为n的数组a,A和B轮流拿走一个数,开始时A和B拥有的v为0,A和B每次拿走一个数时,他的v = v^ ai,A和B都很聪明,问都按照最优的情况考虑,拿完所有数之后A和B的v的大 ...

  5. 区分多个web driver实例

    固然可以用加载不同cookie的办法,让3个帐号共享一个web driver登陆,但总感觉切换麻烦,干脆用了3个web driver实例.问题来了,如何区分?不是说程序里如何区分,机器比人聪明,知道外 ...

  6. Python 常用的操作文件代码

    1:统计list中相同的个数,并按大小排序. original_list = ['a', 'b', 'b', 'a', 'd', 'd', 'b', 'z', 'c', 'b', 'r', 's', ...

  7. JDK1.8源码学习-Object

    JDK1.8源码学习-Object 目录 一.方法简介 1.一个本地方法,主要作用是将本地方法注册到虚拟机中. private static native void registerNatives() ...

  8. unity探索者之获取设备当前电量

    很多入坑了的小伙伴应该都知道,很多时候做移动端项目都会有显示当前电池电量的需求 对于这个功能,在unity中要做的事并不多,核心方法就一个,自己做一个定时器或者直接使用协程间隔调用该方法就好了 pub ...

  9. Jmeter 常用函数(14)- 详解 __strLen

    如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.htm 作用 读取给定字符串的长度 语法格式 ${__ ...

  10. 记一次因为Gradle与Lombok不兼容导致编译时的内存溢出 Expiring Daemon because JVM heap space is exhausted

    1.现象 版本 Gradel:6.1.1 / 6.5.1 Lombok:1.8.6 / 1.8.10 截图 解决过程 调大idea的堆内存 不行 × idea安装目录中找到 idea64.exe.vm ...