源码下载: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. CSS可见格式化模型

    1.盒模型 1.1 盒子大小 盒模型描述了元素如何显示,以及如何相互作用.相互影响. 页面中的所有元素都被看作一个矩形盒子,这个盒子包含元素的内容.内边距.边框和外边距. 给元素应用的背景会作用于元素 ...

  2. SpringBoot2 整合Ehcache组件,轻量级缓存管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.Ehcache缓存简介 1.基础简介 EhCache是一个纯Java的进程内缓存框架,具有快速.上手简单等特点,是Hibernate中默认 ...

  3. 2020-04-17:说说redis的rdb原理。假设服务器的内存8g,redis父进程占用了6g,子进程fork父进程后,子父进程总共占用内存12g,如何解决内存不足的问题?(挖)

    福哥答案2020-04-18: 这是一道挖坑题.内存占用只会比6g多一点,不会用12g.fork+cow.

  4. C#LeetCode刷题之#933-最近的请求次数(Number of Recent Calls)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4134 访问. 写一个 RecentCounter 类来计算最近的 ...

  5. C#LeetCode刷题之#367-有效的完全平方数(Valid Perfect Square)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3869 访问. 给定一个正整数 num,编写一个函数,如果 num ...

  6. C#LeetCode刷题之#206-反转链表(Reverse Linked List)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3828 访问. 反转一个单链表. 输入: 1->2-> ...

  7. C#LeetCode刷题之#849-到最近的人的最大距离(Maximize Distance to Closest Person)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3754 访问. 在一排座位( seats)中,1 代表有人坐在座位 ...

  8. Hyperledger Fabric介绍

    转载地址 https://blog.csdn.net/xiaonu123/article/details/81006936 简介 Hyperledger介绍 超级账本(Hyperledger)项目是首 ...

  9. oracle中表加锁死锁的现象、原因及解决方案

    一.表加锁.死锁出现的现象 1.对数据库操作update.insert.delete时候,数据库无法更新,操作等待时长,操作结果不发生改变: 2.在程序中,底层(数据访问层)操作时候不成功,数据库连接 ...

  10. Java并发--volatile关键字

    一.volatile的实现原理 synchronized是阻塞式同步,在线程竞争激烈的情况下会升级为重量级锁,而volatile就可以说是JVM提供的最轻量级的同步机制.JMM告诉我们,各个线程会将共 ...