源码: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. 1、迭代器 Iterator模式 一个一个遍历 行为型设计模式

    1.Iterator模式 迭代器(iterator)有时又称游标(cursor)是程序设计的软件设计模式,可在容器(container,例如链表或者阵列)上遍访的接口,设计人员无需关心容器的内容. I ...

  2. Java泛型是什么?实战demo

    1. 概述 泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用. 什么是泛型?为什么要使用泛型? 泛型,即“参数化类型”.一提到参数,最熟悉的就是定义方法时有形参,然后调用 ...

  3. 微信商户H5支付申请不通过被驳回,拒绝原因提示:网站存在不实内容或不安全信息

    一.H5支付简介及使用场景说明 H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付.主要用于触屏版的手机浏览器请求微信支付 ...

  4. 使用JSPWiki丰富Unity-UPM包的使用

    1.简述 诸如npm.Nuget之类的包管理工具,Unity推出了自己的Unity Package Manager(UPM)工具来管理使用到的第三方库. 现在Unity Package Manager ...

  5. 用 cgo 生成用于 cgo 的 C 兼容的结构体

    假设(并非完全假设,这里有 demo)你正在编写一个程序包,用于连接 Go 和其它一些提供大量 C 结构体内存的程序.这些结构可能是系统调用的结果,也可能是一个库给你提供的纯粹信息性内容.无论哪种情况 ...

  6. 2020-04-06:为什么HashMap不一直使用红黑树?

    红黑树的阈值是8,当链表大于等于8时链表变成了红黑树结构,大大减少了查找的时间. 当长度低于6时会由红黑树转成链表,TreeNodes占用空间是普通Nodes的两倍,所以只有当bin包含足够多的节点时 ...

  7. 使用Spring Boot开发者工具进行自动重启和页面自动刷新

    简介 大家可能都听说过开发Node.js应用时可以使用多种工具对开发者提供便利,如WebPack提供了开发者服务器来支持js应用动态更替,并在保存文件时自动刷新浏览器.Spring Boot也提供了相 ...

  8. python3 - 常用的操作数据库

    # 获取手机号数据表的中的数据 sql2 = 'SELECT shoujihao FROM shoujihao' self.cursor.execute(sql2) sjh_dates = self. ...

  9. JAVA HTML 以压缩包下载多文件

    Html:  利用form表单来发送下载请求 <form id ="submitForm" method="post"> </form> ...

  10. Banner信息收集

    一.什么是Banner Banner信息,欢迎语,在banner信息中可以得到软件开发商,软件名称.版本.服务类型等信息,通过这些信息可以使用某些工具直接去使用相对应的exp去攻击. 前提条件:需要和 ...