├── Interpreter4FPL
├── .idea
│ ├── .name
│ ├── encodings.xml
│ ├── vcs.xml
│ ├── modules.xml
│ ├── misc.xml
│ ├── Interpreter4FPL.iml
│ └── workspace.xml
├── __pycache__
│ ├── expnode.cpython-35.pyc
│ ├── mylexer.cpython-35.pyc
│ ├── mypainter.cpython-35.pyc
│ └── myparser.cpython-35.pyc
├── main.py
├── expnode.py
├── mypainter.py
├── mylexer.py
└── myparser.py
├── test&pic
├── 五环.png
├── GUI.png
├── test0.jpg
├── 几何标志.png
├── 0testOK.png
├── NewGUI.png
├── test1.txt
├── 摆线&螺线
│ ├── 等角螺线.txt
│ ├── 外摆线.txt
│ ├── 内摆线.txt
│ ├── 长幅圆外旋轮线.txt
│ └── 心形螺线.txt
├── 奥运五环.txt
├── 0testOK.txt
├── test2.txt
├── 几何标志.txt
└── test0.txt
├── docs
├── 函数绘图语言解释器.ppt
├── 编译原理 随课实验报告封面.docx
└── 编译原理实验(绘图语言解释器)讲义.ppt
├── version2
├── GUI.png
├── 0testOK.png
├── 0testOK.txt
├── README.md
├── main.py
├── mypainter.py
├── expnode.py
├── mylexer.py
└── myparser.py
├── .idea
├── encodings.xml
├── vcs.xml
├── modules.xml
├── misc.xml
├── Interpreter.iml
└── workspace.xml
├── version1
├── README.md
├── t.py
├── test.py
├── grammer.py
├── Lexical.py
├── parser.py
└── expression.py
├── version4
├── README.md
├── main.py
├── expnode.py
├── mypainter.py
├── mylexer.py
└── myparser.py
├── version3
├── README.md
├── main.py
├── mypainter.py
├── expnode.py
├── mylexer.py
└── myparser.py
└── README.md
/Interpreter4FPL/.idea/.name:
--------------------------------------------------------------------------------
1 | Interpreter4FPL
--------------------------------------------------------------------------------
/test&pic/五环.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/test&pic/五环.png
--------------------------------------------------------------------------------
/docs/函数绘图语言解释器.ppt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/docs/函数绘图语言解释器.ppt
--------------------------------------------------------------------------------
/test&pic/GUI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/test&pic/GUI.png
--------------------------------------------------------------------------------
/test&pic/test0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/test&pic/test0.jpg
--------------------------------------------------------------------------------
/test&pic/几何标志.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/test&pic/几何标志.png
--------------------------------------------------------------------------------
/version2/GUI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/version2/GUI.png
--------------------------------------------------------------------------------
/test&pic/0testOK.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/test&pic/0testOK.png
--------------------------------------------------------------------------------
/test&pic/NewGUI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/test&pic/NewGUI.png
--------------------------------------------------------------------------------
/version2/0testOK.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/version2/0testOK.png
--------------------------------------------------------------------------------
/docs/编译原理 随课实验报告封面.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/docs/编译原理 随课实验报告封面.docx
--------------------------------------------------------------------------------
/docs/编译原理实验(绘图语言解释器)讲义.ppt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/docs/编译原理实验(绘图语言解释器)讲义.ppt
--------------------------------------------------------------------------------
/test&pic/test1.txt:
--------------------------------------------------------------------------------
1 | for t from 1 to 100 step 0.1 draw(1+sin(sqrt(2*3**2*2)-5*t)-sin(t), cos(t*24-e**sqrt(pi)));
--------------------------------------------------------------------------------
/Interpreter4FPL/__pycache__/expnode.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/Interpreter4FPL/__pycache__/expnode.cpython-35.pyc
--------------------------------------------------------------------------------
/Interpreter4FPL/__pycache__/mylexer.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/Interpreter4FPL/__pycache__/mylexer.cpython-35.pyc
--------------------------------------------------------------------------------
/Interpreter4FPL/__pycache__/mypainter.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/Interpreter4FPL/__pycache__/mypainter.cpython-35.pyc
--------------------------------------------------------------------------------
/Interpreter4FPL/__pycache__/myparser.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/izcat/Interpreter4FPL/HEAD/Interpreter4FPL/__pycache__/myparser.cpython-35.pyc
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Interpreter4FPL/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/test&pic/摆线&螺线/等角螺线.txt:
--------------------------------------------------------------------------------
1 | //origin is (0, 35);
2 | --SCALE is ( 40,40);
3 | // 等角螺线 / 对数螺线
4 | // r = a*e**(b*t)
5 | for t from 0 to 6*pi step 0.01 draw (e**(0.2*t)*cos(t), e**(0.2*t)*sin(t));
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/test&pic/摆线&螺线/外摆线.txt:
--------------------------------------------------------------------------------
1 | // 外摆线
2 | // x=(a+b)cosθ-bcos[(a+b)θ/b]
3 | // y=(a+b)sinθ-bsin[(a+b)θ/b]
4 | // 当a/b是有理数时,它是闭曲线
5 | for t from 0 to 10*pi step 0.01 draw (11*cos(t)-5*cos(11/5*t), 11*sin(t)-5*sin(11/5*t));
6 |
--------------------------------------------------------------------------------
/test&pic/摆线&螺线/内摆线.txt:
--------------------------------------------------------------------------------
1 | // 旋轮线(内摆线)
2 | // X=(a-b)cosθ+bcos[(a-b)θ/b]
3 | // Y=(a-b)sinθ-bsin[(a-b)θ/b]
4 | // 当a/b是有理数时,它是闭曲线
5 | for t from 0 to 4*pi step 0.01 draw (11*cos(t)-5*cos(11/5*t), 11*sin(t)-5*sin(11/5*t));
6 |
--------------------------------------------------------------------------------
/test&pic/摆线&螺线/长幅圆外旋轮线.txt:
--------------------------------------------------------------------------------
1 | for t from 0 to 10*pi step 0.01 draw (8*cos(t)-5*cos(8/3*t), 8*sin(t)-5*sin(8/3*t)) of red;
2 |
3 | for t from 0 to 10*pi step 0.01 draw (11*cos(t)-6*cos(11/5*t), 11*sin(t)-6*sin(11/5*t)) of red;
--------------------------------------------------------------------------------
/Interpreter4FPL/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/version1/README.md:
--------------------------------------------------------------------------------
1 | # Version 1
2 | 完成词法分析
3 |
4 | ## 词法分析器功能
5 | - 输入:函数绘图语言源程序,以字符串形式传递给 `Lexer` 参数
6 | - 输出:返回源程序进行词法分析得到的全部 Token,类型为列表
7 |
8 | ## Update:
9 | 此版本 `Lexer` 会无法正确识别带小数点的浮点数!在version2中的 `Lexer` 才是正确写法!
10 |
--------------------------------------------------------------------------------
/version1/t.py:
--------------------------------------------------------------------------------
1 | Points = dict(X=[], Y=[])
2 | print(Points)
3 | print(Points['X'])
4 |
5 | a = 100
6 |
7 | def test1():
8 | # print(a)
9 | a = 1
10 |
11 | def test2():
12 | a = 2
13 |
14 | test2()
15 | print(a)
16 | test1()
17 | print(a)
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Interpreter4FPL/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Interpreter4FPL/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/version4/README.md:
--------------------------------------------------------------------------------
1 | # Version 4
2 |
3 | 改进内容:
4 | - 在version3的基础上,分离语法分析器 `myparser` 模块与语义分析器 `mypainter` 模块
5 | - 重新设计了语法分析过程中的运行提示,增加了层级level参数,使递归调用的输出信息更友好
6 | - 重写了 `mypainter` 模块,改用面向对象方式
7 | - `Painter` 类 接收绘图源程序代码,调用语法分析器 `myparser.Parser`
8 | - 将获取到的语法树交给 `analyse` 方法进行语义分析
9 | - 语义分析完成后,`showPic` 执行绘图
10 | - 改进 `main` 程序入口模块,增加了打开文件选项,可以直接选择写好绘图源程序打开
11 |
--------------------------------------------------------------------------------
/test&pic/奥运五环.txt:
--------------------------------------------------------------------------------
1 | origin is (0, 35);
2 | SCALE is ( 40,40);
3 | for t from 0 to 2*pi step 0.01 draw (sin(t), cos(t));
4 | for t from 0 to 2*pi step 0.01 draw (-2.2+sin(t), cos(t)) of blue;
5 | for t from 0 to 2*pi step 0.01 draw (2.2+sin(t), cos(t)) of Red;
6 | for t from 0 to 2*pi step 0.01 draw (-1.1+sin(t), -1.1+cos(t)) of YELLOW;
7 | for t from 0 to 2*pi step 0.01 draw (1.1+sin(t), -1.1+cos(t)) of GREEN;
--------------------------------------------------------------------------------
/test&pic/0testOK.txt:
--------------------------------------------------------------------------------
1 | ORigin is (-30, 0);
2 | SCALE is ( 20, 25);
3 | for t from 0 to 2*pi step 0.01 draw (sin(t), cos(t));
4 |
5 | SCALE is ( 30, 20);
6 | for t from -1 to 1 step 0.01 draw (2, t);
7 | FOR t from 0 to 1 step 0.01 draw (2+t, t);
8 | for t from -1 to 1 step 0.01 draw (2, t);
9 | FOR t from 0 to 1 step 0.01 draw (2+t, -t);
10 |
11 | for t from 0 to 2*pi step 0.01 draw (1+3*sin(t), 3*cos(t));
12 |
--------------------------------------------------------------------------------
/version2/0testOK.txt:
--------------------------------------------------------------------------------
1 | ORigin is (-30, 0);
2 | SCALE is ( 20, 25);
3 | for t from 0 to 2*pi step 0.01 draw (sin(t), cos(t));
4 |
5 | SCALE is ( 30, 20);
6 | for t from -1 to 1 step 0.01 draw (2, t);
7 | FOR t from 0 to 1 step 0.01 draw (2+t, t);
8 | for t from -1 to 1 step 0.01 draw (2, t);
9 | FOR t from 0 to 1 step 0.01 draw (2+t, -t);
10 |
11 | for t from 0 to 2*pi step 0.01 draw (1+3*sin(t), 3*cos(t));
12 |
--------------------------------------------------------------------------------
/version2/README.md:
--------------------------------------------------------------------------------
1 | # Version 2
2 | 已实现实验要求的函数绘图语言的全部功能
3 |
4 | 解释器执行的第一个程序结果(显示 'OK' 字样):
5 |
6 | 
7 |
8 |
9 |
10 | ## 修复Bug
11 | 由于新加入主界面的模块 `main.py` 无法正常 import 写好的 `parser`模块,因为会与 Python 的同名库冲突。
12 | 将全部模块改名,加上'my'前缀
13 | ## 不足
14 | 词法分析器与语义分析器没有完全分离,本解释器在语法分析阶段,未生成源代码的整体语法树,直接将绘制的点信息交给painter处理
15 | 缺少异常处理机制
16 | 没有完全面向对象开发
17 |
18 |
--------------------------------------------------------------------------------
/Interpreter4FPL/.idea/Interpreter4FPL.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/test&pic/test2.txt:
--------------------------------------------------------------------------------
1 |
2 | ROT IS -pi/2;
3 | for t from 0 to pi step 0.001 draw (t*cos(t), t*sin(t)) of red;
4 | for t from 0 to pi step 0.001 draw (t*cos(t), -t*sin(t));
5 |
6 | ROT IS -pi/2+pi/12;
7 | for t from 0 to pi step 0.001 draw (t*cos(t), t*sin(t)) of yellow;
8 | for t from 0 to pi step 0.001 draw (t*cos(t), -t*sin(t));
9 |
10 | ROT IS -pi/2-pi/12;
11 | for t from 0 to pi step 0.001 draw (t*cos(t), t*sin(t)) of yellow;
12 | for t from 0 to pi step 0.001 draw (t*cos(t), -t*sin(t));
13 |
--------------------------------------------------------------------------------
/.idea/Interpreter.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/test&pic/摆线&螺线/心形螺线.txt:
--------------------------------------------------------------------------------
1 | // 阿基米德螺线
2 | // r = a + b*t
3 | ROT IS 0;
4 | for t from pi/2 to 3/2*pi step 0.001 draw (t*cos(t), t*sin(t)) of blue;
5 | for t from pi/2 to 3/2*pi step 0.001 draw (-t*cos(t), t*sin(t));
6 |
7 | ROT IS -pi/2;
8 | for t from 0 to pi step 0.001 draw (t*cos(t), t*sin(t)) of yellow;
9 | for t from 0 to pi step 0.001 draw (t*cos(t), -t*sin(t));
10 |
11 | // 费马螺线
12 | // r = a*sqrt(t)
13 | ROT IS -pi/2;
14 | for t from 0 to pi step 0.001 draw (2*sqrt(t)*cos(t), 2*sqrt(t)*sin(t)) of red;
15 | for t from 0 to pi step 0.001 draw (2*sqrt(t)*cos(t), -2*sqrt(t)*sin(t));
16 |
17 |
--------------------------------------------------------------------------------
/version1/test.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 |
3 | class TokenType(Enum):
4 | ORIGIN = "ORIGIN"
5 | SCALE = "SCALE"
6 | ROT = "ROT"
7 | IS = "IS"
8 | TO = "TO"
9 | STEP = "STEP"
10 | DRAW = "DRAW"
11 | FOR = "FOR"
12 | FROM = "FROM"
13 | T = "T"
14 | SEMICO = ';'
15 | L_BRACKET = '('
16 | R_BRACKET = ')'
17 | COMMA = ','
18 | PLUS = '+'
19 | MINUS = '-'
20 | MUL = '*'
21 | DIV = '/'
22 | POWER = '**'
23 | FUNC = "FUNCTION"
24 | CONST_ID = "CONST_ID"
25 | NONTOKEN = 22
26 | ERRTOKEN = 23
27 |
28 | print(TokenType)
--------------------------------------------------------------------------------
/version3/README.md:
--------------------------------------------------------------------------------
1 | # Version 3
2 |
3 | 本次版本不涉及代码修复和功能修改,version2可以正常运行标准绘图源程序
4 |
5 | 在完成作业要求的基础上,本次更新增加了**自定义颜色**的语法
6 | 即
7 | **FOR T FROM T_start TO T_end STEP T_step DRAW (Point_x, Point_Y)**
8 | **[OF (RED|GREEN|BLUE|YELLOW|BLACK)]**
9 |
10 | 更改内容如下
11 | - `mylexer` 模块新增记号类别 `TokenType` : **OF**,**RED**,**GREEN**,**BLUE**,**YELLOW**, **BLACK**
12 | - `mylexer` 模块新增字符与记号的字典映射 `TokenTypeDict` :
13 | - OF = Token(TokenType.OF, "OF")
14 | - RED = Token(TokenType.COLOR, "RED")
15 | - GREEN = Token(TokenType.COLOR, "GREEN")
16 | - BLUE = Token(TokenType.COLOR, "BLUE")
17 | - YELLOW = Token(TokenType.COLOR, "YELLOW")
18 | - BLACK = Token(TokenType.COLOR, "BLACK")
19 | - `myparser` 模块作少量改动,`ForStatement` 方法新增颜色识别语句,将获取颜色结果传给 `Painter`
20 | - `mypainter` 模块内的 `paint` 方法
21 | - plt.plot(Painter.Points['X'], Painter.Points['Y'], '.'+Draw_color)
22 | - 参考自 https://blog.csdn.net/qiurisiyu2016/article/details/80187177
23 | - 第三个参数 'r', 'g', 'b', 'k'(Black),'y'(Yellow)
24 | - '.' 点标记 ',' 像素点
25 |
26 |
--------------------------------------------------------------------------------
/version2/main.py:
--------------------------------------------------------------------------------
1 | from tkinter import Tk
2 | from tkinter import Text
3 | from tkinter import Menu
4 |
5 | # parse.py与python包名冲突
6 | from mylexer import Lexer
7 | from myparser import Parser
8 |
9 |
10 | textBox = None
11 |
12 | def callLexer():
13 | # '1.0' 第一行第一列开始
14 | str = textBox.get('1.0', "end")
15 | # Lexer(string, show=False)
16 | # show=True显示分析过程
17 | tokens = Lexer(str, show=True)
18 |
19 | def callParser():
20 | str = textBox.get('1.0', "end")
21 | # Parser(string, show=False)
22 | # show=True显示分析过程
23 | Parser(str, show=True)
24 |
25 | def callPainter():
26 | str = textBox.get('1.0', "end")
27 | # Parser(string, show=False)
28 | # paint=True函数绘图
29 | Parser(str, paint=True)
30 |
31 | def main():
32 | tk = Tk()
33 | tk.title("izcat's Interpreter for Functional Painting Language")
34 | tk.geometry("800x600")
35 |
36 | menuBar = Menu(tk)
37 | menuBar.add_command(label="词法分析", command=callLexer)
38 | menuBar.add_command(label="语法分析", command=callParser)
39 | menuBar.add_command(label="函数绘图", command=callPainter)
40 | tk.config(menu=menuBar)
41 |
42 | global textBox
43 | textBox = Text(tk, width=800, height=300)
44 | textBox.pack()
45 |
46 | tk.mainloop()
47 |
48 | if __name__=='__main__':
49 | main()
50 |
51 |
--------------------------------------------------------------------------------
/test&pic/几何标志.txt:
--------------------------------------------------------------------------------
1 |
2 | ROT IS pi/12;
3 | for t from 0 to 1 step 0.01 draw (0, t) of blue;
4 | for t from 0 to 1 step 0.01 draw (1, t);
5 | for t from 0 to 1 step 0.01 draw (t, 0);
6 | for t from 0 to 1 step 0.01 draw (t, 1);
7 |
8 |
9 | ROT IS pi/12+pi/3;
10 | for t from 0 to 1 step 0.01 draw (0, t);
11 | for t from 0 to 1 step 0.01 draw (1, t);
12 | for t from 0 to 1 step 0.01 draw (t, 0);
13 | for t from 0 to 1 step 0.01 draw (t, 1);
14 |
15 |
16 | ROT IS pi/12+pi/3*2;
17 | for t from 0 to 1 step 0.01 draw (0, t);
18 | for t from 0 to 1 step 0.01 draw (1, t);
19 | for t from 0 to 1 step 0.01 draw (t, 0);
20 | for t from 0 to 1 step 0.01 draw (t, 1);
21 |
22 |
23 | ROT IS pi/12+pi/3*3;
24 | for t from 0 to 1 step 0.01 draw (0, t);
25 | for t from 0 to 1 step 0.01 draw (1, t);
26 | for t from 0 to 1 step 0.01 draw (t, 0);
27 | for t from 0 to 1 step 0.01 draw (t, 1);
28 |
29 |
30 | ROT IS pi/12+pi/3*4;
31 | for t from 0 to 1 step 0.01 draw (0, t);
32 | for t from 0 to 1 step 0.01 draw (1, t);
33 | for t from 0 to 1 step 0.01 draw (t, 0);
34 | for t from 0 to 1 step 0.01 draw (t, 1);
35 |
36 |
37 | ROT IS pi/12+pi/3*5;
38 | for t from 0 to 1 step 0.01 draw (0, t);
39 | for t from 0 to 1 step 0.01 draw (1, t);
40 | for t from 0 to 1 step 0.01 draw (t, 0);
41 | for t from 0 to 1 step 0.01 draw (t, 1);
42 |
--------------------------------------------------------------------------------
/version3/main.py:
--------------------------------------------------------------------------------
1 | from tkinter import Tk
2 | from tkinter import Text
3 | from tkinter import Menu
4 |
5 | # parse.py与python包名冲突
6 | from mylexer import Lexer
7 | from myparser import Parser
8 |
9 |
10 | textBox = None
11 |
12 | def callLexer():
13 | # '1.0' 第一行第一列开始
14 | str = textBox.get('1.0', "end")
15 | # Lexer(string, show=False)
16 | # show=True显示分析过程
17 | tokens = Lexer(str, show=True)
18 |
19 | def callParser():
20 | str = textBox.get('1.0', "end")
21 | # Parser(string, show=False)
22 | # show=True显示分析过程
23 | Parser(str, show=True)
24 |
25 | def callPainter():
26 | str = textBox.get('1.0', "end")
27 | # Parser(string, show=False)
28 | # paint=True函数绘图
29 | Parser(str, paint=True)
30 |
31 | def main():
32 | tk = Tk()
33 | tk.title("izcat's Interpreter for Functional Painting Language")
34 | tk.geometry("800x600")
35 |
36 | menuBar = Menu(tk)
37 | menuOpt = Menu(menuBar, tearoff=0)
38 | menuOpt.add_command(label="词法分析", command=callLexer)
39 | menuOpt.add_command(label="语法分析", command=callParser)
40 | menuOpt.add_command(label="函数绘图", command=callPainter)
41 | menuOpt.add_separator()
42 | menuBar.add_cascade(label="选择操作", menu=menuOpt)
43 | tk.config(menu=menuBar)
44 |
45 | global textBox
46 | textBox = Text(tk, width=800, height=300)
47 | textBox.pack()
48 |
49 | tk.mainloop()
50 |
51 | if __name__=='__main__':
52 | main()
53 |
54 |
--------------------------------------------------------------------------------
/test&pic/test0.txt:
--------------------------------------------------------------------------------
1 | -- 十字线
2 | ORIGIN IS (400, 400);
3 | FOR T FROM -350 TO 350 STEP 1 DRAW (T, 0);
4 | FOR T FROM -350 TO 350 STEP 1 DRAW (0, T);
5 |
6 |
7 | ------------------------------------------------------------
8 |
9 | -- 左上角
10 | ORIGIN IS (200,550);
11 | SCALE IS (80,80);
12 | ROT IS 0;
13 | FOR T FROM 0 TO 2*PI STEP PI/50 DRAW (COS(T), SIN(T)) of YELLOW;
14 | FOR T FROM 0 TO 20*PI 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)));
15 |
16 | ------------------------------------------------------------
17 |
18 | -- 右上角
19 | ORIGIN IS (600,550);
20 | SCALE IS (80,80/3);
21 |
22 | ROT IS PI/2+0*PI/3;
23 | FOR T FROM -PI TO PI STEP PI/50 DRAW (COS(T),SIN(T)) of RED;
24 |
25 | ROT IS PI/2+2*PI/3;
26 | FOR T FROM -PI TO PI STEP PI/50 DRAW (COS(T),SIN(T));
27 |
28 | ROT IS PI/2-2*PI/3;
29 | FOR T FROM -PI TO PI STEP PI/50 DRAW (COS(T),SIN(T));
30 |
31 |
32 | ------------------------------------------------------------
33 |
34 | -- 左下角
35 | SCALE IS (20, 30);
36 | ROT IS 0;
37 | ORIGIN IS (200-20*PI, 200);
38 | FOR T FROM 0 TO 2*PI STEP PI/50 DRAW (T, SIN(T)) of GREEN;
39 | ORIGIN IS (200-20*PI, 250);
40 | FOR T FROM 0 TO 2*PI STEP PI/50 DRAW (T, SIN(T));
41 | ORIGIN IS (200-20*PI, 300);
42 | FOR T FROM 0 TO 2*PI STEP PI/50 DRAW (T, SIN(T));
43 |
44 | ------------------------------------------------------------
45 |
46 | --右下角
47 | ORIGIN IS (600,250);
48 | ROT IS 0;
49 |
50 | SCALE IS (50, 50);
51 | FOR T FROM 0 TO 2*PI STEP PI/100 DRAW(COS(T), SIN(T)) of BLUE;
52 |
53 | SCALE IS (100, 100);
54 | FOR T FROM 0 TO 2*PI STEP PI/200 DRAW(COS(T), SIN(T));
55 |
--------------------------------------------------------------------------------
/version4/main.py:
--------------------------------------------------------------------------------
1 | from tkinter import Tk
2 | from tkinter import Text
3 | from tkinter import Menu
4 | from tkinter import filedialog
5 | import os
6 |
7 | # parse.py与python包名冲突
8 | from mylexer import Lexer
9 | from myparser import Parser
10 | from mypainter import Painter
11 |
12 |
13 | textBox = None
14 |
15 | def callLexer():
16 | # '1.0' 第一行第一列开始
17 | str = textBox.get('1.0', "end")
18 | # Lexer(string, show=False)
19 | # show=True显示分析过程
20 | Lexer(str, show=True)
21 |
22 | def callParser():
23 | str = textBox.get('1.0', "end")
24 | # Parser(string, show=False)
25 | # show=True显示分析过程
26 | Parser(str, show=True)
27 |
28 | def callPainter():
29 | str = textBox.get('1.0', "end")
30 | # 函数绘图
31 | Painter(str)
32 |
33 | # 打开文件 显示到textBox上
34 | def openFile():
35 | global textBox
36 | filePath = filedialog.askopenfilename(title=u'选择文件',
37 | initialdir=(os.path.expanduser(r"文件路径")))
38 | txtFile = open(filePath)
39 | content = txtFile.read()
40 | textBox.delete(0.0, "end")
41 | textBox.insert("insert", content)
42 |
43 |
44 | def main():
45 | tk = Tk()
46 | tk.title("izcat's Interpreter for Functional Painting Language")
47 | tk.geometry("800x600")
48 |
49 | menuBar = Menu(tk)
50 | menuBar.add_command(label="文件", command=openFile)
51 |
52 | menuOpt = Menu(menuBar, tearoff=0)
53 | menuOpt.add_command(label="词法分析", command=callLexer)
54 | menuOpt.add_command(label="语法分析", command=callParser)
55 | menuOpt.add_command(label="函数绘图", command=callPainter)
56 | menuOpt.add_separator()
57 | menuBar.add_cascade(label="选择", menu=menuOpt)
58 | tk.config(menu=menuBar)
59 |
60 | global textBox
61 | textBox = Text(tk, width=800, height=300)
62 | textBox.pack()
63 |
64 | tk.mainloop()
65 |
66 | if __name__=='__main__':
67 | main()
68 |
69 |
--------------------------------------------------------------------------------
/version2/mypainter.py:
--------------------------------------------------------------------------------
1 | from expnode import *
2 | import matplotlib.pyplot as plt
3 | import math
4 |
5 | class Painter():
6 | orx = 0.0
7 | ory = 0.0
8 | scx = 1.0
9 | scy = 1.0
10 | ang = 0.0
11 | # 绘制的点横坐标
12 | Points = dict(X=[], Y=[])
13 | # xlist = [] # 绘制的点横坐标
14 | # ylist = [] # 绘制的点纵坐标
15 | #
16 | def set(Origin_x=0.0, Origin_y=0.0, Scale_x=1.0, Scale_y=1.0, Rot_angle=0.0):
17 | Painter.orx = Origin_x
18 | Painter.ory = Origin_y
19 | Painter.scx = Scale_x
20 | Painter.scy = Scale_y
21 | Painter.ang = Rot_angle
22 |
23 | def paint(T_start, T_end, T_step, Point_x, Point_y):
24 | # for T_value in range(T_start, T_end, T_step):
25 | T_value = T_start
26 |
27 | while T_value<=T_end:
28 | ExpNode.T_value = T_value
29 | x = Point_x.getValue()
30 | y = Point_y.getValue()
31 |
32 | # print("(%f, %f)" % (x, y))
33 |
34 | # 坐标变换
35 | # 比例变换
36 | x, y = x*Painter.scx, y*Painter.scy
37 | # 旋转变换
38 | x, y = x*math.cos(Painter.ang) + y*math.sin(Painter.ang), y*math.cos(Painter.ang) - x*math.sin(Painter.ang)
39 | # 平移变换
40 | x, y = x+Painter.orx, y+Painter.ory
41 |
42 | # points.append((x, y))
43 | Painter.Points['X'].append(x)
44 | Painter.Points['Y'].append(y)
45 |
46 | # print("(%f, %f)" % (x, y))
47 | T_value += T_step
48 |
49 | def showPic():
50 | plt.xlim(xmax=100, xmin=-100)
51 | plt.ylim(ymax=100, ymin=-100)
52 | # plt.plot(x,y,format_string,**kwargs)
53 | # 第三个参数 https://blog.csdn.net/qiurisiyu2016/article/details/80187177
54 | # 'r', 'g', 'b', 'k'(Black),'y'(Yellow)
55 | # '.' 点标记 ',' 像素点
56 | plt.plot(Painter.Points['X'], Painter.Points['Y'], 'k.')
57 | plt.show()
58 |
59 | # 清空点 下次重新绘图
60 | Painter.Points['X'].clear()
61 | Painter.Points['Y'].clear()
62 |
63 |
--------------------------------------------------------------------------------
/version3/mypainter.py:
--------------------------------------------------------------------------------
1 | from expnode import *
2 | import matplotlib.pyplot as plt
3 | import math
4 |
5 | class Painter():
6 | orx = 0.0
7 | ory = 0.0
8 | scx = 1.0
9 | scy = 1.0
10 | ang = 0.0
11 | # 绘制的点横坐标
12 | Points = dict(X=[], Y=[])
13 | # xlist = [] # 绘制的点横坐标
14 | # ylist = [] # 绘制的点纵坐标
15 | #
16 | def set(Origin_x=0.0, Origin_y=0.0, Scale_x=1.0, Scale_y=1.0, Rot_angle=0.0):
17 | Painter.orx = Origin_x
18 | Painter.ory = Origin_y
19 | Painter.scx = Scale_x
20 | Painter.scy = Scale_y
21 | Painter.ang = Rot_angle
22 | Painter.Points['X'].clear()
23 | Painter.Points['Y'].clear()
24 |
25 | def paint(T_start, T_end, T_step, Point_x, Point_y, Draw_color):
26 | # for T_value in range(T_start, T_end, T_step):
27 | T_value = T_start
28 |
29 | while T_value<=T_end:
30 | ExpNode.T_value = T_value
31 | x = Point_x.getValue()
32 | y = Point_y.getValue()
33 |
34 | # print("(%f, %f)" % (x, y))
35 |
36 | # 坐标变换
37 | # 比例变换
38 | x, y = x*Painter.scx, y*Painter.scy
39 | # 旋转变换
40 | x, y = x*math.cos(Painter.ang) + y*math.sin(Painter.ang), y*math.cos(Painter.ang) - x*math.sin(Painter.ang)
41 | # 平移变换
42 | x, y = x+Painter.orx, y+Painter.ory
43 |
44 | # points.append((x, y))
45 | Painter.Points['X'].append(x)
46 | Painter.Points['Y'].append(y)
47 |
48 | # print("(%f, %f)" % (x, y))
49 | T_value += T_step
50 |
51 | # plt.plot(x,y,format_string,**kwargs)
52 | # 第三个参数 https://blog.csdn.net/qiurisiyu2016/article/details/80187177
53 | # 'r', 'g', 'b', 'k'(Black),'y'(Yellow)
54 | # '.' 点标记 ',' 像素点
55 | plt.plot(Painter.Points['X'], Painter.Points['Y'], '.'+Draw_color)
56 |
57 | def showPic():
58 | # plt.xlim(xmax=100, xmin=-100)
59 | # plt.ylim(ymax=100, ymin=-100)
60 | # 保持纵横比例
61 | plt.axis('equal')
62 |
63 | plt.show()
64 |
65 | # 清空点 下次重新绘图
66 | Painter.Points['X'].clear()
67 | Painter.Points['Y'].clear()
68 |
69 |
--------------------------------------------------------------------------------
/Interpreter4FPL/main.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 | # @Time : 2019/12/6 12:31
3 | # @Author : izcat
4 | # @Site : cnblogs.com/izcat
5 | # @File : main.py
6 | # @Software : PyCharm
7 | # @Desc : 项目GUI与程序入口
8 |
9 | from tkinter import Tk
10 | from tkinter import Text
11 | from tkinter import Menu
12 | from tkinter import filedialog
13 | import os
14 |
15 | # parse.py与python包名冲突
16 | from mylexer import Lexer
17 | from myparser import Parser
18 | from mypainter import Painter
19 |
20 |
21 | textBox = None
22 |
23 | def callLexer():
24 | # '1.0' 第一行第一列开始
25 | str = textBox.get('1.0', "end")
26 | # Lexer(string, show=False)
27 | # show=True显示分析过程
28 | Lexer(str, show=True)
29 |
30 | def callParser():
31 | str = textBox.get('1.0', "end")
32 | # Parser(string, show=False)
33 | # show=True显示分析过程
34 | Parser(str, show=True)
35 |
36 | def callPainter():
37 | str = textBox.get('1.0', "end")
38 | # 函数绘图
39 | Painter(str)
40 |
41 | # 打开文件 显示到textBox上
42 | def openFile():
43 | global textBox
44 | filePath = filedialog.askopenfilename(title=u'选择文件',
45 | initialdir=(os.path.expanduser(r"文件路径")))
46 | txtFile = open(filePath)
47 | content = txtFile.read()
48 | textBox.delete(0.0, "end")
49 | textBox.insert("insert", content)
50 |
51 |
52 | def main():
53 | tk = Tk()
54 | tk.title("izcat's Interpreter for Functional Painting Language")
55 | tk.geometry("800x600")
56 |
57 | menuBar = Menu(tk)
58 | menuBar.add_command(label="文件", command=openFile)
59 |
60 | menuOpt = Menu(menuBar, tearoff=0)
61 | menuOpt.add_command(label="词法分析", command=callLexer)
62 | menuOpt.add_command(label="语法分析", command=callParser)
63 | menuOpt.add_command(label="函数绘图", command=callPainter)
64 | menuOpt.add_separator()
65 | menuBar.add_cascade(label="选择", menu=menuOpt)
66 | tk.config(menu=menuBar)
67 |
68 | global textBox
69 | textBox = Text(tk, width=800, height=300)
70 | textBox.pack()
71 |
72 | tk.mainloop()
73 |
74 | if __name__=='__main__':
75 | main()
76 |
77 |
--------------------------------------------------------------------------------
/version2/expnode.py:
--------------------------------------------------------------------------------
1 | from mylexer import Token
2 | from mylexer import TokenType
3 |
4 | class ExpNode:
5 | T_value = 0.0
6 |
7 | def __init__(self, token, left=None, right=None):
8 | self.token = token
9 | self.lson = left
10 | self.rson = right
11 | def addson(self, son):
12 | if self.lson==None:
13 | self.lson = son
14 | return self
15 | elif self.rson==None:
16 | self.rson = son
17 | return self
18 | else:
19 | print("Cannot add son!")
20 | exit(-1)
21 |
22 | def getValue(self):
23 | # 叶子节点
24 | if self.lson==None and self.rson==None:
25 | if self.token.tokenType==TokenType.CONST_ID:
26 | return self.token.value
27 | elif self.token.tokenType==TokenType.T:
28 | return ExpNode.T_value
29 | else:
30 | print("Expression Error")
31 | exit(-1)
32 |
33 | # 只有左子树 函数节点 or +5 or -5
34 | elif self.rson==None:
35 | if self.token.tokenType==TokenType.PLUS:
36 | return self.lson.getValue()
37 | elif self.token.tokenType==TokenType.MINUS:
38 | return -self.lson.getValue()
39 | elif self.token.tokenType==TokenType.FUNC:
40 | return self.token.funcPtr(self.lson.getValue())
41 | else:
42 | print("Expression Error")
43 | exit(-1)
44 | # 只有右子树
45 | # elif self.lson==None:
46 | # if self.token.tokenType==TokenType.PLUS:
47 | # return self.rson.getValue()
48 | # elif self.token.tokenType==TokenType.MINUS:
49 | # return -self.rson.getValue()
50 | # elif self.token.tokenType==TokenType.FUNC:
51 | # return self.token.funcptr(self.rson.getValue())
52 | # else:
53 | # print("Expression Error")
54 | else:
55 | if self.token.tokenType==TokenType.PLUS:
56 | return self.lson.getValue() + self.rson.getValue()
57 | elif self.token.tokenType==TokenType.MINUS:
58 | return self.lson.getValue() - self.rson.getValue()
59 | elif self.token.tokenType==TokenType.MUL:
60 | return self.lson.getValue() * self.rson.getValue()
61 | elif self.token.tokenType==TokenType.DIV:
62 | return self.lson.getValue() / self.rson.getValue()
63 | elif self.token.tokenType==TokenType.POWER:
64 | return self.lson.getValue() ** self.rson.getValue()
65 | else:
66 | print("Expression Error")
67 | exit(-1)
68 |
69 | def dfs(self, depth=0):
70 | if self.lson!=None:
71 | self.lson.dfs(depth+1)
72 | if self.rson!=None:
73 | self.rson.dfs(depth+1)
74 |
75 | print("Depth %d" % depth)
76 | self.token.show()
--------------------------------------------------------------------------------
/version3/expnode.py:
--------------------------------------------------------------------------------
1 | from mylexer import Token
2 | from mylexer import TokenType
3 |
4 | class ExpNode:
5 | T_value = 0.0
6 |
7 | def __init__(self, token, left=None, right=None):
8 | self.token = token
9 | self.lson = left
10 | self.rson = right
11 | def addson(self, son):
12 | if self.lson==None:
13 | self.lson = son
14 | return self
15 | elif self.rson==None:
16 | self.rson = son
17 | return self
18 | else:
19 | print("Cannot add son!")
20 | exit(-1)
21 |
22 | def getValue(self):
23 | # 叶子节点
24 | if self.lson==None and self.rson==None:
25 | if self.token.tokenType==TokenType.CONST_ID:
26 | return self.token.value
27 | elif self.token.tokenType==TokenType.T:
28 | return ExpNode.T_value
29 | else:
30 | print("Expression Error")
31 | exit(-1)
32 |
33 | # 只有左子树 函数节点 or +5 or -5
34 | elif self.rson==None:
35 | if self.token.tokenType==TokenType.PLUS:
36 | return self.lson.getValue()
37 | elif self.token.tokenType==TokenType.MINUS:
38 | return -self.lson.getValue()
39 | elif self.token.tokenType==TokenType.FUNC:
40 | return self.token.funcPtr(self.lson.getValue())
41 | else:
42 | print("Expression Error")
43 | exit(-1)
44 | # 只有右子树
45 | # elif self.lson==None:
46 | # if self.token.tokenType==TokenType.PLUS:
47 | # return self.rson.getValue()
48 | # elif self.token.tokenType==TokenType.MINUS:
49 | # return -self.rson.getValue()
50 | # elif self.token.tokenType==TokenType.FUNC:
51 | # return self.token.funcptr(self.rson.getValue())
52 | # else:
53 | # print("Expression Error")
54 | else:
55 | if self.token.tokenType==TokenType.PLUS:
56 | return self.lson.getValue() + self.rson.getValue()
57 | elif self.token.tokenType==TokenType.MINUS:
58 | return self.lson.getValue() - self.rson.getValue()
59 | elif self.token.tokenType==TokenType.MUL:
60 | return self.lson.getValue() * self.rson.getValue()
61 | elif self.token.tokenType==TokenType.DIV:
62 | return self.lson.getValue() / self.rson.getValue()
63 | elif self.token.tokenType==TokenType.POWER:
64 | return self.lson.getValue() ** self.rson.getValue()
65 | else:
66 | print("Expression Error")
67 | exit(-1)
68 |
69 | def dfs(self, depth=0):
70 | ret = ' '*depth + self.token.lexeme + '\n'
71 | if self.lson!=None:
72 | ret += self.lson.dfs(depth+1)
73 | if self.rson!=None:
74 | ret += self.rson.dfs(depth+1)
75 |
76 | return ret
77 | # print("Depth %d" % depth)
78 | # self.token.show()
--------------------------------------------------------------------------------
/version4/expnode.py:
--------------------------------------------------------------------------------
1 | from mylexer import Token
2 | from mylexer import TokenType
3 |
4 | class ExpNode:
5 | T_value = 0.0
6 |
7 | def __init__(self, token, left=None, right=None):
8 | self.token = token
9 | self.lson = left
10 | self.rson = right
11 | def addson(self, son):
12 | if self.lson==None:
13 | self.lson = son
14 | return self
15 | elif self.rson==None:
16 | self.rson = son
17 | return self
18 | else:
19 | print("Cannot add son!")
20 | exit(-1)
21 |
22 | def getValue(self):
23 | # 叶子节点
24 | if self.lson==None and self.rson==None:
25 | if self.token.tokenType==TokenType.CONST_ID:
26 | return self.token.value
27 | elif self.token.tokenType==TokenType.T:
28 | return ExpNode.T_value
29 | else:
30 | print("Expression Error")
31 | exit(-1)
32 |
33 | # 只有左子树 函数节点 or +5 or -5
34 | elif self.rson==None:
35 | if self.token.tokenType==TokenType.PLUS:
36 | return self.lson.getValue()
37 | elif self.token.tokenType==TokenType.MINUS:
38 | return -self.lson.getValue()
39 | elif self.token.tokenType==TokenType.FUNC:
40 | return self.token.funcPtr(self.lson.getValue())
41 | else:
42 | print("Expression Error")
43 | exit(-1)
44 | # 只有右子树
45 | # elif self.lson==None:
46 | # if self.token.tokenType==TokenType.PLUS:
47 | # return self.rson.getValue()
48 | # elif self.token.tokenType==TokenType.MINUS:
49 | # return -self.rson.getValue()
50 | # elif self.token.tokenType==TokenType.FUNC:
51 | # return self.token.funcptr(self.rson.getValue())
52 | # else:
53 | # print("Expression Error")
54 | else:
55 | if self.token.tokenType==TokenType.PLUS:
56 | return self.lson.getValue() + self.rson.getValue()
57 | elif self.token.tokenType==TokenType.MINUS:
58 | return self.lson.getValue() - self.rson.getValue()
59 | elif self.token.tokenType==TokenType.MUL:
60 | return self.lson.getValue() * self.rson.getValue()
61 | elif self.token.tokenType==TokenType.DIV:
62 | return self.lson.getValue() / self.rson.getValue()
63 | elif self.token.tokenType==TokenType.POWER:
64 | return self.lson.getValue() ** self.rson.getValue()
65 | else:
66 | print("Expression Error")
67 | exit(-1)
68 |
69 | def dfs(self, depth=0):
70 | ret = ' '*depth + self.token.lexeme + '\n'
71 | if self.lson!=None:
72 | ret += self.lson.dfs(depth+1)
73 | if self.rson!=None:
74 | ret += self.rson.dfs(depth+1)
75 |
76 | return ret
77 | # print("Depth %d" % depth)
78 | # self.token.show()
--------------------------------------------------------------------------------
/version4/mypainter.py:
--------------------------------------------------------------------------------
1 | from expnode import *
2 | from myparser import Parser
3 | import matplotlib.pyplot as plt
4 | import math
5 |
6 | class Painter:
7 | def __init__(self, string):
8 | self.orx = 0.0
9 | self.ory = 0.0
10 | self.scx = 1.0
11 | self.scy = 1.0
12 | self.ang = 0.0
13 | self.Draw_color = 'k'
14 | statements = Parser(string)
15 | # print(len(statements))
16 |
17 | self.analyse(statements)
18 | self.showPic()
19 |
20 | # 语义分析
21 | def analyse(self, statements):
22 | for statement in statements:
23 | if statement[0]=="RotStatement":
24 | self.ang = statement[1].getValue()
25 | elif statement[0]=="ScaleStatement":
26 | self.scx, self.scy = statement[1].getValue(), statement[2].getValue()
27 | elif statement[0]=="OriginStatement":
28 | self.orx, self.ory = statement[1].getValue(), statement[2].getValue()
29 | elif statement[0]=="ForStatement":
30 | T_start, T_end = statement[1].getValue(), statement[2].getValue()
31 | T_step = statement[3].getValue()
32 |
33 | Point_x, Point_y = statement[4], statement[5]
34 | if statement[6]:
35 | # print(statement[6])
36 | self.Draw_color = statement[6]
37 | self.paint(T_start, T_end, T_step, Point_x, Point_y)
38 | else:
39 | print("analyse Error")
40 |
41 | def paint(self, T_start, T_end, T_step, Point_x, Point_y):
42 | # for T_value in range(T_start, T_end, T_step):
43 | T_value = T_start
44 | # 绘制的点坐标
45 | Points = dict(X=[], Y=[])
46 | while T_value<=T_end:
47 | ExpNode.T_value = T_value
48 | x = Point_x.getValue()
49 | y = Point_y.getValue()
50 |
51 | # print("(%f, %f)" % (x, y))
52 |
53 | # 坐标变换
54 | # 比例变换
55 | x, y = x*self.scx, y*self.scy
56 | # 旋转变换
57 | x, y = x*math.cos(self.ang) + y*math.sin(self.ang), y*math.cos(self.ang) - x*math.sin(self.ang)
58 | # 平移变换
59 | x, y = x+self.orx, y+self.ory
60 |
61 | # points.append((x, y))
62 | Points['X'].append(x)
63 | Points['Y'].append(y)
64 |
65 | # print("(%f, %f)" % (x, y))
66 | T_value += T_step
67 |
68 | # plt.plot(x,y,format_string,**kwargs)
69 | # 第三个参数 https://blog.csdn.net/qiurisiyu2016/article/details/80187177
70 | # 'r', 'g', 'b', 'k'(Black),'y'(Yellow)
71 | # '.' 点标记 ',' 像素点
72 | plt.plot(Points['X'], Points['Y'], '.'+self.Draw_color)
73 |
74 | # 颜色全相同bug已修复 Points应为局部变量
75 | # print("=="+self.Draw_color)
76 |
77 |
78 | def showPic(self):
79 | # plt.xlim(xmax=100, xmin=-100)
80 | # plt.ylim(ymax=100, ymin=-100)
81 | # 保持纵横比例
82 |
83 | plt.axis('equal')
84 |
85 | plt.show()
86 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/Interpreter4FPL/expnode.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 | # @Time : 2019/12/6 12:50
3 | # @Author : izcat
4 | # @Site : $ cnblogs.com/izcat
5 | # @File : expnode.py
6 | # @Software : PyCharm
7 | # @Desc : 表达式节点定义
8 |
9 | from mylexer import Token
10 | from mylexer import TokenType
11 |
12 | class ExpNode:
13 | T_value = 0.0
14 |
15 | def __init__(self, token, left=None, right=None):
16 | self.token = token
17 | self.lson = left
18 | self.rson = right
19 | def addson(self, son):
20 | if self.lson==None:
21 | self.lson = son
22 | return self
23 | elif self.rson==None:
24 | self.rson = son
25 | return self
26 | else:
27 | print("Cannot add son!")
28 | exit(-1)
29 |
30 | def getValue(self):
31 | # 叶子节点
32 | if self.lson==None and self.rson==None:
33 | if self.token.tokenType==TokenType.CONST_ID:
34 | return self.token.value
35 | elif self.token.tokenType==TokenType.T:
36 | return ExpNode.T_value
37 | else:
38 | print("Expression Error")
39 | exit(-1)
40 |
41 | # 只有左子树 函数节点 or +5 or -5
42 | elif self.rson==None:
43 | if self.token.tokenType==TokenType.PLUS:
44 | return self.lson.getValue()
45 | elif self.token.tokenType==TokenType.MINUS:
46 | return -self.lson.getValue()
47 | elif self.token.tokenType==TokenType.FUNC:
48 | return self.token.funcPtr(self.lson.getValue())
49 | else:
50 | print("Expression Error")
51 | exit(-1)
52 | # 只有右子树
53 | # elif self.lson==None:
54 | # if self.token.tokenType==TokenType.PLUS:
55 | # return self.rson.getValue()
56 | # elif self.token.tokenType==TokenType.MINUS:
57 | # return -self.rson.getValue()
58 | # elif self.token.tokenType==TokenType.FUNC:
59 | # return self.token.funcptr(self.rson.getValue())
60 | # else:
61 | # print("Expression Error")
62 | else:
63 | if self.token.tokenType==TokenType.PLUS:
64 | return self.lson.getValue() + self.rson.getValue()
65 | elif self.token.tokenType==TokenType.MINUS:
66 | return self.lson.getValue() - self.rson.getValue()
67 | elif self.token.tokenType==TokenType.MUL:
68 | return self.lson.getValue() * self.rson.getValue()
69 | elif self.token.tokenType==TokenType.DIV:
70 | return self.lson.getValue() / self.rson.getValue()
71 | elif self.token.tokenType==TokenType.POWER:
72 | return self.lson.getValue() ** self.rson.getValue()
73 | else:
74 | print("Expression Error")
75 | exit(-1)
76 |
77 | def dfs(self, depth=0):
78 | ret = ' '*depth + self.token.lexeme + '\n'
79 | if self.lson!=None:
80 | ret += self.lson.dfs(depth+1)
81 | if self.rson!=None:
82 | ret += self.rson.dfs(depth+1)
83 |
84 | return ret
85 | # print("Depth %d" % depth)
86 | # self.token.show()
--------------------------------------------------------------------------------
/version1/grammer.py:
--------------------------------------------------------------------------------
1 | # Program -> {Statement SEMICO}
2 | # Statement -> OriginStatement | ScaleStatement | RotStatement | ForStatement
3 | # OriginStatement -> ORIGIN IS L_BRACKET Expression COMMA Expression R_BRACKET
4 | # ScaleStatement -> SCALE IS L_BRACKET Expression COMMA Expression R_BRACKET
5 | # RotStatement -> ROT IS Expression
6 | # ForStatement -> FOR T FROM Expression TO Expression STEP Expression
7 | # DRAW L_BRACKET Expression COMMA Expression R_BRACKET
8 |
9 | from lexer import *
10 | import sys
11 |
12 | tokenIter = None
13 | tokenNow = Token(TokenType.NONTOKEN, '');
14 |
15 | # 从词法分析器的tokens获得token
16 | def FetchToken():
17 | global tokenNow
18 | try:
19 | tokenNow = next(tokenIter)
20 | return tokenNow
21 | except StopIteration:
22 | sys.exit()
23 |
24 | def MatchToken(tokenType, show=False):
25 | if show:
26 | tokenNow.show()
27 | if tokenNow.tokenType==tokenType:
28 | FetchToken()
29 | else:
30 | print("Excepted ", tokenType, "received ", tokenNow.tokenType)
31 | print("error!")
32 | exit(-1)
33 |
34 | def Parser(string):
35 | global tokenIter # 必须要 global
36 | tokenList = Lexer(string)
37 | tokenIter = iter(tokenList)
38 | FetchToken()
39 | Program()
40 |
41 | def OriginStatement():
42 | MatchToken(TokenType.ORIGIN)
43 | MatchToken(TokenType.IS)
44 | MatchToken(TokenType.L_BRACKET)
45 | Origin_x = Expression().getValue()
46 | MatchToken(TokenType.COMMA)
47 | Origin_y = Expression().getValue()
48 | MatchToken(TokenType.R_BRACKET)
49 |
50 | def ScaleStatement():
51 | MatchToken(TokenType.SCALE)
52 | MatchToken(TokenType.IS)
53 | MatchToken(TokenType.L_BRACKET)
54 | Scale_x = Expression().getValue()
55 | MatchToken(TokenType.COMMA)
56 | Scale_y = Expression().getValue()
57 | MatchToken(TokenType.R_BRACKET)
58 |
59 | def RotStatement():
60 | MatchToken(TokenType.ROT)
61 | MatchToken(TokenType.IS)
62 | Rot_angle = Expression().getValue()
63 |
64 | def ForStatement():
65 | MatchToken(TokenType.FOR)
66 | MatchToken(TokenType.T)
67 | MatchToken(TokenType.FROM)
68 | T_start = Expression()
69 | MatchToken(TokenType.TO)
70 | T_end = Expression()
71 | MatchToken(TokenType.STEP)
72 | T_step = Expression()
73 |
74 | MatchToken(TokenType.DRAW)
75 | MatchToken(TokenType.L_BRACKET)
76 | Point_x = Expression()
77 | MatchToken(TokenType.COMMA)
78 | Point_y = Expression()
79 | MatchToken(TokenType.R_BRACKET)
80 |
81 |
82 | # Statement -> OriginStatement | ScaleStatement | RotStatement | ForStatement
83 | def Statement():
84 | if tokenNow.tokenType==TokenType.ORIGIN:
85 | OriginStatement()
86 | elif tokenNow.tokenType==TokenType.SCALE:
87 | ScaleStatement()
88 | elif tokenNow.tokenType==TokenType.ROT:
89 | RotStatement()
90 | elif tokenNow.tokenType==TokenType.FOR:
91 | ForStatement()
92 | else:
93 | print("error!")
94 |
95 |
96 | def Program():
97 | while tokenNow.tokenType!=TokenType.NONTOKEN:
98 | Statement()
99 | matched = MatchToken(TokenType.SEMICO)
100 | if not matched:
101 | break
102 |
103 |
104 | def test():
105 | Parser("--hello fad\n //fadfjl\n ROT is ( 1, 0*2) \n ROT is (sin(t), cos(tt));")
106 |
107 | test()
108 |
--------------------------------------------------------------------------------
/Interpreter4FPL/mypainter.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 | # @Time : 2019/12/6 12:55
3 | # @Author : izcat
4 | # @Site : $ cnblogs.com/izcat
5 | # @File : mypainter.py
6 | # @Software : PyCharm
7 | # @Desc : 语义分析器,绘图程序
8 |
9 | from expnode import *
10 | from myparser import Parser
11 | import matplotlib.pyplot as plt
12 | import math
13 |
14 |
15 | class Painter:
16 | def __init__(self, string):
17 | self.orx = 0.0
18 | self.ory = 0.0
19 | self.scx = 1.0
20 | self.scy = 1.0
21 | self.ang = 0.0
22 | self.Draw_color = 'k'
23 | statements = Parser(string)
24 | # print(len(statements))
25 |
26 | self.analyse(statements)
27 | self.showPic()
28 |
29 | # 语义分析
30 | def analyse(self, statements):
31 | for statement in statements:
32 | if statement[0] == "RotStatement":
33 | self.ang = statement[1].getValue()
34 | elif statement[0] == "ScaleStatement":
35 | self.scx, self.scy = statement[1].getValue(), statement[2].getValue()
36 | elif statement[0] == "OriginStatement":
37 | self.orx, self.ory = statement[1].getValue(), statement[2].getValue()
38 | elif statement[0] == "ForStatement":
39 | T_start, T_end = statement[1].getValue(), statement[2].getValue()
40 | T_step = statement[3].getValue()
41 |
42 | Point_x, Point_y = statement[4], statement[5]
43 | if statement[6]:
44 | # print(statement[6])
45 | self.Draw_color = statement[6]
46 | self.paint(T_start, T_end, T_step, Point_x, Point_y)
47 | else:
48 | print("analyse Error")
49 |
50 | def paint(self, T_start, T_end, T_step, Point_x, Point_y):
51 | # for T_value in range(T_start, T_end, T_step):
52 | T_value = T_start
53 | # 绘制的点坐标
54 | Points = dict(X=[], Y=[])
55 | while T_value <= T_end:
56 | ExpNode.T_value = T_value
57 | x = Point_x.getValue()
58 | y = Point_y.getValue()
59 |
60 | # print("(%f, %f)" % (x, y))
61 |
62 | # 坐标变换
63 | # 比例变换
64 | x, y = x * self.scx, y * self.scy
65 | # 旋转变换
66 | x, y = x * math.cos(self.ang) + y * math.sin(self.ang), y * math.cos(self.ang) - x * math.sin(self.ang)
67 | # 平移变换
68 | x, y = x + self.orx, y + self.ory
69 |
70 | # points.append((x, y))
71 | Points['X'].append(x)
72 | Points['Y'].append(y)
73 |
74 | # print("(%f, %f)" % (x, y))
75 | T_value += T_step
76 |
77 | # plt.plot(x,y,format_string,**kwargs)
78 | # 第三个参数 https://blog.csdn.net/qiurisiyu2016/article/details/80187177
79 | # 'r', 'g', 'b', 'k'(Black),'y'(Yellow)
80 | # '.' 点标记 ',' 像素点
81 | plt.plot(Points['X'], Points['Y'], '.' + self.Draw_color)
82 |
83 | # 颜色全相同bug已修复 Points应为局部变量
84 | # print("=="+self.Draw_color)
85 |
86 | def showPic(self):
87 | # plt.xlim(xmax=100, xmin=-100)
88 | # plt.ylim(ymax=100, ymin=-100)
89 | # 保持纵横比例
90 |
91 | plt.axis('equal')
92 |
93 | plt.show()
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Interpreter For Functional Painting Language
2 | > 西电 编译原理大作业
3 |
4 | ## 实验目的
5 | 实现函数绘图语言的解释器,通过实验加深对编译器构造原理和方法的理解,巩固所学知识。
6 | - 会用正规式设计简单语言的词法
7 | - 会用产生式设计简单语言的语法
8 | - 会用递归下降子程序编写语言的解释器
9 |
10 |
11 |
12 | ## 实验要求
13 |
14 | ### 语句原则:
15 |
16 | 1. 各类语句可以按任意次序书写,且语句以分号结尾。源程序中的语句以它们出现的先后顺序处理。
17 |
18 | 2. ORIGIN、ROT和SCALE 语句只影响其后的绘图语句,且遵循最后出现的语句有效的原则。
19 | 例如,若有下述ROT语句序列:
20 | ROT IS 0.7 ;
21 | ROT IS 1.57 ;
22 | 则随后的绘图语句将按1.57而不是0.7弧度旋转。
23 |
24 | 3. 无论ORIGIN、ROT和SCALE语句的出现顺序如何,图形的变换顺序总是:比例变换→旋转变换→平移变换
25 |
26 | 4. 语言对大小写不敏感,例如for、For、FOR等,均被认为是同一个保留字。
27 |
28 | 5. 语句中表达式的值均为双精度类型,旋转角度单位为弧度且为逆时针旋转,平移单位为点。
29 |
30 | ### 循环绘图(FOR-DRAW )语句
31 | 语法:FOR T FROM 起点 TO 终点 STEP 步长 DRAW(横坐标, 纵坐标);
32 |
33 | 语义:令T从起点到终点、每次改变一个步长,绘制出由(横坐标,纵坐标)所规定的点的轨迹。
34 |
35 | 举例:FOR T FROM 0 TO 2*PI STEP PI/50 DRAW (cos(T), sin(T));
36 |
37 | 说明:该语句的作用是令T从0到2*PI、步长 PI/50,绘制出各个点的坐标(cos(T),sin(T)),即一个单位圆。
38 |
39 | ### 比例设置(SCALE)语句
40 | 语法:SCALE IS (横坐标比例因子,纵坐标比例因子);
41 |
42 | 语义:设置横坐标和纵坐标的比例,并分别按照比例因子进行缩放。
43 |
44 | 举例:SCALE IS (100, 100);
45 |
46 | 说明:将横坐标和纵坐标的比例设置为1:1,且放大100倍。
47 |
48 | ### 坐标平移(ORIGIN)语句
49 | 语法:ORIGIN IS (横坐标,纵坐标);
50 |
51 | 语义:将坐标系的原点平移到横坐标和纵坐标规定的点处。
52 |
53 | 举例:ORIGIN IS (360, 240);
54 |
55 | 说明:将原点从(0, 0)平移到(360, 240) 处
56 |
57 | ### 角度旋转(ROT)语句
58 | 语法:ROT IS 角度;
59 |
60 | 语义:逆时针旋转角度所规定的弧度值。
61 | 具体计算公式:
62 | 旋转后X=旋转前X*COS(角度)+旋转前Y*SIN(角度)
63 | 旋转后Y=旋转前Y*COS(角度)-旋转前X*SIN(角度)
64 |
65 | 举例:ROT IS PI/2;
66 |
67 | 说明:逆时针旋转PI/2,即逆时针旋转90度。
68 |
69 | ### 注释语句
70 | 作用:便于理解;
71 | 屏蔽暂时不需要的语句。
72 | 语法:// This is a comment line
73 | 或 -- 此行是注释
74 | 语义:// 或 -- 之后,直到行尾,均是注释
75 |
76 |
77 |
78 | -------
79 |
80 |
81 |
82 | ## 实验过程
83 |
84 | ### Version 1
85 | 代码详见 https://github.com/izcat/Interpreter4FPL/tree/master/version1
86 |
87 | 完成词法分析
88 |
89 | #### 词法分析器功能
90 |
91 | - 输入:函数绘图语言源程序,以字符串形式传递给 `Lexer` 参数
92 | - 输出:返回源程序进行词法分析得到的全部 Token,类型为列表
93 |
94 | #### Update:
95 |
96 | 此版本 `Lexer` 会无法正确识别带小数点的浮点数!在version2中的 `Lexer` 才是正确写法!
97 |
98 |
99 | ### Version 2
100 | 代码详见 https://github.com/izcat/Interpreter4FPL/tree/master/version2
101 |
102 | 已实现实验要求的函数绘图语言的全部功能
103 | 解释器执行的第一个程序结果(显示 'OK' 字样):
104 | 
105 |
106 |
107 | #### 修复Bug
108 |
109 | 由于新加入主界面的模块 `main.py` 无法正常 import 写好的 `parser`模块,因为会与 Python 的同名库冲突。
110 | 将全部模块改名,加上'my'前缀
111 |
112 | #### 不足
113 |
114 | 词法分析器与语义分析器没有完全分离,本解释器在语法分析阶段,未生成源代码的整体语法树,直接将绘制的点信息交给painter处理
115 | 缺少异常处理机制
116 | 没有完全面向对象开发
117 |
118 |
119 | ### Version 3
120 | 代码详见 https://github.com/izcat/Interpreter4FPL/tree/master/version3
121 |
122 | 本次版本不涉及代码修复和功能修改,version2可以正常运行标准绘图源程序
123 |
124 | 在完成作业要求的基础上,本次更新增加了**自定义颜色**的语法
125 | 即
126 | **FOR T FROM T_start TO T_end STEP T_step DRAW (Point_x, Point_Y)**
127 | **[OF (RED|GREEN|BLUE|YELLOW|BLACK)]**
128 |
129 | 更改内容如下
130 |
131 | - `mylexer` 模块新增记号类别 `TokenType` : **OF**,**RED**,**GREEN**,**BLUE**,**YELLOW**, **BLACK**
132 | - `mylexer` 模块新增字符与记号的字典映射 `TokenTypeDict` :
133 | - OF = Token(TokenType.OF, "OF")
134 | - RED = Token(TokenType.COLOR, "RED")
135 | - GREEN = Token(TokenType.COLOR, "GREEN")
136 | - BLUE = Token(TokenType.COLOR, "BLUE")
137 | - YELLOW = Token(TokenType.COLOR, "YELLOW")
138 | - BLACK = Token(TokenType.COLOR, "BLACK")
139 | - `myparser` 模块作少量改动,`ForStatement` 方法新增颜色识别语句,将获取颜色结果传给 `Painter`
140 | - `mypainter` 模块内的 `paint` 方法
141 | - plt.plot(Painter.Points['X'], Painter.Points['Y'], '.'+Draw_color)
142 | - 参考自 https://blog.csdn.net/qiurisiyu2016/article/details/80187177
143 | - 第三个参数 'r', 'g', 'b', 'k'(Black),'y'(Yellow)
144 | - '.' 点标记 ',' 像素点
145 |
146 |
147 | ### Version 4
148 | 代码详见 https://github.com/izcat/Interpreter4FPL/tree/master/version4
149 |
150 | 改进内容:
151 |
152 | - 在version3的基础上,分离语法分析器 `myparser` 模块与语义分析器 `mypainter` 模块
153 | - 重新设计了语法分析过程中的运行提示,增加了层级level参数,使递归调用的输出信息更友好
154 | - 重写了 `mypainter` 模块,改用面向对象方式
155 | - `Painter` 类 接收绘图源程序代码,调用语法分析器 `myparser.Parser`
156 | - 将获取到的语法树交给 `analyse` 方法进行语义分析
157 | - 语义分析完成后,`showPic` 执行绘图
158 | - 改进 `main` 程序入口模块,增加了打开文件选项,可以直接选择写好绘图源程序打开
159 |
160 |
161 | ## 结果展示
162 |
163 | 
164 | 
165 | 
166 |
167 |
168 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | 1575603892701
76 |
77 |
78 | 1575603892701
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/version1/Lexical.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 | import math
3 |
4 | class TokenType(Enum):
5 | ORIGIN = "ORIGIN"
6 | SCALE = "SCALE"
7 | ROT = "ROT"
8 | IS = "IS"
9 | FOR = "FOR"
10 | FROM = "FROM"
11 | TO = "TO"
12 | STEP = "STEP"
13 | DRAW = "DRAW"
14 | T = "T"
15 | FUNC = "FUNCTION"
16 | CONST_ID = "CONST_ID"
17 | SEMICO = ';'
18 | L_BRACKET = '('
19 | R_BRACKET = ')'
20 | COMMA = ','
21 | PLUS = '+'
22 | MINUS = '-'
23 | MUL = '*'
24 | DIV = '/'
25 | POWER = '**'
26 | NONTOKEN = "NON"
27 | ERRTOKEN = "ERR"
28 |
29 | # print(TokenType.FUNC.name) ==> FUNC
30 | # print(TokenType.FUNC.value) ==> FUNCTION
31 | #
32 | class Token:
33 | def __init__(self, tokentype, lexeme, value=0.0, funcptr=None):
34 | self.tokenType = tokentype
35 | self.lexeme = lexeme
36 | self.value = value
37 | self.funcPtr = funcptr
38 |
39 | def show(self):
40 | print(self.tokenType.name.ljust(15), self.lexeme.ljust(15), str(self.value).ljust(15), self.funcPtr)
41 |
42 | # ID
43 | TokenTypeDict = dict(PI = Token(TokenType.CONST_ID, "PI", 3.1415926),
44 | E = Token(TokenType.CONST_ID, "E", 2.71828),
45 | T = Token(TokenType.T, "T"),
46 | ORIGIN = Token(TokenType.ORIGIN, "ORIGIN"),
47 | SCALE = Token(TokenType.SCALE, "SCALE"),
48 | ROT = Token(TokenType.ROT, "ROT"),
49 | IS = Token(TokenType.IS, "IS"),
50 | FOR = Token(TokenType.FOR, "FOR"),
51 | FROM = Token(TokenType.FROM, "FROM"),
52 | TO = Token(TokenType.TO, "TO"),
53 | STEP = Token(TokenType.STEP, "STEP"),
54 | DRAW = Token(TokenType.DRAW, "DRAW"),
55 | SIN = Token(TokenType.FUNC, "SIN", 0.0, math.sin),
56 | COS = Token(TokenType.FUNC, "COS", 0.0, math.cos),
57 | TAN = Token(TokenType.FUNC, "TAN", 0.0, math.tan),
58 | LN = Token(TokenType.FUNC, "LN", 0.0, math.log),
59 | EXP = Token(TokenType.FUNC, "EXP", 0.0, math.exp),
60 | SQRT = Token(TokenType.FUNC, "SQRT", 0.0, math.sqrt));
61 |
62 |
63 | # 没有使用 NONTOKEN
64 | # 利用 i FUNC
30 | # print(TokenType.FUNC.value) ==> FUNCTION
31 | #
32 | class Token:
33 | def __init__(self, tokentype, lexeme, value=0.0, funcptr=None):
34 | self.tokenType = tokentype
35 | self.lexeme = lexeme
36 | self.value = value
37 | self.funcPtr = funcptr
38 |
39 | def show(self):
40 | print(self.tokenType.name.ljust(15), self.lexeme.ljust(15), str(self.value).ljust(15), self.funcPtr)
41 |
42 | # ID
43 | TokenTypeDict = dict(PI = Token(TokenType.CONST_ID, "PI", math.pi),
44 | E = Token(TokenType.CONST_ID, "E", math.e),
45 | T = Token(TokenType.T, "T"),
46 | ORIGIN = Token(TokenType.ORIGIN, "ORIGIN"),
47 | SCALE = Token(TokenType.SCALE, "SCALE"),
48 | ROT = Token(TokenType.ROT, "ROT"),
49 | IS = Token(TokenType.IS, "IS"),
50 | FOR = Token(TokenType.FOR, "FOR"),
51 | FROM = Token(TokenType.FROM, "FROM"),
52 | TO = Token(TokenType.TO, "TO"),
53 | STEP = Token(TokenType.STEP, "STEP"),
54 | DRAW = Token(TokenType.DRAW, "DRAW"),
55 | SIN = Token(TokenType.FUNC, "SIN", 0.0, math.sin),
56 | COS = Token(TokenType.FUNC, "COS", 0.0, math.cos),
57 | TAN = Token(TokenType.FUNC, "TAN", 0.0, math.tan),
58 | LN = Token(TokenType.FUNC, "LN", 0.0, math.log),
59 | EXP = Token(TokenType.FUNC, "EXP", 0.0, math.exp),
60 | SQRT = Token(TokenType.FUNC, "SQRT", 0.0, math.sqrt));
61 |
62 |
63 |
64 | def showTokens(tokens):
65 | print("Category".ljust(15), "Input".ljust(15), "Value".ljust(15), "FuncPtr")
66 | for token in tokens:
67 | token.show()
68 |
69 | # 没有使用 NONTOKEN
70 | # 利用 i FUNC
32 | # print(TokenType.FUNC.value) ==> FUNCTION
33 | #
34 | class Token:
35 | def __init__(self, tokentype, lexeme, value=0.0, funcptr=None):
36 | self.tokenType = tokentype
37 | self.lexeme = lexeme
38 | self.value = value
39 | self.funcPtr = funcptr
40 |
41 | def show(self):
42 | print(self.tokenType.name.ljust(15), self.lexeme.ljust(15), str(self.value).ljust(15), self.funcPtr)
43 |
44 | # CONST_ID
45 | TokenTypeDict = dict(PI = Token(TokenType.CONST_ID, "PI", math.pi),
46 | E = Token(TokenType.CONST_ID, "E", math.e),
47 | T = Token(TokenType.T, "T"),
48 | ORIGIN = Token(TokenType.ORIGIN, "ORIGIN"),
49 | SCALE = Token(TokenType.SCALE, "SCALE"),
50 | ROT = Token(TokenType.ROT, "ROT"),
51 | IS = Token(TokenType.IS, "IS"),
52 | FOR = Token(TokenType.FOR, "FOR"),
53 | FROM = Token(TokenType.FROM, "FROM"),
54 | TO = Token(TokenType.TO, "TO"),
55 | STEP = Token(TokenType.STEP, "STEP"),
56 | DRAW = Token(TokenType.DRAW, "DRAW"),
57 | SIN = Token(TokenType.FUNC, "SIN", 0.0, math.sin),
58 | COS = Token(TokenType.FUNC, "COS", 0.0, math.cos),
59 | TAN = Token(TokenType.FUNC, "TAN", 0.0, math.tan),
60 | LN = Token(TokenType.FUNC, "LN", 0.0, math.log),
61 | EXP = Token(TokenType.FUNC, "EXP", 0.0, math.exp),
62 | SQRT = Token(TokenType.FUNC, "SQRT", 0.0, math.sqrt),
63 | OF = Token(TokenType.OF, "OF"),
64 | RED = Token(TokenType.COLOR, "RED"),
65 | GREEN = Token(TokenType.COLOR, "GREEN"),
66 | BLUE = Token(TokenType.COLOR, "BLUE"),
67 | YELLOW = Token(TokenType.COLOR, "YELLOW"),
68 | BLACK = Token(TokenType.COLOR, "BLACK"));
69 |
70 |
71 |
72 | def showTokens(tokens):
73 | print("Category".ljust(15), "Input".ljust(15), "Value".ljust(15), "FuncPtr")
74 | for token in tokens:
75 | token.show()
76 |
77 | # 没有使用 NONTOKEN
78 | # 利用 i FUNC
32 | # print(TokenType.FUNC.value) ==> FUNCTION
33 | #
34 | class Token:
35 | def __init__(self, tokentype, lexeme, value=0.0, funcptr=None):
36 | self.tokenType = tokentype
37 | self.lexeme = lexeme
38 | self.value = value
39 | self.funcPtr = funcptr
40 |
41 | def show(self):
42 | print(self.tokenType.name.ljust(15), self.lexeme.ljust(15), str(self.value).ljust(15), self.funcPtr)
43 |
44 | # CONST_ID
45 | TokenTypeDict = dict(PI = Token(TokenType.CONST_ID, "PI", math.pi),
46 | E = Token(TokenType.CONST_ID, "E", math.e),
47 | T = Token(TokenType.T, "T"),
48 | ORIGIN = Token(TokenType.ORIGIN, "ORIGIN"),
49 | SCALE = Token(TokenType.SCALE, "SCALE"),
50 | ROT = Token(TokenType.ROT, "ROT"),
51 | IS = Token(TokenType.IS, "IS"),
52 | FOR = Token(TokenType.FOR, "FOR"),
53 | FROM = Token(TokenType.FROM, "FROM"),
54 | TO = Token(TokenType.TO, "TO"),
55 | STEP = Token(TokenType.STEP, "STEP"),
56 | DRAW = Token(TokenType.DRAW, "DRAW"),
57 | SIN = Token(TokenType.FUNC, "SIN", 0.0, math.sin),
58 | COS = Token(TokenType.FUNC, "COS", 0.0, math.cos),
59 | TAN = Token(TokenType.FUNC, "TAN", 0.0, math.tan),
60 | LN = Token(TokenType.FUNC, "LN", 0.0, math.log),
61 | EXP = Token(TokenType.FUNC, "EXP", 0.0, math.exp),
62 | SQRT = Token(TokenType.FUNC, "SQRT", 0.0, math.sqrt),
63 | OF = Token(TokenType.OF, "OF"),
64 | RED = Token(TokenType.COLOR, "RED"),
65 | GREEN = Token(TokenType.COLOR, "GREEN"),
66 | BLUE = Token(TokenType.COLOR, "BLUE"),
67 | YELLOW = Token(TokenType.COLOR, "YELLOW"),
68 | BLACK = Token(TokenType.COLOR, "BLACK"));
69 |
70 |
71 |
72 | def showTokens(tokens):
73 | print("Category".ljust(15), "Input".ljust(15), "Value".ljust(15), "FuncPtr")
74 | for token in tokens:
75 | token.show()
76 |
77 | # 没有使用 NONTOKEN
78 | # 利用 i OriginStatement | ScaleStatement | RotStatement | ForStatement
237 | def Statement():
238 | if tokenNow.tokenType==TokenType.ORIGIN:
239 | OriginStatement()
240 | elif tokenNow.tokenType==TokenType.SCALE:
241 | ScaleStatement()
242 | elif tokenNow.tokenType==TokenType.ROT:
243 | RotStatement()
244 | elif tokenNow.tokenType==TokenType.FOR:
245 | ForStatement()
246 | else:
247 | print("Statement Error!")
248 |
249 |
250 | def Program():
251 | while tokenNow.tokenType!=TokenType.NONTOKEN:
252 | Statement()
253 | matched = MatchToken(TokenType.SEMICO)
254 | if not matched:
255 | print("Program Error")
256 | break
257 |
258 | def Parser(string):
259 | global tokenIter # 必须要 global
260 | tokenList = Lexer(string)
261 | tokenIter = iter(tokenList)
262 | FetchToken()
263 | Program()
264 |
265 |
266 |
267 | def test():
268 | Parser("--hello fad\n //fadfjl\n ROT is pi/2 ; SCALE is ( 1, 2*2); \n ORIGIN is ((2), 242/4);")
269 | str = "ORigin is (-30, 0); SCALE is ( 20, 25); for t from 0 to 2*pi step 0.01 draw (sin(t), cos(t)); SCALE is ( 30, 20); for t from -1 to 1 step 0.01 draw (2, t); FOR t from 0 to 1 step 0.01 draw (2+t, t);for t from -1 to 1 step 0.01 draw (2, t); FOR t from 0 to 1 step 0.01 draw (2+t, -t);for t from 0 to 2*pi step 0.01 draw (1+3*sin(t), 3*cos(t)); "
270 |
271 | Parser(str);
272 | # print("(%f, %f)" % (Origin_x, Origin_y))
273 | # print("(%f, %f)" % (Scale_x, Scale_y))
274 | print("%f" % Rot_angle)
275 |
276 | Painter.showPic()
277 |
278 | test()
--------------------------------------------------------------------------------
/Interpreter4FPL/mylexer.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 | # @Time : 2019/12/6 12:43
3 | # @Author : izcat
4 | # @Site : $ cnblogs.com/izcat
5 | # @File : mylexer.py
6 | # @Software : PyCharm
7 | # @Desc : 词法分析器
8 |
9 | from enum import Enum
10 | import math
11 |
12 |
13 | class TokenType(Enum):
14 | ORIGIN = "ORIGIN"
15 | SCALE = "SCALE"
16 | ROT = "ROT"
17 | IS = "IS"
18 | FOR = "FOR"
19 | FROM = "FROM"
20 | TO = "TO"
21 | STEP = "STEP"
22 | DRAW = "DRAW"
23 | T = "T"
24 | FUNC = "FUNCTION"
25 | CONST_ID = "CONST_ID"
26 | SEMICO = ';'
27 | L_BRACKET = '('
28 | R_BRACKET = ')'
29 | COMMA = ','
30 | PLUS = '+'
31 | MINUS = '-'
32 | MUL = '*'
33 | DIV = '/'
34 | POWER = '**'
35 | NONTOKEN = "NON"
36 | ERRTOKEN = "ERR"
37 | OF = "OF"
38 | COLOR = "COLOR"
39 |
40 |
41 | # print(TokenType.FUNC.name) ==> FUNC
42 | # print(TokenType.FUNC.value) ==> FUNCTION
43 | #
44 | class Token:
45 | def __init__(self, tokentype, lexeme, value=0.0, funcptr=None):
46 | self.tokenType = tokentype
47 | self.lexeme = lexeme
48 | self.value = value
49 | self.funcPtr = funcptr
50 |
51 | def show(self):
52 | print(self.tokenType.name.ljust(15), self.lexeme.ljust(15), str(self.value).ljust(15), self.funcPtr)
53 |
54 |
55 | # CONST_ID
56 | TokenTypeDict = dict(PI=Token(TokenType.CONST_ID, "PI", math.pi),
57 | E=Token(TokenType.CONST_ID, "E", math.e),
58 | T=Token(TokenType.T, "T"),
59 | ORIGIN=Token(TokenType.ORIGIN, "ORIGIN"),
60 | SCALE=Token(TokenType.SCALE, "SCALE"),
61 | ROT=Token(TokenType.ROT, "ROT"),
62 | IS=Token(TokenType.IS, "IS"),
63 | FOR=Token(TokenType.FOR, "FOR"),
64 | FROM=Token(TokenType.FROM, "FROM"),
65 | TO=Token(TokenType.TO, "TO"),
66 | STEP=Token(TokenType.STEP, "STEP"),
67 | DRAW=Token(TokenType.DRAW, "DRAW"),
68 | SIN=Token(TokenType.FUNC, "SIN", 0.0, math.sin),
69 | COS=Token(TokenType.FUNC, "COS", 0.0, math.cos),
70 | TAN=Token(TokenType.FUNC, "TAN", 0.0, math.tan),
71 | LN=Token(TokenType.FUNC, "LN", 0.0, math.log),
72 | EXP=Token(TokenType.FUNC, "EXP", 0.0, math.exp),
73 | SQRT=Token(TokenType.FUNC, "SQRT", 0.0, math.sqrt),
74 | OF=Token(TokenType.OF, "OF"),
75 | RED=Token(TokenType.COLOR, "RED"),
76 | GREEN=Token(TokenType.COLOR, "GREEN"),
77 | BLUE=Token(TokenType.COLOR, "BLUE"),
78 | YELLOW=Token(TokenType.COLOR, "YELLOW"),
79 | BLACK=Token(TokenType.COLOR, "BLACK"));
80 |
81 |
82 | def showTokens(tokens):
83 | print("Category".ljust(15), "Input".ljust(15), "Value".ljust(15), "FuncPtr")
84 | for token in tokens:
85 | token.show()
86 |
87 |
88 | # 没有使用 NONTOKEN
89 | # 利用 i Term Expression'
4 | # Expression' -> (PLUS | MINUS) Term Expression' | $
5 | #
6 | # Term -> Factor Term'
7 | # Term' -> (MUL | DIV) Factor | $
8 | #
9 | # Factor -> (PLUS | MINUS) Factor | Component
10 | #
11 | # Component -> Atom POWER Component | Atom
12 | #
13 | # Atom -> CONST_ID | T
14 | # | FUNC L_BRACKET Expression R_BRACKET
15 | # | L_BRACKET Expression R_BRACKET
16 | #
17 |
18 | # EBNF
19 | # Expression -> Term { (PLUS | MINUS) Term }
20 | #
21 | # Term -> Factor { (MUL | DIV) Factor }
22 | #
23 | # Factor -> (PLUS | MINUS) Factor | Component
24 | #
25 | # Component -> Atom POWER Component | Atom
26 | #
27 | # Atom -> CONST_ID | T
28 | # | FUNC L_BRACKET Expression R_BRACKET
29 | # | L_BRACKET Expression R_BRACKET
30 |
31 |
32 |
33 | from lexer import *
34 | import sys
35 | # 二叉树节点
36 | # + - * / ** T CONST_ID FUNC
37 | # '(' ')' 匹配过程中扔掉
38 | # 叶子节点: T CONST_ID
39 | # 非叶子节点: 非终结符
40 |
41 | T_value = 0.0
42 |
43 | class ExpNode:
44 | def __init__(self, token, left=None, right=None):
45 | self.token = token
46 | self.lson = left
47 | self.rson = right
48 | def addson(self, son):
49 | if self.lson==None:
50 | self.lson = son
51 | return self
52 | elif self.rson==None:
53 | self.rson = son
54 | return self
55 | else:
56 | print("Cannot add son!")
57 | exit(-1)
58 |
59 | def getValue(self):
60 | # 叶子节点
61 | if self.lson==None and self.rson==None:
62 | if self.token.tokenType==TokenType.CONST_ID:
63 | return self.token.value
64 | elif self.token.tokenType==TokenType.T:
65 | return T_value
66 | else:
67 | print("Expression Error")
68 | exit(-1)
69 |
70 | # 只有左子树 函数节点 or +5 or -5
71 | elif self.rson==None:
72 | if self.token.tokenType==TokenType.PLUS:
73 | return self.lson.getValue()
74 | elif self.token.tokenType==TokenType.MINUS:
75 | return -self.lson.getValue()
76 | elif self.token.tokenType==TokenType.FUNC:
77 | return self.token.funcPtr(self.lson.getValue())
78 | else:
79 | print("Expression Error")
80 | exit(-1)
81 | # 只有右子树
82 | # elif self.lson==None:
83 | # if self.token.tokenType==TokenType.PLUS:
84 | # return self.rson.getValue()
85 | # elif self.token.tokenType==TokenType.MINUS:
86 | # return -self.rson.getValue()
87 | # elif self.token.tokenType==TokenType.FUNC:
88 | # return self.token.funcptr(self.rson.getValue())
89 | # else:
90 | # print("Expression Error")
91 | else:
92 | if self.token.tokenType==TokenType.PLUS:
93 | return self.lson.getValue() + self.rson.getValue()
94 | elif self.token.tokenType==TokenType.MINUS:
95 | return self.lson.getValue() - self.rson.getValue()
96 | elif self.token.tokenType==TokenType.MUL:
97 | return self.lson.getValue() * self.rson.getValue()
98 | elif self.token.tokenType==TokenType.DIV:
99 | return self.lson.getValue() / self.rson.getValue()
100 | elif self.token.tokenType==TokenType.POWER:
101 | return self.lson.getValue() ** self.rson.getValue()
102 | else:
103 | print("Expression Error")
104 | exit(-1)
105 |
106 | def dfs(self, depth=0):
107 | if self.lson!=None:
108 | self.lson.dfs(depth+1)
109 | if self.rson!=None:
110 | self.rson.dfs(depth+1)
111 |
112 | print("Depth %d" % depth)
113 | self.token.show()
114 |
115 |
116 | tokenIter = None
117 | tokenNow = Token(TokenType.NONTOKEN, '')
118 |
119 | # 从词法分析器的tokens获得token
120 | def FetchToken():
121 | global tokenNow
122 | try:
123 | tokenNow = next(tokenIter)
124 | return tokenNow
125 | except StopIteration:
126 | sys.exit()
127 |
128 | def MatchToken(tokenType, show=False):
129 | if show:
130 | tokenNow.show()
131 | if tokenNow.tokenType==tokenType:
132 | FetchToken()
133 | else:
134 | print("Excepted ", tokenType, "received ", tokenNow.tokenType)
135 | print("error!")
136 | exit(-1)
137 |
138 | def Parser(string):
139 | global tokenIter # 必须要 global
140 | tokenList = Lexer(string)
141 | tokenIter = iter(tokenList)
142 | FetchToken()
143 | exp = Expression()
144 | print("--------------------")
145 |
146 | # exp.token.show()
147 | # print(exp.lson)
148 | # print(exp.rson)
149 | exp.dfs()
150 | print(exp.getValue())
151 |
152 | def Msg(op, str):
153 | if op==0:
154 | print("Enter %s" % str)
155 | else:
156 | print("Exit %s" % str)
157 |
158 | # 加法运算
159 | # 左结合
160 | # 新的 + - 为根节点
161 | # Example: 1+2-3
162 | # -
163 | # / \
164 | # + 3
165 | # / \
166 | # 1 2
167 | #
168 |
169 | def Expression():
170 | Msg(0, "Expression")
171 | left = Term()
172 | root = None
173 | while tokenNow.tokenType==TokenType.PLUS or tokenNow.tokenType==TokenType.MINUS:
174 | root = ExpNode(tokenNow)
175 | MatchToken(tokenNow.tokenType)
176 | right = Term()
177 | root.addson(left)
178 | root.addson(right)
179 | left = root
180 | # left.dfs()
181 | Msg(1, "Expression")
182 | return left
183 |
184 | # def Expression():
185 | # Msg(0, "Expression")
186 | # left = Term()
187 | # root = None
188 | # while tokenNow.tokenType==TokenType.PLUS or tokenNow.tokenType==TokenType.MINUS:
189 | # root = ExpNode(tokenNow)
190 | # MatchToken(tokenNow.tokenType)
191 | # right = Expression()
192 | # root.addson(left)
193 | # root.addson(right)
194 | # left = root
195 | # Msg(1, "Expression")
196 | # return left
197 |
198 | # 乘法运算
199 | # 左结合
200 | # 新的 * / 为根节点
201 | # Example: 1*2*3
202 | # *
203 | # / \
204 | # * 3
205 | # / \
206 | # 1 2
207 | def Term():
208 | Msg(0, "Term")
209 | left = Factor()
210 | root = None
211 | while tokenNow.tokenType==TokenType.MUL or tokenNow.tokenType==TokenType.DIV:
212 | root = ExpNode(tokenNow)
213 | MatchToken(tokenNow.tokenType)
214 | right = Factor()
215 | root.addson(left)
216 | root.addson(right)
217 | left = root
218 |
219 | Msg(1, "Term")
220 | return left
221 |
222 | def Factor():
223 | Msg(0, "Factor")
224 | if tokenNow.tokenType==TokenType.PLUS or tokenNow.tokenType==TokenType.MINUS:
225 | root = ExpNode(tokenNow)
226 | MatchToken(tokenNow.tokenType);
227 | son = Factor()
228 | root.addson(son)
229 | Msg(1, "Factor")
230 | return root
231 | else:
232 | Msg(1, "Factor")
233 | return Component()
234 |
235 | # 乘方运算
236 | # 右结合
237 | # 不支持 CONST_ID ** MINUS CONST_ID, 需要添括号
238 | def Component():
239 | Msg(0, "Component")
240 | left = Atom()
241 | if tokenNow.tokenType==TokenType.POWER:
242 | root = ExpNode(tokenNow)
243 | MatchToken(tokenNow.tokenType)
244 | right = Component()
245 |
246 | root.addson(left)
247 | root.addson(right)
248 | Msg(1, "Component")
249 | return root
250 | else:
251 | Msg(1, "Component")
252 | return left
253 |
254 | # 函数节点 FUNC <- CONST_ID | T
255 | # 叶子节点 CONST_ID | T
256 | def Atom():
257 | Msg(0, "Atom")
258 | if tokenNow.tokenType==TokenType.CONST_ID or tokenNow.tokenType==TokenType.T:
259 | root = ExpNode(tokenNow)
260 | MatchToken(tokenNow.tokenType)
261 | Msg(1, "Atom")
262 | return root
263 |
264 | elif tokenNow.tokenType==TokenType.FUNC:
265 | root = ExpNode(tokenNow)
266 | MatchToken(tokenNow.tokenType)
267 | MatchToken(TokenType.L_BRACKET)
268 | son = Expression()
269 | MatchToken(TokenType.R_BRACKET)
270 | root.addson(son)
271 | Msg(1, "Atom")
272 | return root
273 |
274 | elif tokenNow.tokenType==TokenType.L_BRACKET:
275 | MatchToken(TokenType.L_BRACKET)
276 | root = Expression()
277 | MatchToken(TokenType.R_BRACKET)
278 | Msg(1, "Atom")
279 | return root
280 | else:
281 | print("Atom Error!")
282 |
283 |
284 | # Parser("1+2-3")
285 | # exp = "sin(sqrt(sqrt(sqrt(sqrt(pi**2**3))))**2/2)" => 1.0
286 | # exp = "sin((2+5)-3**(5)-100*cos(3)-2)"
287 | # exp = "-152.143134+3.2**(5.0)+(1.3-34)*2/2-1*2**5*245-1+2-3*4/5-(6)*7-(((232)))*((2**5)-5)**1.4"
288 | # 不支持 a**-N
289 | # exp = "2**(-1)"
290 | #
291 |
292 | Parser(exp)
293 | print(eval(exp))
--------------------------------------------------------------------------------
/version2/myparser.py:
--------------------------------------------------------------------------------
1 | from mylexer import Lexer
2 | from expnode import *
3 | from mypainter import *
4 | import math
5 | import sys
6 |
7 | ########################################
8 | # 语法分析器
9 | ########################################
10 |
11 | tokenIter = None
12 | tokenNow = Token(TokenType.NONTOKEN, '')
13 | showProcess = False
14 |
15 | Origin_x = 0.0
16 | Origin_y = 0.0
17 | Scale_x = 1.0
18 | Scale_y = 1.0
19 | Rot_angle = 0.0
20 |
21 |
22 |
23 | def setDefaultValue(show):
24 | global Origin_x
25 | global Origin_y
26 | global Scale_x
27 | global Scale_y
28 | global Rot_angle
29 | global showProcess # 没有global showProcess一直为False
30 | Origin_x = 0.0
31 | Origin_y = 0.0
32 | Scale_x = 1.0
33 | Scale_y = 1.0
34 | Rot_angle = 0.0
35 | showProcess = show
36 |
37 |
38 |
39 | # 从词法分析器的tokens获得token
40 | def FetchToken():
41 | global tokenNow
42 | try:
43 | tokenNow = next(tokenIter)
44 | return tokenNow
45 | except StopIteration:
46 | sys.exit()
47 |
48 | def MatchToken(tokenType, show=False):
49 | if show:
50 | tokenNow.show()
51 | if tokenNow.tokenType==tokenType:
52 | FetchToken()
53 | return True
54 | else:
55 | print("Excepted ", tokenType, "received ", tokenNow.tokenType)
56 | print("error!")
57 | return False
58 | exit(-1)
59 |
60 |
61 | def Msg(op, str):
62 | global showProcess
63 | if not showProcess:
64 | return
65 | if op==0:
66 | print("Enter %s" % str)
67 | else:
68 | print("Exit %s" % str)
69 |
70 |
71 | ##########################################
72 | # 表达式
73 | # ########################################
74 |
75 | # 二叉树节点
76 | # + - * / ** T CONST_ID FUNC
77 | # '(' ')' 匹配过程中扔掉
78 | # 叶子节点: T CONST_ID
79 | # 非叶子节点: 非终结符
80 |
81 | # 加法运算
82 | # 左结合
83 | # 新的 + - 为根节点
84 | # Example: 1+2-3
85 | # -
86 | # / \
87 | # + 3
88 | # / \
89 | # 1 2
90 | #
91 |
92 | def Expression():
93 | Msg(0, "Expression")
94 | left = Term()
95 | root = None
96 | while tokenNow.tokenType==TokenType.PLUS or tokenNow.tokenType==TokenType.MINUS:
97 | root = ExpNode(tokenNow)
98 | MatchToken(tokenNow.tokenType)
99 | right = Term()
100 | root.addson(left)
101 | root.addson(right)
102 | left = root
103 | # left.dfs()
104 | Msg(1, "Expression")
105 | return left
106 |
107 | # def Expression():
108 | # Msg(0, "Expression")
109 | # left = Term()
110 | # root = None
111 | # while tokenNow.tokenType==TokenType.PLUS or tokenNow.tokenType==TokenType.MINUS:
112 | # root = ExpNode(tokenNow)
113 | # MatchToken(tokenNow.tokenType)
114 | # right = Expression()
115 | # root.addson(left)
116 | # root.addson(right)
117 | # left = root
118 | # Msg(1, "Expression")
119 | # return left
120 |
121 | # 乘法运算
122 | # 左结合
123 | # 新的 * / 为根节点
124 | # Example: 1*2*3
125 | # *
126 | # / \
127 | # * 3
128 | # / \
129 | # 1 2
130 | def Term():
131 | Msg(0, "Term")
132 | left = Factor()
133 | root = None
134 | while tokenNow.tokenType==TokenType.MUL or tokenNow.tokenType==TokenType.DIV:
135 | root = ExpNode(tokenNow)
136 | MatchToken(tokenNow.tokenType)
137 | right = Factor()
138 | root.addson(left)
139 | root.addson(right)
140 | left = root
141 |
142 | Msg(1, "Term")
143 | return left
144 |
145 | def Factor():
146 | Msg(0, "Factor")
147 | if tokenNow.tokenType==TokenType.PLUS or tokenNow.tokenType==TokenType.MINUS:
148 | root = ExpNode(tokenNow)
149 | MatchToken(tokenNow.tokenType);
150 | son = Factor()
151 | root.addson(son)
152 | Msg(1, "Factor")
153 | return root
154 | else:
155 | Msg(1, "Factor")
156 | return Component()
157 |
158 | # 乘方运算
159 | # 右结合
160 | # 不支持 CONST_ID ** MINUS CONST_ID, 需要添括号
161 | def Component():
162 | Msg(0, "Component")
163 | left = Atom()
164 | if tokenNow.tokenType==TokenType.POWER:
165 | root = ExpNode(tokenNow)
166 | MatchToken(tokenNow.tokenType)
167 | right = Component()
168 |
169 | root.addson(left)
170 | root.addson(right)
171 | Msg(1, "Component")
172 | return root
173 | else:
174 | Msg(1, "Component")
175 | return left
176 |
177 | # 函数节点 FUNC <- CONST_ID | T
178 | # 叶子节点 CONST_ID | T
179 | def Atom():
180 | Msg(0, "Atom")
181 | if tokenNow.tokenType==TokenType.CONST_ID or tokenNow.tokenType==TokenType.T:
182 | root = ExpNode(tokenNow)
183 | MatchToken(tokenNow.tokenType)
184 | Msg(1, "Atom")
185 | return root
186 |
187 | elif tokenNow.tokenType==TokenType.FUNC:
188 | root = ExpNode(tokenNow)
189 | MatchToken(tokenNow.tokenType)
190 | MatchToken(TokenType.L_BRACKET)
191 | son = Expression()
192 | MatchToken(TokenType.R_BRACKET)
193 | root.addson(son)
194 | Msg(1, "Atom")
195 | return root
196 |
197 | elif tokenNow.tokenType==TokenType.L_BRACKET:
198 | MatchToken(TokenType.L_BRACKET)
199 | root = Expression()
200 | MatchToken(TokenType.R_BRACKET)
201 | Msg(1, "Atom")
202 | return root
203 | else:
204 | print("Atom Error!")
205 |
206 |
207 |
208 | def OriginStatement():
209 | Msg(0, "OriginStatement")
210 | global Origin_x
211 | global Origin_y
212 | MatchToken(TokenType.ORIGIN)
213 | MatchToken(TokenType.IS)
214 | MatchToken(TokenType.L_BRACKET)
215 | Origin_x = Expression().getValue()
216 | MatchToken(TokenType.COMMA)
217 | Origin_y = Expression().getValue()
218 | MatchToken(TokenType.R_BRACKET)
219 |
220 | Msg(1, "OriginStatement")
221 |
222 | def ScaleStatement():
223 | Msg(0, "ScaleStatement")
224 | global Scale_x
225 | global Scale_y
226 | MatchToken(TokenType.SCALE)
227 | MatchToken(TokenType.IS)
228 | MatchToken(TokenType.L_BRACKET)
229 | Scale_x = Expression().getValue()
230 | MatchToken(TokenType.COMMA)
231 | Scale_y = Expression().getValue()
232 | # print(Scale_x)
233 | # print(Scale_y)
234 | MatchToken(TokenType.R_BRACKET)
235 |
236 | Msg(1, "ScaleStatement")
237 |
238 | def RotStatement():
239 | Msg(0, "RotStatement")
240 | global Rot_angle
241 | MatchToken(TokenType.ROT)
242 | MatchToken(TokenType.IS)
243 | Rot_angle = Expression().getValue()
244 |
245 | Msg(1, "RotStatement")
246 |
247 | def ForStatement():
248 | Msg(0, "ForStatement")
249 | MatchToken(TokenType.FOR)
250 | MatchToken(TokenType.T)
251 | MatchToken(TokenType.FROM)
252 | T_start = Expression().getValue()
253 | MatchToken(TokenType.TO)
254 | T_end = Expression().getValue()
255 | MatchToken(TokenType.STEP)
256 | T_step = Expression().getValue()
257 |
258 |
259 | MatchToken(TokenType.DRAW)
260 | MatchToken(TokenType.L_BRACKET)
261 | Point_x = Expression()
262 | MatchToken(TokenType.COMMA)
263 | Point_y = Expression()
264 | MatchToken(TokenType.R_BRACKET)
265 |
266 | # global T_value
267 | Painter.set(Origin_x, Origin_y, Scale_x, Scale_y, Rot_angle)
268 | Painter.paint(T_start, T_end, T_step, Point_x, Point_y)
269 |
270 | Msg(1, "ForStatement")
271 |
272 | # Statement -> OriginStatement | ScaleStatement | RotStatement | ForStatement
273 | def Statement():
274 | Msg(0, "Statement")
275 | if tokenNow.tokenType==TokenType.ORIGIN:
276 | OriginStatement()
277 | elif tokenNow.tokenType==TokenType.SCALE:
278 | ScaleStatement()
279 | elif tokenNow.tokenType==TokenType.ROT:
280 | RotStatement()
281 | elif tokenNow.tokenType==TokenType.FOR:
282 | ForStatement()
283 | else:
284 | print("Statement Error!")
285 |
286 | Msg(0, "Statement")
287 |
288 |
289 | def Program():
290 | Msg(0, "Program")
291 | while tokenNow.tokenType!=TokenType.NONTOKEN:
292 | Statement()
293 | matched = MatchToken(TokenType.SEMICO)
294 | if not matched:
295 | print("Program Error")
296 | break
297 | Msg(1, "Program")
298 |
299 | def Parser(string, show=False, paint=False):
300 | global tokenIter # 必须要 global
301 |
302 | # 调用词法分析器 得到记号表
303 | tokenList = Lexer(string)
304 | tokenIter = iter(tokenList)
305 |
306 | setDefaultValue(show)
307 | FetchToken()
308 | Program()
309 |
310 | if paint:
311 | Painter.showPic()
312 |
313 |
314 |
315 | def test():
316 | # Parser("--hello fad\n //fadfjl\n ROT is pi/2 ; SCALE is ( 1, 2*2); \n ORIGIN is ((2), 242/4);")
317 | str = "ORigin is (-30, 0); SCALE is ( 20, 25); for t from 0 to 2*pi step 0.01 draw (sin(t), cos(t)); SCALE is ( 30, 20); for t from -1 to 1 step 0.01 draw (2, t); FOR t from 0 to 1 step 0.01 draw (2+t, t);for t from -1 to 1 step 0.01 draw (2, t); FOR t from 0 to 1 step 0.01 draw (2+t, -t);for t from 0 to 2*pi step 0.01 draw (1+3*sin(t), 3*cos(t)); "
318 |
319 | Parser(str);
320 | # print("(%f, %f)" % (Origin_x, Origin_y))
321 | # print("(%f, %f)" % (Scale_x, Scale_y))
322 | # print("%f" % Rot_angle)
323 |
324 | Painter.showPic()
325 |
326 | # test()
--------------------------------------------------------------------------------
/version3/myparser.py:
--------------------------------------------------------------------------------
1 | from mylexer import Lexer
2 | from expnode import *
3 | from mypainter import *
4 | import math
5 | import sys
6 |
7 | ########################################
8 | # 语法分析器
9 | ########################################
10 |
11 | tokenIter = None
12 | tokenNow = Token(TokenType.NONTOKEN, '')
13 | showProcess = False
14 |
15 | Origin_x = 0.0
16 | Origin_y = 0.0
17 | Scale_x = 1.0
18 | Scale_y = 1.0
19 | Rot_angle = 0.0
20 | Draw_color = 'k'
21 |
22 |
23 | def setDefaultValue(show):
24 | global Origin_x
25 | global Origin_y
26 | global Scale_x
27 | global Scale_y
28 | global Rot_angle
29 | global showProcess # 没有global showProcess一直为False
30 | global Draw_color
31 | Origin_x = 0.0
32 | Origin_y = 0.0
33 | Scale_x = 1.0
34 | Scale_y = 1.0
35 | Rot_angle = 0.0
36 | showProcess = show
37 | Draw_color = 'k'
38 |
39 |
40 |
41 | # 从词法分析器的tokens获得token
42 | def FetchToken():
43 | global tokenNow
44 | try:
45 | tokenNow = next(tokenIter)
46 | return tokenNow
47 | except StopIteration:
48 | sys.exit()
49 |
50 | def MatchToken(tokenType, show=False):
51 | if show:
52 | tokenNow.show()
53 | if tokenNow.tokenType==tokenType:
54 | FetchToken()
55 | return True
56 | else:
57 | print("Excepted ", tokenType, "received ", tokenNow.tokenType)
58 | print("error!")
59 | return False
60 | exit(-1)
61 |
62 |
63 | def Msg(op, str):
64 | global showProcess
65 | if not showProcess:
66 | return
67 | if op==0:
68 | print("Enter %s" % str)
69 | else:
70 | print("Exit %s" % str)
71 |
72 |
73 | ##########################################
74 | # 表达式
75 | # ########################################
76 |
77 | # 二叉树节点
78 | # + - * / ** T CONST_ID FUNC
79 | # '(' ')' 匹配过程中扔掉
80 | # 叶子节点: T CONST_ID
81 | # 非叶子节点: 非终结符
82 |
83 | # 加法运算
84 | # 左结合
85 | # 新的 + - 为根节点
86 | # Example: 1+2-3
87 | # -
88 | # / \
89 | # + 3
90 | # / \
91 | # 1 2
92 | #
93 |
94 | def Expression():
95 | Msg(0, "Expression")
96 | left = Term()
97 | root = None
98 | while tokenNow.tokenType==TokenType.PLUS or tokenNow.tokenType==TokenType.MINUS:
99 | root = ExpNode(tokenNow)
100 | MatchToken(tokenNow.tokenType)
101 | right = Term()
102 | root.addson(left)
103 | root.addson(right)
104 | left = root
105 | # left.dfs()
106 | Msg(1, "Expression")
107 | return left
108 |
109 | # def Expression():
110 | # Msg(0, "Expression")
111 | # left = Term()
112 | # root = None
113 | # while tokenNow.tokenType==TokenType.PLUS or tokenNow.tokenType==TokenType.MINUS:
114 | # root = ExpNode(tokenNow)
115 | # MatchToken(tokenNow.tokenType)
116 | # right = Expression()
117 | # root.addson(left)
118 | # root.addson(right)
119 | # left = root
120 | # Msg(1, "Expression")
121 | # return left
122 |
123 | # 乘法运算
124 | # 左结合
125 | # 新的 * / 为根节点
126 | # Example: 1*2*3
127 | # *
128 | # / \
129 | # * 3
130 | # / \
131 | # 1 2
132 | def Term():
133 | Msg(0, "Term")
134 | left = Factor()
135 | root = None
136 | while tokenNow.tokenType==TokenType.MUL or tokenNow.tokenType==TokenType.DIV:
137 | root = ExpNode(tokenNow)
138 | MatchToken(tokenNow.tokenType)
139 | right = Factor()
140 | root.addson(left)
141 | root.addson(right)
142 | left = root
143 |
144 | Msg(1, "Term")
145 | return left
146 |
147 | def Factor():
148 | Msg(0, "Factor")
149 | if tokenNow.tokenType==TokenType.PLUS or tokenNow.tokenType==TokenType.MINUS:
150 | root = ExpNode(tokenNow)
151 | MatchToken(tokenNow.tokenType);
152 | son = Factor()
153 | root.addson(son)
154 | Msg(1, "Factor")
155 | return root
156 | else:
157 | Msg(1, "Factor")
158 | return Component()
159 |
160 | # 乘方运算
161 | # 右结合
162 | # 不支持 CONST_ID ** MINUS CONST_ID, 需要添括号
163 | def Component():
164 | Msg(0, "Component")
165 | left = Atom()
166 | if tokenNow.tokenType==TokenType.POWER:
167 | root = ExpNode(tokenNow)
168 | MatchToken(tokenNow.tokenType)
169 | right = Component()
170 |
171 | root.addson(left)
172 | root.addson(right)
173 | Msg(1, "Component")
174 | return root
175 | else:
176 | Msg(1, "Component")
177 | return left
178 |
179 | # 函数节点 FUNC <- CONST_ID | T
180 | # 叶子节点 CONST_ID | T
181 | def Atom():
182 | Msg(0, "Atom")
183 | if tokenNow.tokenType==TokenType.CONST_ID or tokenNow.tokenType==TokenType.T:
184 | root = ExpNode(tokenNow)
185 | MatchToken(tokenNow.tokenType)
186 | Msg(1, "Atom")
187 | return root
188 |
189 | elif tokenNow.tokenType==TokenType.FUNC:
190 | root = ExpNode(tokenNow)
191 | MatchToken(tokenNow.tokenType)
192 | MatchToken(TokenType.L_BRACKET)
193 | son = Expression()
194 | MatchToken(TokenType.R_BRACKET)
195 | root.addson(son)
196 | Msg(1, "Atom")
197 | return root
198 |
199 | elif tokenNow.tokenType==TokenType.L_BRACKET:
200 | MatchToken(TokenType.L_BRACKET)
201 | root = Expression()
202 | MatchToken(TokenType.R_BRACKET)
203 | Msg(1, "Atom")
204 | return root
205 | else:
206 | print("Atom Error!")
207 |
208 |
209 |
210 | def OriginStatement():
211 | Msg(0, "OriginStatement")
212 | global Origin_x
213 | global Origin_y
214 | MatchToken(TokenType.ORIGIN)
215 | MatchToken(TokenType.IS)
216 | MatchToken(TokenType.L_BRACKET)
217 | Origin_x = Expression().getValue()
218 | MatchToken(TokenType.COMMA)
219 | Origin_y = Expression().getValue()
220 | MatchToken(TokenType.R_BRACKET)
221 |
222 | Msg(1, "OriginStatement")
223 |
224 | def ScaleStatement():
225 | Msg(0, "ScaleStatement")
226 | global Scale_x
227 | global Scale_y
228 | MatchToken(TokenType.SCALE)
229 | MatchToken(TokenType.IS)
230 | MatchToken(TokenType.L_BRACKET)
231 | Scale_x = Expression().getValue()
232 | MatchToken(TokenType.COMMA)
233 | Scale_y = Expression().getValue()
234 | # print(Scale_x)
235 | # print(Scale_y)
236 | MatchToken(TokenType.R_BRACKET)
237 |
238 | Msg(1, "ScaleStatement")
239 |
240 | def RotStatement():
241 | Msg(0, "RotStatement")
242 | global Rot_angle
243 | MatchToken(TokenType.ROT)
244 | MatchToken(TokenType.IS)
245 | Rot_angle = Expression().getValue()
246 |
247 | Msg(1, "RotStatement")
248 |
249 | def getColor():
250 | if tokenNow.tokenType==TokenType.COLOR:
251 | if tokenNow.lexeme=='RED':
252 | color = 'r'
253 | elif tokenNow.lexeme=='GREEN':
254 | color = 'g'
255 | elif tokenNow.lexeme=='BLUE':
256 | color = 'b'
257 | elif tokenNow.lexeme=='YELLOW':
258 | color = 'y'
259 | elif tokenNow.lexeme=='BLACK':
260 | color = 'k'
261 | MatchToken(TokenType.COLOR)
262 | return color
263 | # else:
264 | # print("GetColor Error")
265 | else:
266 | print("GetColor Error")
267 |
268 | def ForStatement():
269 | Msg(0, "ForStatement")
270 | MatchToken(TokenType.FOR)
271 | MatchToken(TokenType.T)
272 | MatchToken(TokenType.FROM)
273 | T_start = Expression().getValue()
274 | MatchToken(TokenType.TO)
275 | T_end = Expression().getValue()
276 | MatchToken(TokenType.STEP)
277 | T_step = Expression().getValue()
278 |
279 |
280 | MatchToken(TokenType.DRAW)
281 | MatchToken(TokenType.L_BRACKET)
282 | Point_x = Expression()
283 | print(Point_x.dfs())
284 | MatchToken(TokenType.COMMA)
285 | Point_y = Expression()
286 | MatchToken(TokenType.R_BRACKET)
287 |
288 | # 自定义颜色
289 | global Draw_color
290 | if tokenNow.tokenType==TokenType.OF:
291 | MatchToken(TokenType.OF)
292 | Draw_color = getColor()
293 | # global T_value
294 | Painter.set(Origin_x, Origin_y, Scale_x, Scale_y, Rot_angle)
295 | Painter.paint(T_start, T_end, T_step, Point_x, Point_y, Draw_color)
296 |
297 | Msg(1, "ForStatement")
298 |
299 | # Statement -> OriginStatement | ScaleStatement | RotStatement | ForStatement
300 | def Statement():
301 | Msg(0, "Statement")
302 | if tokenNow.tokenType==TokenType.ORIGIN:
303 | OriginStatement()
304 | elif tokenNow.tokenType==TokenType.SCALE:
305 | ScaleStatement()
306 | elif tokenNow.tokenType==TokenType.ROT:
307 | RotStatement()
308 | elif tokenNow.tokenType==TokenType.FOR:
309 | ForStatement()
310 | else:
311 | print("Statement Error!")
312 | exit(-1)
313 |
314 | Msg(0, "Statement")
315 |
316 |
317 | def Program():
318 | Msg(0, "Program")
319 | while tokenNow.tokenType!=TokenType.NONTOKEN:
320 | Statement()
321 | matched = MatchToken(TokenType.SEMICO)
322 | if not matched:
323 | print("Program Error")
324 | exit(-1)
325 | Msg(1, "Program")
326 | return True
327 |
328 | def Parser(string, show=False, paint=False):
329 | global tokenIter # 必须要 global
330 |
331 | # 调用词法分析器 得到记号表
332 | tokenList = Lexer(string)
333 | tokenIter = iter(tokenList)
334 |
335 | setDefaultValue(show)
336 | FetchToken()
337 | state = Program()
338 |
339 | if paint and state:
340 | Painter.showPic()
341 |
342 |
343 |
344 | def test():
345 | # Parser("--hello fad\n //fadfjl\n ROT is pi/2 ; SCALE is ( 1, 2*2); \n ORIGIN is ((2), 242/4);")
346 | str = "ORigin is (-30, 0); SCALE is ( 20, 25); for t from 0 to 2*pi step 0.01 draw (sin(t), cos(t)); SCALE is ( 30, 20); for t from -1 to 1 step 0.01 draw (2, t); FOR t from 0 to 1 step 0.01 draw (2+t, t);for t from -1 to 1 step 0.01 draw (2, t); FOR t from 0 to 1 step 0.01 draw (2+t, -t);for t from 0 to 2*pi step 0.01 draw (1+3*sin(t), 3*cos(t)); "
347 |
348 | Parser(str);
349 | # print("(%f, %f)" % (Origin_x, Origin_y))
350 | # print("(%f, %f)" % (Scale_x, Scale_y))
351 | # print("%f" % Rot_angle)
352 |
353 | Painter.showPic()
354 |
355 | # test()
--------------------------------------------------------------------------------
/version4/myparser.py:
--------------------------------------------------------------------------------
1 | from mylexer import Lexer
2 | from mylexer import TokenType
3 | from mylexer import Token
4 | from expnode import ExpNode
5 | import math
6 | import sys
7 |
8 | ########################################
9 | # 语法分析器
10 | ########################################
11 |
12 | tokenIter = None
13 | tokenNow = None
14 | showProcess = False
15 |
16 |
17 | def setDefaultValue(show):
18 | global showProcess
19 | showProcess = show
20 |
21 |
22 | # 从词法分析器的tokens获得token
23 | def FetchToken():
24 | global tokenNow
25 | try:
26 | tokenNow = next(tokenIter)
27 | return tokenNow
28 | except StopIteration:
29 | sys.exit()
30 |
31 | def MatchToken(tokenType, show=False):
32 | if show:
33 | tokenNow.show()
34 | if tokenNow.tokenType==tokenType:
35 | FetchToken()
36 | return True
37 | else:
38 | print("Excepted ", tokenType, "received ", tokenNow.tokenType)
39 | print("error!")
40 | return False
41 | exit(-1)
42 |
43 | # level 递归层次
44 | # op=0 进入
45 | # op=1 退出
46 | # showProcess Painter调用不显示信息
47 | def Msg(level, str, op=1):
48 | global showProcess
49 | if not showProcess:
50 | return
51 | if op==0:
52 | print(" "*level+ "Enter --> %s" % str)
53 | else:
54 | print(" "*level+ "Exit <-- %s" % str)
55 |
56 |
57 | ##########################################
58 | # 表达式
59 | # ########################################
60 |
61 | # 二叉树节点
62 | # + - * / ** T CONST_ID FUNC
63 | # '(' ')' 匹配过程中扔掉
64 | # 叶子节点: T CONST_ID
65 | # 非叶子节点: 非终结符
66 |
67 | # 加法运算
68 | # 左结合
69 | # 新的 + - 为根节点
70 | # Example: 1+2-3
71 | # -
72 | # / \
73 | # + 3
74 | # / \
75 | # 1 2
76 | #
77 |
78 | def Expression(level):
79 | Msg(level, "Expression", 0)
80 | left = Term(level+1)
81 | root = None
82 | while tokenNow.tokenType==TokenType.PLUS or tokenNow.tokenType==TokenType.MINUS:
83 | root = ExpNode(tokenNow)
84 | MatchToken(tokenNow.tokenType)
85 | right = Term(level+1)
86 | root.addson(left)
87 | root.addson(right)
88 | left = root
89 | # left.dfs()
90 | Msg(level, "Expression")
91 | return left
92 |
93 | # def Expression():
94 | # Msg(0, "Expression")
95 | # left = Term()
96 | # root = None
97 | # while tokenNow.tokenType==TokenType.PLUS or tokenNow.tokenType==TokenType.MINUS:
98 | # root = ExpNode(tokenNow)
99 | # MatchToken(tokenNow.tokenType)
100 | # right = Expression()
101 | # root.addson(left)
102 | # root.addson(right)
103 | # left = root
104 | # Msg(1, "Expression")
105 | # return left
106 |
107 | # 乘法运算
108 | # 左结合
109 | # 新的 * / 为根节点
110 | # Example: 1*2*3
111 | # *
112 | # / \
113 | # * 3
114 | # / \
115 | # 1 2
116 | def Term(level):
117 | Msg(level, "Term", 0)
118 | left = Factor(level)
119 | root = None
120 | while tokenNow.tokenType==TokenType.MUL or tokenNow.tokenType==TokenType.DIV:
121 | root = ExpNode(tokenNow)
122 | MatchToken(tokenNow.tokenType)
123 | right = Factor(level+1)
124 | root.addson(left)
125 | root.addson(right)
126 | left = root
127 |
128 | Msg(level, "Term")
129 | return left
130 |
131 | def Factor(level):
132 | Msg(level, "Factor", 0)
133 | if tokenNow.tokenType==TokenType.PLUS or tokenNow.tokenType==TokenType.MINUS:
134 | root = ExpNode(tokenNow)
135 | MatchToken(tokenNow.tokenType);
136 | son = Factor(level+1)
137 | root.addson(son)
138 | Msg(level, "Factor")
139 | return root
140 | else:
141 | Msg(level, "Factor")
142 | return Component(level+1)
143 |
144 | # 乘方运算
145 | # 右结合
146 | # 不支持 CONST_ID ** MINUS CONST_ID, 需要添括号
147 | def Component(level):
148 | Msg(level, "Component", 0)
149 | left = Atom(level)
150 | if tokenNow.tokenType==TokenType.POWER:
151 | root = ExpNode(tokenNow)
152 | MatchToken(tokenNow.tokenType)
153 | right = Component(level+1)
154 |
155 | root.addson(left)
156 | root.addson(right)
157 | Msg(level, "Component")
158 | return root
159 | else:
160 | Msg(level, "Component")
161 | return left
162 |
163 | # 函数节点 FUNC <- CONST_ID | T
164 | # 叶子节点 CONST_ID | T
165 | def Atom(level):
166 | Msg(level, "Atom", 0)
167 | if tokenNow.tokenType==TokenType.CONST_ID or tokenNow.tokenType==TokenType.T:
168 | root = ExpNode(tokenNow)
169 | MatchToken(tokenNow.tokenType)
170 | Msg(level, "Atom")
171 | return root
172 |
173 | elif tokenNow.tokenType==TokenType.FUNC:
174 | root = ExpNode(tokenNow)
175 | MatchToken(tokenNow.tokenType)
176 | MatchToken(TokenType.L_BRACKET)
177 | son = Expression(level+1)
178 | MatchToken(TokenType.R_BRACKET)
179 | root.addson(son)
180 | Msg(level, "Atom")
181 | return root
182 |
183 | elif tokenNow.tokenType==TokenType.L_BRACKET:
184 | MatchToken(TokenType.L_BRACKET)
185 | root = Expression(level+1)
186 | MatchToken(TokenType.R_BRACKET)
187 | Msg(level, "Atom")
188 | return root
189 | else:
190 | print("Atom Error!")
191 |
192 |
193 |
194 | def OriginStatement(level):
195 | Msg(level, "OriginStatement", 0)
196 | MatchToken(TokenType.ORIGIN)
197 | MatchToken(TokenType.IS)
198 | MatchToken(TokenType.L_BRACKET)
199 | Origin_x = Expression(level+1)
200 | MatchToken(TokenType.COMMA)
201 | Origin_y = Expression(level+1)
202 | MatchToken(TokenType.R_BRACKET)
203 |
204 | Msg(level, "OriginStatement")
205 | return ["OriginStatement", Origin_x, Origin_y]
206 |
207 | def ScaleStatement(level):
208 | Msg(level, "ScaleStatement", 0)
209 | MatchToken(TokenType.SCALE)
210 | MatchToken(TokenType.IS)
211 | MatchToken(TokenType.L_BRACKET)
212 | Scale_x = Expression(level+1)
213 | MatchToken(TokenType.COMMA)
214 | Scale_y = Expression(level+1)
215 | # print(Scale_x)
216 | # print(Scale_y)
217 | MatchToken(TokenType.R_BRACKET)
218 |
219 | Msg(level, "ScaleStatement")
220 | return ["ScaleStatement", Scale_x, Scale_y]
221 |
222 | def RotStatement(level):
223 | Msg(level, "RotStatement", 0)
224 | MatchToken(TokenType.ROT)
225 | MatchToken(TokenType.IS)
226 | Rot_angle = Expression(level+1)
227 |
228 | Msg(level, "RotStatement")
229 | return ["RotStatement", Rot_angle]
230 |
231 | def getColor():
232 | if tokenNow.tokenType==TokenType.COLOR:
233 | if tokenNow.lexeme=='RED':
234 | color = 'r'
235 | elif tokenNow.lexeme=='GREEN':
236 | color = 'g'
237 | elif tokenNow.lexeme=='BLUE':
238 | color = 'b'
239 | elif tokenNow.lexeme=='YELLOW':
240 | color = 'y'
241 | elif tokenNow.lexeme=='BLACK':
242 | color = 'k'
243 | MatchToken(TokenType.COLOR)
244 | return color
245 | # else:
246 | # print("GetColor Error")
247 | else:
248 | print("GetColor Error")
249 |
250 | def ForStatement(level):
251 | Msg(level, "ForStatement", 0)
252 | MatchToken(TokenType.FOR)
253 | MatchToken(TokenType.T)
254 | MatchToken(TokenType.FROM)
255 | T_start = Expression(level+1)
256 | MatchToken(TokenType.TO)
257 | T_end = Expression(level+1)
258 | MatchToken(TokenType.STEP)
259 | T_step = Expression(level+1)
260 |
261 |
262 | MatchToken(TokenType.DRAW)
263 | MatchToken(TokenType.L_BRACKET)
264 | Point_x = Expression(level+1)
265 | # print(Point_x.dfs())
266 | MatchToken(TokenType.COMMA)
267 | Point_y = Expression(level+1)
268 | MatchToken(TokenType.R_BRACKET)
269 |
270 | # 自定义颜色
271 | Draw_color = None
272 | if tokenNow.tokenType==TokenType.OF:
273 | MatchToken(TokenType.OF)
274 | Draw_color = getColor()
275 | # global T_value
276 | # Painter.set(Origin_x, Origin_y, Scale_x, Scale_y, Rot_angle)
277 | # Painter.paint(T_start, T_end, T_step, Point_x, Point_y, Draw_color)
278 |
279 | Msg(level, "ForStatement")
280 | return ["ForStatement", T_start, T_end, T_step, Point_x, Point_y, Draw_color]
281 |
282 | # Statement -> OriginStatement | ScaleStatement | RotStatement | ForStatement
283 | def Statement(level):
284 | Msg(level, "Statement", 0)
285 | statement = None
286 | if tokenNow.tokenType==TokenType.ORIGIN:
287 | statement = OriginStatement(level+1)
288 | elif tokenNow.tokenType==TokenType.SCALE:
289 | statement = ScaleStatement(level+1)
290 | elif tokenNow.tokenType==TokenType.ROT:
291 | statement = RotStatement(level+1)
292 | elif tokenNow.tokenType==TokenType.FOR:
293 | statement = ForStatement(level+1)
294 | else:
295 | print("Statement Error!")
296 | exit(-1)
297 |
298 | Msg(level, "Statement")
299 | return statement
300 |
301 |
302 | def Program(level=0):
303 | Msg(level, "Program", 0)
304 | statements = []
305 | while tokenNow.tokenType!=TokenType.NONTOKEN:
306 | tmpstatement = Statement(level+1)
307 | matched = MatchToken(TokenType.SEMICO)
308 | if matched:
309 | statements.append(tmpstatement)
310 | else:
311 | print("Program Error")
312 | exit(-1)
313 | Msg(level, "Program")
314 | return statements
315 |
316 | def Parser(string, show=False):
317 | global tokenIter # 必须要 global
318 |
319 | # 调用词法分析器 得到记号表
320 | tokenList = Lexer(string)
321 | tokenIter = iter(tokenList)
322 |
323 | setDefaultValue(show)
324 | FetchToken()
325 | return Program()
326 |
327 |
328 | def test():
329 | # Parser("--hello fad\n //fadfjl\n ROT is pi/2 ; SCALE is ( 1, 2*2); \n ORIGIN is ((2), 242/4);")
330 | str = "ORigin is (-30, 0); SCALE is ( 20, 25); for t from 0 to 2*pi step 0.01 draw (sin(t), cos(t)); SCALE is ( 30, 20); for t from -1 to 1 step 0.01 draw (2, t); FOR t from 0 to 1 step 0.01 draw (2+t, t);for t from -1 to 1 step 0.01 draw (2, t); FOR t from 0 to 1 step 0.01 draw (2+t, -t);for t from 0 to 2*pi step 0.01 draw (1+3*sin(t), 3*cos(t)); "
331 |
332 | Parser(str);
333 | # print("(%f, %f)" % (Origin_x, Origin_y))
334 | # print("(%f, %f)" % (Scale_x, Scale_y))
335 | # print("%f" % Rot_angle)
336 |
337 |
338 | # test()
--------------------------------------------------------------------------------
/Interpreter4FPL/myparser.py:
--------------------------------------------------------------------------------
1 | #-*- coding:utf-8 -*-
2 | # @Time : 2019/12/6 12:53
3 | # @Author : izcat
4 | # @Site : cnblogs.com/izcat
5 | # @File : myparser.py
6 | # @Software : PyCharm
7 | # @Desc : 语法分析器
8 |
9 | from mylexer import Lexer
10 | from mylexer import TokenType
11 | from mylexer import Token
12 | from expnode import ExpNode
13 | import math
14 | import sys
15 |
16 | ########################################
17 | # 语法分析器
18 | ########################################
19 |
20 | tokenIter = None
21 | tokenNow = None
22 | showProcess = False
23 |
24 |
25 | def setDefaultValue(show):
26 | global showProcess
27 | showProcess = show
28 |
29 |
30 | # 从词法分析器的tokens获得token
31 | def FetchToken():
32 | global tokenNow
33 | try:
34 | tokenNow = next(tokenIter)
35 | return tokenNow
36 | except StopIteration:
37 | sys.exit()
38 |
39 |
40 | def MatchToken(tokenType, show=False):
41 | if show:
42 | tokenNow.show()
43 | if tokenNow.tokenType == tokenType:
44 | FetchToken()
45 | return True
46 | else:
47 | print("Excepted ", tokenType, "received ", tokenNow.tokenType)
48 | print("error!")
49 | return False
50 | exit(-1)
51 |
52 |
53 | # level 递归层次
54 | # op=0 进入
55 | # op=1 退出
56 | # showProcess Painter调用不显示信息
57 | def Msg(level, str, op=1):
58 | global showProcess
59 | if not showProcess:
60 | return
61 | if op == 0:
62 | print(" " * level + "Enter --> %s" % str)
63 | else:
64 | print(" " * level + "Exit <-- %s" % str)
65 |
66 |
67 | ##########################################
68 | # 表达式
69 | # ########################################
70 |
71 | # 二叉树节点
72 | # + - * / ** T CONST_ID FUNC
73 | # '(' ')' 匹配过程中扔掉
74 | # 叶子节点: T CONST_ID
75 | # 非叶子节点: 非终结符
76 |
77 | # 加法运算
78 | # 左结合
79 | # 新的 + - 为根节点
80 | # Example: 1+2-3
81 | # -
82 | # / \
83 | # + 3
84 | # / \
85 | # 1 2
86 | #
87 |
88 | def Expression(level):
89 | Msg(level, "Expression", 0)
90 | left = Term(level + 1)
91 | root = None
92 | while tokenNow.tokenType == TokenType.PLUS or tokenNow.tokenType == TokenType.MINUS:
93 | root = ExpNode(tokenNow)
94 | MatchToken(tokenNow.tokenType)
95 | right = Term(level + 1)
96 | root.addson(left)
97 | root.addson(right)
98 | left = root
99 | # left.dfs()
100 | Msg(level, "Expression")
101 | return left
102 |
103 |
104 | # def Expression():
105 | # Msg(0, "Expression")
106 | # left = Term()
107 | # root = None
108 | # while tokenNow.tokenType==TokenType.PLUS or tokenNow.tokenType==TokenType.MINUS:
109 | # root = ExpNode(tokenNow)
110 | # MatchToken(tokenNow.tokenType)
111 | # right = Expression()
112 | # root.addson(left)
113 | # root.addson(right)
114 | # left = root
115 | # Msg(1, "Expression")
116 | # return left
117 |
118 | # 乘法运算
119 | # 左结合
120 | # 新的 * / 为根节点
121 | # Example: 1*2*3
122 | # *
123 | # / \
124 | # * 3
125 | # / \
126 | # 1 2
127 | def Term(level):
128 | Msg(level, "Term", 0)
129 | left = Factor(level)
130 | root = None
131 | while tokenNow.tokenType == TokenType.MUL or tokenNow.tokenType == TokenType.DIV:
132 | root = ExpNode(tokenNow)
133 | MatchToken(tokenNow.tokenType)
134 | right = Factor(level + 1)
135 | root.addson(left)
136 | root.addson(right)
137 | left = root
138 |
139 | Msg(level, "Term")
140 | return left
141 |
142 |
143 | def Factor(level):
144 | Msg(level, "Factor", 0)
145 | if tokenNow.tokenType == TokenType.PLUS or tokenNow.tokenType == TokenType.MINUS:
146 | root = ExpNode(tokenNow)
147 | MatchToken(tokenNow.tokenType);
148 | son = Factor(level + 1)
149 | root.addson(son)
150 | Msg(level, "Factor")
151 | return root
152 | else:
153 | Msg(level, "Factor")
154 | return Component(level + 1)
155 |
156 |
157 | # 乘方运算
158 | # 右结合
159 | # 不支持 CONST_ID ** MINUS CONST_ID, 需要添括号
160 | def Component(level):
161 | Msg(level, "Component", 0)
162 | left = Atom(level)
163 | if tokenNow.tokenType == TokenType.POWER:
164 | root = ExpNode(tokenNow)
165 | MatchToken(tokenNow.tokenType)
166 | right = Component(level + 1)
167 |
168 | root.addson(left)
169 | root.addson(right)
170 | Msg(level, "Component")
171 | return root
172 | else:
173 | Msg(level, "Component")
174 | return left
175 |
176 |
177 | # 函数节点 FUNC <- CONST_ID | T
178 | # 叶子节点 CONST_ID | T
179 | def Atom(level):
180 | Msg(level, "Atom", 0)
181 | if tokenNow.tokenType == TokenType.CONST_ID or tokenNow.tokenType == TokenType.T:
182 | root = ExpNode(tokenNow)
183 | MatchToken(tokenNow.tokenType)
184 | Msg(level, "Atom")
185 | return root
186 |
187 | elif tokenNow.tokenType == TokenType.FUNC:
188 | root = ExpNode(tokenNow)
189 | MatchToken(tokenNow.tokenType)
190 | MatchToken(TokenType.L_BRACKET)
191 | son = Expression(level + 1)
192 | MatchToken(TokenType.R_BRACKET)
193 | root.addson(son)
194 | Msg(level, "Atom")
195 | return root
196 |
197 | elif tokenNow.tokenType == TokenType.L_BRACKET:
198 | MatchToken(TokenType.L_BRACKET)
199 | root = Expression(level + 1)
200 | MatchToken(TokenType.R_BRACKET)
201 | Msg(level, "Atom")
202 | return root
203 | else:
204 | print("Atom Error!")
205 |
206 |
207 | def OriginStatement(level):
208 | Msg(level, "OriginStatement", 0)
209 | MatchToken(TokenType.ORIGIN)
210 | MatchToken(TokenType.IS)
211 | MatchToken(TokenType.L_BRACKET)
212 | Origin_x = Expression(level + 1)
213 | MatchToken(TokenType.COMMA)
214 | Origin_y = Expression(level + 1)
215 | MatchToken(TokenType.R_BRACKET)
216 |
217 | Msg(level, "OriginStatement")
218 | return ["OriginStatement", Origin_x, Origin_y]
219 |
220 |
221 | def ScaleStatement(level):
222 | Msg(level, "ScaleStatement", 0)
223 | MatchToken(TokenType.SCALE)
224 | MatchToken(TokenType.IS)
225 | MatchToken(TokenType.L_BRACKET)
226 | Scale_x = Expression(level + 1)
227 | MatchToken(TokenType.COMMA)
228 | Scale_y = Expression(level + 1)
229 | # print(Scale_x)
230 | # print(Scale_y)
231 | MatchToken(TokenType.R_BRACKET)
232 |
233 | Msg(level, "ScaleStatement")
234 | return ["ScaleStatement", Scale_x, Scale_y]
235 |
236 |
237 | def RotStatement(level):
238 | Msg(level, "RotStatement", 0)
239 | MatchToken(TokenType.ROT)
240 | MatchToken(TokenType.IS)
241 | Rot_angle = Expression(level + 1)
242 |
243 | Msg(level, "RotStatement")
244 | return ["RotStatement", Rot_angle]
245 |
246 |
247 | def getColor():
248 | if tokenNow.tokenType == TokenType.COLOR:
249 | if tokenNow.lexeme == 'RED':
250 | color = 'r'
251 | elif tokenNow.lexeme == 'GREEN':
252 | color = 'g'
253 | elif tokenNow.lexeme == 'BLUE':
254 | color = 'b'
255 | elif tokenNow.lexeme == 'YELLOW':
256 | color = 'y'
257 | elif tokenNow.lexeme == 'BLACK':
258 | color = 'k'
259 | MatchToken(TokenType.COLOR)
260 | return color
261 | # else:
262 | # print("GetColor Error")
263 | else:
264 | print("GetColor Error")
265 |
266 |
267 | def ForStatement(level):
268 | Msg(level, "ForStatement", 0)
269 | MatchToken(TokenType.FOR)
270 | MatchToken(TokenType.T)
271 | MatchToken(TokenType.FROM)
272 | T_start = Expression(level + 1)
273 | MatchToken(TokenType.TO)
274 | T_end = Expression(level + 1)
275 | MatchToken(TokenType.STEP)
276 | T_step = Expression(level + 1)
277 |
278 | MatchToken(TokenType.DRAW)
279 | MatchToken(TokenType.L_BRACKET)
280 | Point_x = Expression(level + 1)
281 | # print(Point_x.dfs())
282 | MatchToken(TokenType.COMMA)
283 | Point_y = Expression(level + 1)
284 | MatchToken(TokenType.R_BRACKET)
285 |
286 | # 自定义颜色
287 | Draw_color = None
288 | if tokenNow.tokenType == TokenType.OF:
289 | MatchToken(TokenType.OF)
290 | Draw_color = getColor()
291 | # global T_value
292 | # Painter.set(Origin_x, Origin_y, Scale_x, Scale_y, Rot_angle)
293 | # Painter.paint(T_start, T_end, T_step, Point_x, Point_y, Draw_color)
294 |
295 | Msg(level, "ForStatement")
296 | return ["ForStatement", T_start, T_end, T_step, Point_x, Point_y, Draw_color]
297 |
298 |
299 | # Statement -> OriginStatement | ScaleStatement | RotStatement | ForStatement
300 | def Statement(level):
301 | Msg(level, "Statement", 0)
302 | statement = None
303 | if tokenNow.tokenType == TokenType.ORIGIN:
304 | statement = OriginStatement(level + 1)
305 | elif tokenNow.tokenType == TokenType.SCALE:
306 | statement = ScaleStatement(level + 1)
307 | elif tokenNow.tokenType == TokenType.ROT:
308 | statement = RotStatement(level + 1)
309 | elif tokenNow.tokenType == TokenType.FOR:
310 | statement = ForStatement(level + 1)
311 | else:
312 | print("Statement Error!")
313 | exit(-1)
314 |
315 | Msg(level, "Statement")
316 | return statement
317 |
318 |
319 | def Program(level=0):
320 | Msg(level, "Program", 0)
321 | statements = []
322 | while tokenNow.tokenType != TokenType.NONTOKEN:
323 | tmpstatement = Statement(level + 1)
324 | matched = MatchToken(TokenType.SEMICO)
325 | if matched:
326 | statements.append(tmpstatement)
327 | else:
328 | print("Program Error")
329 | exit(-1)
330 | Msg(level, "Program")
331 | return statements
332 |
333 |
334 | def Parser(string, show=False):
335 | global tokenIter # 必须要 global
336 |
337 | # 调用词法分析器 得到记号表
338 | tokenList = Lexer(string)
339 | tokenIter = iter(tokenList)
340 |
341 | setDefaultValue(show)
342 | FetchToken()
343 | return Program()
344 |
345 |
346 | def test():
347 | # Parser("--hello fad\n //fadfjl\n ROT is pi/2 ; SCALE is ( 1, 2*2); \n ORIGIN is ((2), 242/4);")
348 | str = "ORigin is (-30, 0); SCALE is ( 20, 25); for t from 0 to 2*pi step 0.01 draw (sin(t), cos(t)); SCALE is ( 30, 20); for t from -1 to 1 step 0.01 draw (2, t); FOR t from 0 to 1 step 0.01 draw (2+t, t);for t from -1 to 1 step 0.01 draw (2, t); FOR t from 0 to 1 step 0.01 draw (2+t, -t);for t from 0 to 2*pi step 0.01 draw (1+3*sin(t), 3*cos(t)); "
349 |
350 | Parser(str);
351 | # print("(%f, %f)" % (Origin_x, Origin_y))
352 | # print("(%f, %f)" % (Scale_x, Scale_y))
353 | # print("%f" % Rot_angle)
354 |
355 |
356 | # test()
--------------------------------------------------------------------------------
/Interpreter4FPL/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | C:\Users\Zong\Desktop\Interpreter\PycharmTest
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 | 1575604286922
181 |
182 |
183 | 1575604286922
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
--------------------------------------------------------------------------------