<编译原理 - 函数绘图语言解释器(3)解释器 - python>

背景

  • 编译原理上机实现一个对函数绘图语言的解释器 - 用除C外的不同种语言实现

  • 设计思路:

    • 将语法分析器并入绘图功能

    • 继承语法分析器覆盖重写

  • 用Pycharm写了一个.py文件:

    • semanticfunc.py

    • 输入流是语法分析器得到的语法树,输出流是绘制的图像

    • 测试文本序列:

//----------------测试程序1:分别测试------------------------
ORIGIN IS (100,300); // Sets the offset of the origin
ROT IS 0; // Set rotation Angle.
SCALE IS (1,1); // Set the abscissa and ordinate scale.
FOR T FROM 0 TO 200 STEP 1 DRAW (T,0); // The trajectory of the x-coordinate.
FOR T FROM 0 TO 150 STEP 1 DRAW (0,-T); // The trajectory of the y-coordinate.
FOR T FROM 0 TO 120 STEP 1 DRAW (T,-T); // The trajectory of the function f[t]=t.
FOR T FROM 0 TO 2*PI STEP PI/50 DRAW(COS(T),SIN(T));
//---------测试程序2----------
ORIGIN IS (20, 200);
ROT IS 0;
SCALE IS (40, 40);
FOR T FROM 0 TO 2*PI STEP PI/50 DRAW (T, -SIN(T));
ORIGIN IS (20, 240);
FOR T FROM 0 TO 2*PI STEP PI/50 DRAW (T, -SIN(T));
ORIGIN IS (20, 280);
FOR T FROM 0 TO 2*PI STEP PI/50 DRAW (T, -SIN(T));
//-----------------测试程序3--------------
ORIGIN IS (380, 240);
SCALE IS (80, 80/3);
ROT IS PI/2+0*PI/3 ;
FOR T FROM -PI TO PI STEP PI/50 DRAW (COS(T), SIN(T));
ROT IS PI/2+2*PI/3;
FOR T FROM -PI TO PI STEP PI/50 DRAW (COS(T), SIN(T));
ROT IS PI/2-2*PI/3;
FOR T FROM -PI TO PI STEP PI/50 DRAW (COS(T), SIN(T));
//-------------------测试程序4-------------
ORIGIN IS(580, 240);
SCALE IS (80, 80);
ROT IS 0;
FOR T FROM 0 TO 2*PI STEP PI/50 DRAW(COS(T),SIN(T));
FOR T FROM 0 TO PI*20 STEP PI/50 DRAW((1-1/(10/7))*COS(T)+1/(10/7)*COS(-T*((10/7)-1)),(1-1/(10/7))*SIN(T)+1/(10/7)*SIN(-T*((10/7)-1)));
//-------------------测试程序5------------
//------------ 函数复杂度图形:-----------
ROT IS 0; -- 不旋转
ORIGIN IS (50, 400); -- 设置新原点(距系统默认原点的偏移量)
SCALE IS (2,1); -- 设置比例
FOR T FROM 0 TO 300 STEP 1 DRAW (T,0); -- 横坐标
FOR T FROM 0 TO 300 STEP 1 DRAW (0,-T); -- 纵坐标
SCALE IS (2,1); -- 设置比例
FOR T FROM 0 TO 300 STEP 1 DRAW (T,-T); -- 函数F(T)=T的轨迹
SCALE IS (2,0.1); -- 设置比例
FOR T FROM 0 TO 55 STEP 1 DRAW (T,-T*T); -- 函数F(T)=T*T的轨迹
SCALE IS (10,5); -- 设置比例
FOR T FROM 0 TO 60 STEP 1 DRAW (T,-SQRT(T)); -- 函数F(T)=SQRT(T)的轨迹
SCALE IS (20,0.1); -- 设置比例
FOR T FROM 0 TO 8 STEP 0.1 DRAW (T,-EXP(T)); -- 函数F(T)=EXP(T)的轨迹
SCALE IS (2,20); -- 设置比例
FOR T FROM 0 TO 300 STEP 1 DRAW (T,-LN(T)); -- 函数F(T)=LN(T)的轨迹

Step 1 :semanticfunc.py - 继承语法分析器并入绘制功能

