当前位置:首页 » 编程语言 » python语法树

python语法树

发布时间: 2023-06-04 04:47:54

A. 如何用python写一个解释器

大学里计算机科学最吸引我的地方就是编译器。最神奇的是,编译器是如何读出我写的那些烂代码,并且还能生成那么复杂的程序。当我终于选了一门编译方面的课程时,我发现这个过程比我想的要简单得多。
在本系列的文章中,我会试着通过为一种基本命令语言IMP写一个解释器,来展示这种简易性。因为IMP是一个简单广为人知的语言,所以打算用 Python写这个解释器。Python代码看起来很像伪代码,所以即使你不认识 Python,你也能理解它。解析可以通过一套从头开始实现的解析器组合完成(在本系列的下一篇文章中会有解释)。除了sys(用于I/O)、re(用于解析正则表达式)以及unittest(用于确保一切工作正常)库,没有使用其他额外的库。
IMP 语言
在开始写之前,我们先来讨论一下将要解释的语言。IMP是拥有下面结构的最小命令语言:
赋值语句(所有变量都是全局的,而且只能存储整数):

Python

1

x := 1

条件语句:

Python

1
2
3
4
5

if x = 1 then
y := 2
else
y := 3
end

while循环:

Python

1
2
3

while x < 10 do
x := x + 1
end

复合语句(分号分隔):

Python

1
2

x := 1;
y := 2

OK,所以它只是一门工具语言,但你可以很容易就把它扩展成比Lua或python更有用的语言。我希望能把这份教程能保持尽量简单。
下面这个例子是计算阶乘的程序:

Python

1
2
3
4
5
6

n := 5;
p := 1;
while n > 0 do
p := p * n;
n := n - 1
end

IMP没有读取输入的方式,所以初始状态必须是在程序最开始写一系列的赋值语句。也没有打印结果的方式,所以解释器必须在程序的结尾打印所有变量的值。
解释器的结构
解释器的核心是“中间表示”(Intermediate representation,IR)。这就是如何在内存中表示IMP程序。因为IMP是一个很简单的语言,中间表示将直接对应于语言的语法;每一种表达和语句都有对应的类。在一种更复杂的语言中,你不仅需要一个“语法表示”,还需要一个更容易分析或运行的“语义表示”。
解释器将会执行三个阶段:
源码中的字符分割成标记符(token)
将标记符组织成一棵抽象语法树(AST)。抽象语法树就是中间表示。
评估这棵抽象语法树,并在最后打印这棵树的状态
将字符串分割成标记符的过程叫做“词法分析”,通过一个词法分析器完成。关键字是很短,易于理解的字符串,包含程序中最基本的部分,如数字、标识符、关键字和操作符。词法分析器会除去空格和注释,因为它们都会被解释器忽略。

将标记符组织成抽象语法树(AST)的过程称为“解析过程”。解析器将程序的结构提取成一张我们可以评估的表格。

实际执行这个解析过的抽象语法树的过程称为评估。这实际上是这个解析器中最简单的部分了。
本文会把重点放在词法分析器上。我们将编写一个通用的词汇库,然后用它来为IMP创建一个词法分析器。下一篇文章将会重点打造一个语法分析器和评估计算器。
词汇库
词法分析器的操作相当简单。它是基于正则表达式的,所以如果你不熟悉它们,你可能需要读一些资料。简单来说,正则表达式就是一种能描述其他字符串的特殊的格式化的字符串。你可以使用它们去匹配电话号码或是邮箱地址,或者是像我们遇到在这种情况,不同类型的标记符。
词法分析器的输入可能只是一个字符串。简单起见,我们将整个输入文件都读到内存中。输出是一个标记符列表。每个标记符包括一个值(它代表的字符串)和一个标记(表示它是一个什么类型的标记符)。语法分析器会使用这两个数据来决定如何构建一棵抽象语法树。
由于不论何种语言的词法分析器,其操作都大同小异,我们将创建一个通用的词法分析器,包括一个正则表达式列表和对应的标签(tag)。对每一个表达式,它都会检查是否和当前位置的输入文本匹配。如果匹配,匹配文本就会作为一个标记符被提取出来,并且被加上该正则表达式的标签。如果该正则表达式没有标签,那么这段文本将会被丢弃。这样免得我们被诸如注释和空格之类的垃圾字符干扰。如果没有匹配的正则表达式,程序就要报错并终止。这个过程会不断循环直到没有字符可匹配。
下面是一段来自词汇库的代码:

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

import sys
import re

def lex(characters, token_exprs):
pos = 0
tokens = []
while pos < len(characters):
match = None
for token_expr in token_exprs:
pattern, tag = token_expr
regex = re.compile(pattern)
match = regex.match(characters, pos)
if match:
text = match.group(0)
if tag:
token = (text, tag)
tokens.append(token)
break
if not match:
sys.stderr.write('Illegal character: %sn' % characters[pos])
sys.exit(1)
else:
pos = match.end(0)
return tokens

注意,我们遍历正则表达式的顺序很重要。lex会遍历所有的表达式,然后接受第一个匹配成功的表达式。这也就意味着,当使用词法分析器时,我们应当首先考虑最具体的表达式(像那些匹配算子(matching operator)和关键词),其次才是比较一般的表达式(像标识符和数字)。
词法分析器
给定上面的lex函数,为IMP定义一个词法分析器就非常简单了。首先我们要做的就是为标记符定义一系列的标签。IMP只需要三个标签。RESERVED表示一个保留字或操作符。INT表示一个文字整数。ID代表标识符。

Python

1
2
3
4
5

import lexer

RESERVED = 'RESERVED'
INT = 'INT'
ID = 'ID'

