源码: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函数的更多相关文章

  1. DeBug Python代码全靠print函数?换用这个一天2K+Star的工具吧,改进版

    pysnooper是代码debug神器,比无限low print好很多和也比日志debug好一些,比断点调试也好一些,这个很犀利的装饰器. https://www.toutiao.com/a66829 ...

  2. Python从菜鸟到高手(8):print函数、赋值与代码块

    1.神奇的print函数   print函数相信读者一定对它不陌生,因为在前面的章节,几乎每个例子都使用了print函数,这个函数的功能就是在控制台输出文本.不过print在输出文本时还可以进行一些设 ...

  3. python的print函数的格式化输出

    使用print函数的时候,可以像C一样格式化输出,同时还支持参数化输出 print('%s' % ("CooMark")) print('整数|%d|' % (123)) prin ...

  4. Python中print函数输出时的左右对齐问题

    为了将print函数输出的内容对齐,笔者在http://www.jb51.net/article/55768.htm中找到了左右对齐的方法.整理如下: 一.数值类型(int.float) #  %d. ...

  5. CentOS 6中MATLAB print函数“所见非所得”bug的解决方案

    0 系统配置+软件版本 主机:Dell optiplex 390 MT (i5) 系统+软件:CentOS 6.5 x64, Matlab R2012, R2013 系统+软件:CentOS 6.7 ...

  6. 一个简化的printf函数

    <C和指针>第7章第5道编程题: 实现一个简化的printf函数,它能够处理%d.%f.%s 和 %c 格式码,根据ANSI标准的原则,其他格式码的行为是未定义的.你可以假定已经存在函数 ...

  7. python中print()函数的“,”与java中System.out.print()函数中的“+”

    python中的print()函数和java中的System.out.print()函数都有着打印字符串的功能. python中: print("hello,world!") 输出 ...

  8. lua的通用print函数

    1.前言 最近在做关于openresty方面的工作,涉及到lua脚本语言,经常需要打日志查看内容.普通的print函数遇到nil或table时,非常无力.而项目中的代码经常遇到参数为nil或table ...

  9. input()和print()函数同时输入输出多个数据--python3

    使用input()和print()函数同时输入输出多个数据,需要空格分割输入信息 #!/usr/bin/python3#-*- conding:utf-8 -*- name, age, QQ = in ...

随机推荐

  1. 了解学习 Javascript, ES5 和 ES6之间的亲密关系

    什么是Javascript JavaScript一种动态类型.弱类型.基于原型的客户端脚本语言,用来给HTML网页增加动态功能.   JavaScript 的标准是 ECMAScript.截至 201 ...

  2. Linux探测工具BCC(可观测性)

    BCC(可观测性) 目录 BCC(可观测性) 简介 动机 版本要求 安装 安装依赖 安装和编译LLVM 安装和编译BCC windows源码查看 BCC的基本使用 工具讲解 execsnoop ope ...

  3. 土题大战Vol.0 A. 笨小猴 思维好题

    土题大战Vol.0 A. 笨小猴 思维好题 题目描述 驴蛋蛋有 \(2n + 1\) 张 \(4\) 星武器卡片,每张卡片上都有两个数字,第 \(i\) 张卡片上的两个数字分别是 \(A_i\) 与 ...

  4. Excel 科学计数法数值转换

    问题场景 如果导出的数据文件后缀为.CSV,一般数值类型的数据超过12位后,单元格的数据就用科学计数法来表示了. 比如身份证号.较长的id,数值会超过12位,而科学计数法表示,不方便查看或操作,很多情 ...

  5. JAVA 读取excel文件成List<Entity>

    package com.fsinfo.common.utils; import com.fsinfo.modules.enterprise.entity.EnterpriseRecordEntity; ...

  6. JavaScript学习系列博客_5_JavaScript中的强制类型转换

    -强制类型转换为String 1.方式1 调用被转换数据的toString()方法 number类型值.布尔类型值.都可以调用toString()方法强制转换.但是null值和undefined值不行 ...

  7. MySQL SQL概述

    MySQL SQL概述 数据库的好处: •实现数据持久化 •使用完整的管理系统统一管理易 数据库的概念: DB:数据库(database):存储数据的“仓库”.它保存了一系列有组织的数据. DBMS: ...

  8. VyOS软路由系统基本设置

    1. VyOS简介 VyOS是一个开源的网络操作系统,可以安装在物理硬件上,也可以安装在你自己的虚拟机上,或者是一个云平台上.它基于GNU/Linux,并加入了多个应用程序,如:Quagga, ISC ...

  9. packmol建模流程-计算

    一.建模流程(modelling procedure): 1.美国数据库下载amc.cif文件:http://rruff.geo.arizona.edu/AMS/amcsd.php 2.导入vesta ...

  10. php 正则表达式匹配(持续更新)

    正则表达式匹配网址: <?php header('Content-type:text/html;charset=utf-8'); $str = ' 百度http://www.baidu.com网 ...