#!/usr/bin/env python
# encoding: utf-8
'''
@author: 黄龙士
@license: (C) Copyright 2019-2021,China.
@contact: iym070010@163.com
@software: xxxxxxx
@file: semanticfunc.py.py
@time: 2019/11/30 10:47
@desc:
''' import parserfunc as pf
import scannerclass as sc
import numpy as np
import turtle
import sys
import matplotlib
import matplotlib.pyplot as plt class semantic(pf.Parsef):
def initPaint(self): # 初始化画布
self.fig = plt.figure()
self.ax = self.fig.add_subplot(111) def Errmsg(self): #出错处理
sys.exit(1) def CalcCoord(self,x,y): # 计算点坐标 即比例旋转平移变换 x,y都是二元组
x = x * self.Scale_x
y = y * self.Scale_y ## 进行比例变换
tmp_x = x * np.cos(self.Rot_angle) + y * np.sin(self.Rot_angle)
y = y * np.cos(self.Rot_angle) - x * np.sin(self.Rot_angle)
x= tmp_x ## 旋转变换
x = x + self.Origin_x
y = y + self.Origin_y ## 进行平移变换
return x,y def DrawLoop(self):
x,y = self.CalcCoord(self.x_ptr,self.y_ptr)
self.ax.scatter(x,y) def Statement(self): ## 重写statement ,让每次ForStatement执行完毕后画图
self.enter("Statement")
if self.token.type == sc.Token_Type.ORIGIN:
self.OriginStatement()
elif self.token.type == sc.Token_Type.SCALE:
self.ScaleStatement()
elif self.token.type == sc.Token_Type.ROT:
self.RotStatement()
elif self.token.type == sc.Token_Type.FOR:
self.ForStatement()
self.DrawLoop()
# elif self.token.type == sc.Token_Type.CONST_ID or self.token.type == sc.Token_Type.L_BRACKET or \
# self.Expression()
else: self.SyntaxError(2)
self.back("Statement") # 绘图语言解释器入口(与主程序的外部接口)
def Parser(self): # 语法分析器的入口
self.enter("Parser")
if (self.scanner.fp == None): # 初始化词法分析器
print("Open Source File Error !\n")
else:
self.FetchToken() # 获取第一个记号
self.Program() # 递归下降分析
plt.show()
self.scanner.CloseScanner() # 关闭词法分析器
self.back("Parser")

Step 2 :semanticmain.py - 解释器主函数入口

#!/usr/bin/env python
# encoding: utf-8
'''
@author: 黄龙士
@license: (C) Copyright 2019-2021,China.
@contact: iym070010@163.com
@software: xxxxxxx
@file: parsermain.py
@time: 2019/11/26 22:31
@desc:
''' import scannerfunc as sf
# import parserfunc as pf
import semanticfunc as paint
import os file_name = 'test.txt'
scanner = sf.scanner(file_name)
semantic = paint.semantic(scanner)
semantic.initPaint()
semantic.Parser()
# parser = pf.Parsef(scanner)
# parser.Parser() # os.system("pause")

实现结果

  • 对于测试程序(1):

  • 对于测试程序(2):

  • 对于测试程序(3):

  • 对于测试程序(4):

  • 对于测试程序(5):

<编译原理 - 函数绘图语言解释器(3)解释器 - python>的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. CDate()函数

    CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant. CDate(date) date 参数是任意有效的日期表达式. 说明 IsDate 函数用于判断 date 是否 ...

  2. Codeforces Round #567 (Div. 2)B. Split a Number (字符串,贪心)

    B. Split a Number time limit per test2 seconds memory limit per test512 megabytes inputstandard inpu ...

  3. Tensorflow 多gpu训练

    Tensorflow可在训练时制定占用那几个gpu,但如果想真正的使用多gpu训练,则需要手动去实现. 不知道tf2会不会改善一下. 具体参考:https://wizardforcel.gitbook ...

  4. 前端错误监控上报公共方法,可在父页面及iframe子页面同时使用

    先创建公共文件error-reported.js 内容如下: /** * 获取前端错误信息进行上报 * @param iframe */ function catchError (iframe) { ...

  5. AGC009题解

    为了1天4题的flag不倒所以开新坑... B. 考虑把这棵树直接建出来,f[i]表示i最少的比赛次数,然后按照定义转移就行了. //Love and Freedom. #include<cst ...

  6. 36.React基础介绍——2019年12月24日

    2019年12月24日16:47:12 2019年10月25日11:24:29 主要介绍react入门知识. 1.jsx语法介绍 1.1 介绍 jsx语法是一种类似于html标签的语法,它的作用相当于 ...

  7. Python 序列化 pickle/cPickle模块

    Python 序列化 pickle/cPickle模块 2013-10-17 Posted by yeho Python序列化的概念很简单.内存里面有一个数据结构,你希望将它保存下来,重用,或者发送给 ...

  8. java web中乱码的种类和一些解决方式

    在java web课堂测试中遇到了一些乱码问题 ,从百度上找到了许多种解决方法和乱码的种类,在这里总结一下. 一.文件出现乱码 [右击文件]->[Properties]->[Resourc ...

  9. IDEA创建SpringBoot,并实现、运行简单实例

    1.打开IDEA,点击 +Create New Project. 开始创建一个新项目. 2.在左侧菜单找到并点击 Spring Initializr,点击next.注意,这里idea默认使用https ...

  10. extjs计算两个DateField所间隔的月份(天数)

    需求:两个DateField控件,分别为开始时间和结束时间.当选择完结束时间后,自动计算这两个时间段所间隔的月或天数. 需要解决的问题: 1.直接使用Ext.getCmp('endDate').get ...