接下来定义词法分析器将会用到的标记符表达式。前两个表达式匹配空格和注释。它们没有标签,所以 lex 会丢弃它们匹配到的所有字符。

Python

1
2
3

token_exprs = [
(r'[ nt]+', None),
(r'#[^n]*', None),

然后,只剩下所有的操作符和保留字了。记住,每个正则表达式前面的“r”表示这个字符串是“raw”;Python不会处理任何转义字符。这使我们可以在字符串中包含进反斜线,正则表达式正是利用这一点来转义操作符比如“+”和“*”。

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

(r':=', RESERVED),
(r'(', RESERVED),
(r')', RESERVED),
(r';', RESERVED),
(r'+', RESERVED),
(r'-', RESERVED),
(r'*', RESERVED),
(r'/', RESERVED),
(r'<=', RESERVED),
(r'<', RESERVED),
(r'>=', RESERVED),
(r'>', RESERVED),
(r'=', RESERVED),
(r'!=', RESERVED),
(r'and', RESERVED),
(r'or', RESERVED),
(r'not', RESERVED),
(r'if', RESERVED),
(r'then', RESERVED),
(r'else', RESERVED),
(r'while', RESERVED),
(r'do', RESERVED),
(r'end', RESERVED),

最后,轮到整数和标识符的表达式。要注意的是,标识符的正则表达式会匹配上面的所有的保留字,所以它一定要留到最后。

Python

1
2
3

(r'[0-9]+', INT),
(r'[A-Za-z][A-Za-z0-9_]*', ID),
]

既然正则表达式已经定义好了,我们还需要创建一个实际的lexer函数。

Python

1
2

def imp_lex(characters):
return lexer.lex(characters, token_exprs)

如果你对这部分感兴趣,这里有一些驱动代码可以测试输出:

Python

1
2
3
4
5
6
7
8
9
10
11

import sys
from imp_lexer import *

if __name__ == '__main__':
filename = sys.argv[1]
file = open(filename)
characters = file.read()
file.close()
tokens = imp_lex(characters)
for token in tokens:
print token

继续……

B. Python主要内容学的是什么

第一步:Python开发基础

Python全栈开发与人工智能之Python开发基础知识学习内容包括:Python基础语法、数据类型、字符编码、文件操作、函数、装饰器、迭代器、内置方法、常用模块等。

第二步:Python高级编程数据库开发

Python全栈开发与人工智能之Python高级编程和数据库开发知识学习内容包括:面向对象开发、Socket网络编程、线程、进程、队列、IO多路模型、Mysql数据库开发等。

第三步:前端开发

Python全栈开发与人工智能之前端开发知识学习内容包括:Html、CSS、JavaScript开发、Jquery&bootstrap开发、前端框架VUE开发等。

第十步:高并发语言GO开发

Python全栈开发与人工智能之高并发语言GO开发学习内容包括:GO语言基础、数据类型与文件IO操作、函数和面向对象、并发编程等。

C. 新手如何学习编程

熟悉以下关键东西,可以边学边做,定期训练,经常思考,长期积累:

1、语法。

2、基础理论(数学、数据结构、算法等)。

3、设计方法(编程原则、设计模式、框架设计等)。

4、库(核心、基础、UI、扩展、游戏引擎等)。

5、计算机相关(操作系统、网络、图形学等)。

6、领域知识(游戏设计、网站设计等)。

7、开发工具(编辑器、IDE、自动部署等)。

8、项目管理(进度管理、分工协作、Bug管理、版本控制等)。

最普遍也是最重要的能力:创造力。努力分析并理解好做什么以及怎么做。要知道上面那些东西一开始都是不存在的。

具体方法包括:

1、快速阅读入门教程和书籍,适合学习语言和基础库。比如我学Java读的《Java编程思想》,练习题做过一点,然后学ActionScript就没读过书,只读过Adobe官方文档《ActionScript 3.0编程》。

2、阅读库的文档、实例、源码。比如Flash、Flex开发,熟悉官方API很重要,很多细节要具体使用时才注意到,这时候最好做个笔记,虽然我从没看过我的笔记。

3、做一个自己感兴趣或熟悉的小项目,比如我就以黑白棋游戏作为多个语言的试水项目,一样的逻辑,便于把关注点放在语言特点上。

4、自己动手丰衣足食。厨师有菜谱,程序员可没菜谱。比如我做游戏,最关键的游戏编程知识全部是动手学出来的,很少有专门针对某个业务领域(如游戏)的编程书籍,要么是入门书,要么是模式书(如算法)、理论书(图形学),很少有书籍教你如何开发一个45度角地图系统加编辑器的,全靠自己思考,以及看前人的代码,需要时找些网络资料。关键是,可以培养最重要的创造力。

对于算法和设计模式,可以研读下,但是关键还是靠平时如何使用了。新手勉强不来的。

项目管理方面的,就得靠工作经验了,多思考多提意见不要只走流程。

热点内容
电脑直播唱歌电脑需要什么配置 发布:2025-07-13 19:03:45 浏览:88
config连接数据库 发布:2025-07-13 19:02:24 浏览:953
bt文件解压 发布:2025-07-13 19:02:16 浏览:744
比较便宜的云服务器 发布:2025-07-13 18:29:59 浏览:406
切换ftp 发布:2025-07-13 18:29:07 浏览:738
锐龙哪个配置最高画质 发布:2025-07-13 18:22:34 浏览:196
压缩机工作原理图 发布:2025-07-13 18:10:15 浏览:39
黑暗追求者安卓怎么联机 发布:2025-07-13 18:10:07 浏览:617
北大保安自学编程 发布:2025-07-13 18:09:58 浏览:858
java递归排列 发布:2025-07-13 18:02:43 浏览:473