源码下载: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页面布局与网格(下)

    3.二维布局:CSS Grid Layout CSS Grid Layout模块为了能在二维空间里控制元素的顺序.位置和大小而定义了一组CSS属性. 被设值为display: grid的元素叫网格容器 ...

  2. 网络协议: TCP/IP 和UDP/IP

    网络协议: TCP/IP 和UDP/IP TCP/IP TCP/IP(Transmission Control Protocol/Internet Protocol)是一种可靠的网络数据传输控制协议. ...

  3. Python 错误 异常

    8 错误,调试和测试 8.1错误处理 所有的异常来自 BaseException 记录错误 : # err_logging.py import logging def foo(s): return 1 ...

  4. sftp与ftp的区别

    SFTP和FTP非常相似,都支持批量传输(一次传输多个文件),文件夹/目录导航,文件移动,文件夹/目录创建,文件删除等.但还是存在着差异,下面我们来看看SFTP和FTP之间的区别. 1. 安全通道FT ...

  5. C#LeetCode刷题之#387-字符串中的第一个唯一字符(First Unique Character in a String)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3939 访问. 给定一个字符串,找到它的第一个不重复的字符,并返回 ...

  6. Vue 生成条形码 jsbarcode的使用

    安装依赖包 npm install jsbarcode --save 在使用页面引入依赖包 import JsBarcode from 'jsbarcode' 定义img标签和id <img i ...

  7. 面试官:怎么做JDK8的垃圾收集器的调优?

    面试官:怎么做JDK8的垃圾收集器的调优? 看着面试官真诚的眼神,心中暗想看起来年纪轻轻却提出如此直击灵魂的问题.擦了擦额头上汗,我稍微调整了一下紧张的情绪,对面试官说: 在JDK8中有Serial收 ...

  8. Java中的注解及自定义注解你用的怎么样,能不能像我这样应用自如?

    Java注解提供了关于代码的一些信息,但并不直接作用于它所注解的代码内容.在这个教程当中,我们将学习Java的注解,如何定制注解,注解的使用以及如何通过反射解析注解. Java1.5引入了注解,当前许 ...

  9. 【HDU3038】How Many Answers Are Wrong - 带权并查集

    描述 TT and FF are ... friends. Uh... very very good friends -________-b FF is a bad boy, he is always ...

  10. 使用 codeblocks 编写C++ udp组播程序遇到的问题

    编译错误 会出现好多undefined reference to'WSAStartup to@8之类的错误,都是undefind开头的 解决方法: Settings -> Compiler se ...