源码: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. 数电学习笔记之CMOS传输门工作原理

    CMOS 传输门从结构上看是由一个PMOS和一个NMOS管组成 先简单粗略讲讲PMOS管和NMOS管导通与截止吧 首先我们MOS管有三个极,源极(S:Source).漏极(D:Drain)和栅极(G: ...

  2. CSS高级特效(下)

    3.混合模式与合成 在图形编辑软件(比如Photoshop)中,设计师很早就可以选择两个设计元素叠加时的颜色如何混合了. CSS Compositing and Blending标准使我们可以在CSS ...

  3. 16、Mediator 仲裁者模式

    只有一个仲裁者 Mediator 模式 组员向仲裁者报告,仲裁者向组员下达指示,组员之间不在相互询问和相互指示. 要调整多个对象之间的关系时,就需要用到 Mediator 模式.将逻辑处理交给仲裁者执 ...

  4. 史上最简单操作!!!!!!!Window Server2012 修改远程桌面端口号

    Window Server2012 修改远程桌面端口号   Win + R 输入 regedit 打开注册表编辑器 在注册表编辑器中找到 PortNumber 双击 PortNumber,选择10进制 ...

  5. C/C++中char[]和string的连接/合并

    一: C风格字符串连接 #include <iostream> using namespace std; int main() { const char *str = "hell ...

  6. Java爬取先知论坛文章

    Java爬取先知论坛文章 0x00 前言 上篇文章写了部分爬虫代码,这里给出一个完整的爬取先知论坛文章代码. 0x01 代码实现 pom.xml加入依赖: <dependencies> & ...

  7. 理解正向代理&反向代理

    通常的代理服务器,只用于代理内部网络对Internet的连接请求,客户机必须指定代理服务器,并将本来要直接发送到Web服务器上的http请求发送到代理服务器中.由于外部网络上的主机并不会配置并使用这个 ...

  8. Open vSwitch with DPDK

    http://docs.openvswitch.org/en/latest/intro/install/dpdk/

  9. web渗透测试之sqlmap拿到数据库信息

    通过扫描我们发现目标网站存在sql注入漏洞,我们访问该里面后发现该网站里面有个表格提交参数.确实存在没有过滤 使用sqlmap扫描发现漏洞的确存在,这里是布尔盲注 查看当前数据库名 查看表名得到以下信 ...

  10. Webstorm的常用快捷键

    编辑 Ctrl + Space 基本代码完成 (任何类. 方法或变量名称) Ctrl + Shift + Enter 完整的语句 Ctrl + P (在方法调用参数) 内的参数信息 Ctrl + Q ...