BasicInterpreter2 改进版,简化了print函数
源码:https://files.cnblogs.com/files/heyang78/BasicInterpreter2-20200601-3.rar
改进后使得变量和字符串可以一起输出了。
输入脚本:
for x= to
for y= to x
z=x*y
print(y+"*"+x+"="+z+" ")
next newline()
next print("end")
输出:
原文=for x= to for y= to x z=x*y print(y+"*"+x+"="+z+" ") next newline() next print("end")
Tokens:
执行结果: *=
*= *=
*= *= *=
*= *= *= *=
*= *= *= *= *=
*= *= *= *= *= *=
*= *= *= *= *= *= *=
*= *= *= *= *= *= *= *=
*= *= *= *= *= *= *= *= *=
end
改进后的InterPreter类:
package com.heyang; import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack; // 保存循环变量名,极限和for语句下首句起始位置的类
class LoopInfo{
public LoopInfo(String loopValueName,double limit,int startLocation) {
this.loopValueName=loopValueName;
this.limit=limit;
this.startLocation=startLocation;
} String loopValueName;
double limit;
int startLocation;
} // 解释器类
public class InterPreter {
private List<Token> tokens;
private int tokenIdx;
private Map<String,Double> varMap;// 用于存放变量的变量表
private Stack<LoopInfo> loopStack;// 用于存放循环的栈 // 构造函数
public InterPreter(List<Token> tokens){
this.tokens=tokens;
this.tokenIdx=0;
varMap=new HashMap<String,Double>();
loopStack=new Stack<LoopInfo>();
} // 执行程序
public void execute() throws Exception{
Token token;
for(;;) {
token=fetchToken();
if(token==null) {
return;
} if(token.getType()==Token.TYPE_VARIABLE) {
returnToken();
doAssignment();
}else if(token.getType()==Token.TYPE_FUNCTION) {
String fname=token.getText(); if("print".equalsIgnoreCase(fname)) {
doPrint();
}if("newline".equalsIgnoreCase(fname)) {
doNewline();
}
}else if(token.getType()==Token.TYPE_IF) {
returnToken();
doIf();
}else if(token.getType()==Token.TYPE_ELSE) {
doElse();
}else if(token.getType()==Token.TYPE_FOR) {
doFor();
}else if(token.getType()==Token.TYPE_NEXT) {
doNext();
}
}
} // Next语句处理
private void doNext() throws Exception{
LoopInfo info=loopStack.pop();
String varName=info.loopValueName;
Double value=loadVariable(varName);
if(value==null) {
throw new Exception("Not found variable:'"+varName);
} double variableValue=value+1;
saveVariable(info.loopValueName, variableValue); if(variableValue>info.limit) {
//
}else {
loopStack.push(info);
tokenIdx=info.startLocation;
}
} // For循环
private void doFor() throws Exception{
Token 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_DIGITAL) {
double value=Double.parseDouble(token.getText());
saveVariable(varibleName, value);
}
}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);
} double limit;
token=fetchToken();
if(token.getType()==Token.TYPE_DIGITAL) {
limit=Double.parseDouble(token.getText());
}else if(token.getType()==Token.TYPE_VARIABLE) {
String varName=token.getText();
Double value=loadVariable(varName);
if(value==null) {
throw new Exception("Not found variable:'"+varName+" token:"+token);
} limit=value;
}else {
throw new Exception("Expected:digital/variable actual:"+token.getText()+" "+token);
} double variableValue=loadVariable(varibleName); if(variableValue<=limit) {
loopStack.push(new LoopInfo(varibleName,limit,tokenIdx));
}else {
fetchToken();
}
} // Else语句处理
private void doElse() throws Exception{
// 走到这里说明是if的肯定分支,因此需要跳过去
Token token;
do {
token=fetchToken();
}while(token.getType()!=Token.TYPE_ENDIF) ;
} // If语句处理
private void doIf() throws Exception{
Token token=fetchToken();
if(token.getType()!=Token.TYPE_IF) {
throw new Exception("Expected:if actual:"+token.getText()+" "+token);
} double left;
token=fetchToken();
if(token.getType()==Token.TYPE_DIGITAL) {
left=Double.parseDouble(token.getText());
}else if(token.getType()==Token.TYPE_VARIABLE) {
String varName=token.getText();
Double value=loadVariable(varName);
if(value==null) {
throw new Exception("Not found variable:'"+varName+" token:"+token);
} left=value;
}else {
throw new Exception("Expected:digital/variable actual:"+token.getText()+" "+token);
} String oprand;
token=fetchToken();
if(token.getType()!=Token.TYPE_EQUAL &&
token.getType()!=Token.TYPE_LESSTHAN &&
token.getType()!=Token.TYPE_LESSEUQALTHAN &&
token.getType()!=Token.TYPE_BIGGERTHAN &&
token.getType()!=Token.TYPE_BIGGEREQUALTHAN
) {
throw new Exception("Expected:comparison symbol, actual:"+token.getText()+" "+token);
}
oprand=token.getText(); double right;
token=fetchToken();
if(token.getType()==Token.TYPE_DIGITAL) {
right=Double.parseDouble(token.getText());
}else if(token.getType()==Token.TYPE_VARIABLE) {
String varName=token.getText();
Double value=loadVariable(varName);
if(value==null) {
throw new Exception("Not found variable:'"+varName+" token:"+token);
} right=value;
}else {
throw new Exception("Expected:digital/variable actual:"+token.getText()+" "+token);
} if(compare(left,oprand,right)) {
token=fetchToken();
if(token.getType()!=Token.TYPE_THEN) {
throw new Exception("Expected:'then' actual:"+token.getText()+" "+token);
}
}else {
do {
token=fetchToken();
}while(token.getType()!=Token.TYPE_ENDIF && token.getType()!=Token.TYPE_ELSE) ;
}
} // 左右比较
private boolean compare(double vLeft,String oprand,double vRight){
if("==".equals(oprand)) {
return vLeft==vRight;
}else if(">".equals(oprand)) {
return vLeft>vRight;
}else if(">=".equals(oprand)) {
return vLeft>=vRight;
}else if("<".equals(oprand)) {
return vLeft<vRight;
}else if("<=".equals(oprand)) {
return vLeft<=vRight;
}else {
return false;
}
} // 打印新行
private void doNewline() throws Exception{
Token token=fetchToken();
if(token.getType()!=Token.TYPE_OPEN_PARENTHESIS) {
throw new Exception("Expected:'(' actual:"+token.getText()+" "+token);
} System.out.println(); token=fetchToken();
if(token.getType()!=Token.TYPE_CLOSE_PARENTHESIS) {
throw new Exception("Expected:')' actual:"+token.getText()+" "+token);
}
} // 打印
private void doPrint() throws Exception{
Token token=fetchToken();
if(token.getType()!=Token.TYPE_OPEN_PARENTHESIS) {
throw new Exception("Expected:'(' actual:"+token.getText()+" "+token);
} do {
token=fetchToken(); if(token.getType()==Token.TYPE_VARIABLE) {
String varName=token.getText();
Double value=loadVariable(varName);
if(value==null) {
throw new Exception("Not found variable:'"+varName+" token:"+token);
} try {
int i=value.intValue();
System.out.print(i);
}catch(Exception ex) {
System.out.print(value);
}
}else if(token.getType()==Token.TYPE_STRING){
String str=token.getText();
if(str.startsWith("\"") && str.endsWith("\"") ) {
System.out.print(str.substring(1, str.length()-1));
}else {
System.out.print(str);
}
}else if(token.getType()==Token.TYPE_PLUS) {
// do nothing
}else {
break;
}
}while(token.getType()!=Token.TYPE_CLOSE_PARENTHESIS); if(token.getType()!=Token.TYPE_CLOSE_PARENTHESIS) {
throw new Exception("Expected:')' actual:"+token.getText()+" "+token);
}
} // 赋值
private void doAssignment() throws Exception{
Token token=fetchToken();
if(token.getType()!=Token.TYPE_VARIABLE) {
throw new Exception("Expected:variable actual:"+token.getText()+" "+token);
}
String varName=token.getText(); token=fetchToken();
if(token.getType()!=Token.TYPE_ASSIGN) {
throw new Exception("Expected:= actual:"+token.getText()+" "+token);
} double varValue=parse_expression();
saveVariable(varName,varValue);
} // 解析表达式
private double parse_expression() throws Exception{
double left,right;
Token currentToken; left=parse_term();
for(;;) {
currentToken=fetchToken();
if(currentToken==null) {
return left;
} if(currentToken.getType()!=Token.TYPE_PLUS && currentToken.getType()!=Token.TYPE_MINUS) {
returnToken();
break;
} right=parse_term(); if(currentToken.getType()==Token.TYPE_PLUS) {
left+= right;
}else if(currentToken.getType()==Token.TYPE_MINUS) {
left-= right;
}else {
returnToken();
}
} return left;
} // 解析乘除
private double parse_term() throws Exception{
double left,right;
Token currentToken; left=parse_primary_exp();
for(;;) {
currentToken=fetchToken();
if(currentToken==null) {
return left;
} if(currentToken.getType()!=Token.TYPE_MULTI && currentToken.getType()!=Token.TYPE_DIVIDE) {
returnToken();
break;
} right=parse_primary_exp(); if(currentToken.getType()==Token.TYPE_MULTI) {
left*= right;
}else if(currentToken.getType()==Token.TYPE_DIVIDE) {
left/= right;
}
} return left;
} // 解析数字/变量/表达式
private double parse_primary_exp() throws Exception{
Token token;
double retval=0.0; token=fetchToken();
if(token==null) {
return 0;
} if(token.getType()==Token.TYPE_DIGITAL) {
retval= Double.parseDouble(token.getText());
return retval;
}else if(token.getType()==Token.TYPE_VARIABLE) {
String varName=token.getText();
Double d=loadVariable(varName);
if(d==null) {
throw new Exception("Not found variable:'"+varName+" token:"+token);
} return d;
}else if(token.getType()==Token.TYPE_OPEN_PARENTHESIS){
retval=parse_expression(); token=fetchToken();
if(token==null) {
return retval;
} if(token.getType()!=Token.TYPE_CLOSE_PARENTHESIS) {
throw new Exception("missing )");
} return retval;
}else {
throw new Exception(token+" should be a digital.");
}
} // 取标记
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--;
}
} // 保存变量进变量表
private void saveVariable(String name,double value) {
varMap.put(name, value);
} // 取得变量值从变量表
private Double loadVariable(String name) {
if(varMap.containsKey(name)) {
return varMap.get(name);
}else {
return null;
}
}
}
--2020年6月1日--
BasicInterpreter2 改进版,简化了print函数的更多相关文章
- DeBug Python代码全靠print函数?换用这个一天2K+Star的工具吧,改进版
pysnooper是代码debug神器,比无限low print好很多和也比日志debug好一些,比断点调试也好一些,这个很犀利的装饰器. https://www.toutiao.com/a66829 ...
- Python从菜鸟到高手(8):print函数、赋值与代码块
1.神奇的print函数 print函数相信读者一定对它不陌生,因为在前面的章节,几乎每个例子都使用了print函数,这个函数的功能就是在控制台输出文本.不过print在输出文本时还可以进行一些设 ...
- python的print函数的格式化输出
使用print函数的时候,可以像C一样格式化输出,同时还支持参数化输出 print('%s' % ("CooMark")) print('整数|%d|' % (123)) prin ...
- Python中print函数输出时的左右对齐问题
为了将print函数输出的内容对齐,笔者在http://www.jb51.net/article/55768.htm中找到了左右对齐的方法.整理如下: 一.数值类型(int.float) # %d. ...
- CentOS 6中MATLAB print函数“所见非所得”bug的解决方案
0 系统配置+软件版本 主机:Dell optiplex 390 MT (i5) 系统+软件:CentOS 6.5 x64, Matlab R2012, R2013 系统+软件:CentOS 6.7 ...
- 一个简化的printf函数
<C和指针>第7章第5道编程题: 实现一个简化的printf函数,它能够处理%d.%f.%s 和 %c 格式码,根据ANSI标准的原则,其他格式码的行为是未定义的.你可以假定已经存在函数 ...
- python中print()函数的“,”与java中System.out.print()函数中的“+”
python中的print()函数和java中的System.out.print()函数都有着打印字符串的功能. python中: print("hello,world!") 输出 ...
- lua的通用print函数
1.前言 最近在做关于openresty方面的工作,涉及到lua脚本语言,经常需要打日志查看内容.普通的print函数遇到nil或table时,非常无力.而项目中的代码经常遇到参数为nil或table ...
- input()和print()函数同时输入输出多个数据--python3
使用input()和print()函数同时输入输出多个数据,需要空格分割输入信息 #!/usr/bin/python3#-*- conding:utf-8 -*- name, age, QQ = in ...
随机推荐
- 在龙芯mips64el平台编译bmon
bmon 是一个 实时命令行流量监控软件,但作者在github并没有提供mips64el的版本.下面记录一下编译过程.可以在这里下载bmon.v4.0.linux-mips64el.tar.gz. 环 ...
- java_字节流、字符流的使用方法
字节流 字节输出流[OutputStream] java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地.它定义了字节输出流的基本共性功能方法. p ...
- 云原生数据库mysql对共享存储分布式文件系统的接口需求分析
1. 引言 云原生数据库跟分布式mpp数据库是有差异的,虽然两者都是计算与存储分离,但是在资源的占用上有所不同.云原生数据库是shard everything架构,其依赖的存储资源.内存资源.事务资源 ...
- 2020-05-08:mycat部署数据库集群的时候 遇到了哪些坑
福哥答案2020-05-08:答案仅供参考,来自群员 使用activity时,连接mycat设置进去的序列化的流程变量,反序列化会报错这个类型字段类型是blob类型,mycat对这种类型处理时有点问题
- My_Tomcat_Host 靶机
1:扫描网段: 发现主机IP为192.168.1.203 2:nmap 扫描端口信息 发现8080端口开启了http服务 22ssh服务 3:尝试ssh连接是需要密码的,然后访问8080端口 4:发 ...
- 【Spring注解驱动开发】如何实现方法、构造器位置的自动装配?我这样回答让面试官很满意!
在 冰河技术 微信公众号前面的文章中,我们介绍了如何使用注解来自动装配Spring组件.之前将的都是在来的字段上添加注解,那有没有什么方法可以实现方法.构造器位置的自动装配吗?今天我们就一起来探讨下如 ...
- Android 禁止ViewPager左右滑动的功能实现
来来来,各位看官~ Look here!!! Android 禁止ViewPager左右滑动的功能实现!! I think it`s so easy,无需重写ViewPager!!! JUST ...
- dispatch_next()方法的实现
之前的文章介绍到,在generate_normal_entry()函数中会调用generate_fixed_frame()函数为Java方法的执行生成对应的栈帧,接下来还会调用dispatch_nex ...
- 如何校验内存数据的一致性,DynamicExpresso 算是帮上大忙了
一:背景 1. 讲故事 记的在上一家公司做全内存项目的时候,因为一些关键表会在程序 startup 的时候全量灌入到内存中,但随着时间的推移,内存和数据库的同步偶尔会出现数据差异的情况,伴随着就是运营 ...
- Macbook pro 下修改MySQL数据库密码
步骤: 1. 打开终端 Terminal, 找到Mysql 的安装路径,一般默认安装路径为:/usr/local/mysql-5.7.12-osx10.11-x86_64/bin [注:我安装的Mys ...