首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

parser

parser模块为Python的内部解析器和字节码编译器提供了一个接口。该接口的主要目的是允许Python代码编辑Python表达式的分析树并从中创建可执行代码。这比试图将任意Python代码片段解析并修改为字符串更好,因为解析是以与形成应用程序的代码相同的方式执行的。它也更快。

注意

从Python 2.5开始,使用ast模块在抽象语法树(AST)生成和编译阶段切入更为方便。

parser模块导出记录在这里也有“ST”的“AST”代替姓名; 这是从没有其他AST开始的遗留问题,与Python 2.5中的AST无关。这也是函数关键字参数被称为ast的原因,而不是st。Python 3中的“ast”函数已被删除。

关于这个模块有几点需要注意,这对使用创建的数据结构很重要。这不是编辑Python代码的分析树的教程,但提供了使用parser模块的一些示例。

最重要的是,需要理解内部解析器处理的Python语法。有关语言语法的完整信息,请参阅Python语言参考。解析器本身是Grammar/Grammar根据标准Python发行版中文件中定义的语法规范创建的。存储在由该模块创建的ST对象中的解析树是由expr()or suite()函数创建的内部解析器的实际输出,如下所述。ST创建的对象sequence2st()忠实地模拟这些结构。请注意,由于该语言的形式语法被修改,所以被认为“正确”的序列的值将因Python的不同版本而异。然而,作为源文本将代码从一个Python版本传输到另一个版本将始终允许在目标版本中创建正确的分析树,唯一的限制是迁移到较老版本的解释器将不支持更新的语言结构。解析树通常不是从一个版本到另一个版本兼容,而源代码始终是向前兼容的。

由st2list()或st2tuple()返回的序列的每个元素都有一个简单的形式。代表文法中非终端元素的序列总长度大于1。第一个元素是一个整数,用于标识语法中的产品。这些整数在C头文件Include / graminit.h和Python模块符号中给出了符号名称。序列中的每个附加元素都代表输入字符串中可识别的生产组件:它们总是与父代具有相同形式的序列。这个结构中应该注意的一个重要方面是,用于标识父节点类型的关键字(如if_stmt中的关键字)包含在节点树中,无需任何特殊处理。例如,if关键字由元组(1,'if')表示,其中1是与所有名称标记关联的数值,包括用户定义的变量和函数名称。在请求行号信息时返回的替代形式中,相同的标记可表示为(1,'if',12),其中12表示找到终端符号的行号。

终端元素的表示方式大致相同,但没有任何子元素,并添加了已识别的源文本。if以上关键字的例子是有代表性的。C头文件Include/token.h和Python模块中定义了各种类型的终端符号token

ST对象不需要支持这个模块的功能,但是有三个目的:允许应用程序分摊处理复杂分析树的代价,提供一个分析树表示,与Python相比,可以节省内存空间列表或元组表示,并且简化在C中创建附加模块来操纵分析树。一个简单的“包装”类可以在Python中创建,以隐藏ST对象的使用。

parser模块为几个不同的目的定义函数。最重要的目的是创建ST对象并将ST对象转换为其他表示形式,例如解析树和编译代码对象,但也有函数用于查询由ST对象表示的解析树的类型。

扩展内容

Module symbol 表示分析树内部节点的常用常量。 Module token 表示分析树的叶节点和用于测试节点值的函数的有用常量。

1.创建ST对象

ST对象可以从源代码或分析树中创建。从源创建ST对象时,将使用不同的函数来创建'eval''exec'表单。

parser.expr(source)

expr()函数将参数解析为它的输入compile(source, 'file.py', 'eval')。如果解析成功,则会创建ST对象来保存内部分析树表示形式,否则会引发适当的异常。

parser.suite(source)

suite()函数将参数解析为它的输入compile(source, 'file.py', 'exec')。如果解析成功,则会创建ST对象来保存内部分析树表示形式,否则会引发适当的异常。

parser.sequence2st(sequence)

该函数接受一个表示为序列的分析树,并尽可能构建内部表示。如果它可以验证该树符合Python语法,并且所有节点都是Python主机版本中的有效节点类型,则会从内部表示形式创建一个ST对象并将其返回给被调用的对象。如果在创建内部表示时出现问题,或者树无法验证,ParserError则会引发异常。不应该假定以这种方式创建的ST对象能够正确编译; 当ST对象被传递时,编译引发的正常异常仍可能启动compilest()。这可能表明问题与语法无关(例如MemoryError异常),但也可能由于解析结果等结构del f(0),它转义了Python解析器,但是由字节码编译器检查。

表示终端令牌的序列可以表示为表单的两元素列表(1, 'name')或者表单的三元素列表(1, 'name', 56)。如果第三个元素存在,则假定它是有效的行号。行号可以为输入树中的任何终端符号子集指定。

parser.tuple2st(sequence)

这与sequence2st()功能相同。此入口点保持向后兼容。

2.转换ST对象

无论用于创建它们的输入,ST对象都可以转换为表示为列表或元组树的解析树,也可以编译为可执行代码对象。可以使用或不使用行号信息来提取分析树。

parser.st2list(ast[, line_info])

该函数从ast 中的调用方接受ST对象,并返回表示等效分析树的Python列表。得到的列表表示可用于检查或以列表形式创建新的分析树。只要内存可用于构建列表表示,该函数就不会失败。如果分析树仅用于检查,则st2tuple()应该使用分析树来减少内存消耗和碎片。当需要列表表示时,此函数比检索元组表示并将其转换为嵌套列表快得多。

如果line_info为true,则所有终端令牌都将包含行号信息,作为表示令牌的列表的第三个元素。请注意,提供的行号指定了令牌结束的行。如果该标志为错误或省略,则该信息被省略。

parser.st2tuple(ast[, line_info])

该函数从ast中的调用方接受ST对象,并返回表示等效分析树的Python元组。除了返回一个元组而不是一个列表之外,这个函数与之相同st2list()

如果line_info为true,则所有终端令牌都将包含行号信息,作为表示令牌的列表的第三个元素。如果该标志为错误或省略,则该信息被省略。

parser.compilest(ast, filename='<syntax-tree>')

可以在ST对象上调用Python字节编译器来生成可用作exec语句或调用内置eval()函数的一部分的代码对象。该函数为编译器提供接口,使用由filename参数指定的源文件名将内部分析树从ast传递到解析器。为文件名提供的默认值指示源是ST对象。

编译ST对象可能会导致与编译相关的异常; 一个例子可能是SyntaxError由分析树引起的del f(0):这个语句在Python的形式语法中被认为是合法的,但不是一个合法的语言结构。所述SyntaxError凸起此条件实际上是由Python字节编译器通常,这就是为什么它可以在此时通过提高生成parser模块。编译失败的大多数原因可以通过检查分析树来以编程方式进行诊断。

3.对ST对象的查询

提供了两个函数,它们允许应用程序确定ST是作为表达式还是套件创建的。既不这些功能可以被用来确定是否有ST,从源代码经由创建expr()suite()或从经由解析树sequence2st()

parser.isexpr(ast)

ast 表示一个'eval'表单时,该函数返回true,否则返回false。这很有用,因为通常使用现有的内置函数不能查询代码对象的信息。请注意,由此创建的代码对象compilest()也不能像这样查询,并且与由内置compile()函数创建的代码对象相同。

parser.issuite(ast)

这个函数反映了isexpr(),它报告ST对象是否代表'exec'形式,通常称为“套件”。假设这个函数等同于isexpr(ast)并不安全,因为附加的语法 片段可能会在未来得到支持。

4.异常和错误处理

解析器模块定义了一个异常,但也可能会从Python运行时环境的其他部分传递其他内置异常。查看每个函数以获取有关它可能引发的异常的信息。

exception parser.ParserError

解析器模块内发生故障时引发异常。这通常是针对验证失败产生的,而不是SyntaxError在正常解析期间产生的内置。异常参数可以是描述失败原因的字符串,也可以是包含导致传递给解析树的故障的序列的元组sequence2st()以及解释性字符串。调用sequence2st()需要能够处理任何一种类型的异常,而对模块中其他功能的调用只需要知道简单的字符串值。

请注意,函数compilest()expr()suite()可能引发解析和编译过程通常引发的异常。这些措施包括内置的例外MemoryErrorOverflowErrorSyntaxError,和SystemError。在这些情况下,这些例外具有通常与其相关的所有含义。有关详细信息,请参阅每个功能的说明。

5. ST对象

ST对象之间支持有序和等式比较。酸洗ST对象(使用pickle模块)也被支持。

parser.STType

返回的对象的类型expr()suite()sequence2st()

ST对象具有以下方法:

ST.compile([filename])

Same as compilest(st, filename).

ST.isexpr()

isexpr(st)一样

ST.issuite()

issuite(st).一样

ST.tolist([line_info])

等同于 st2list(st, line_info).

ST.totuple([line_info])

等同于 st2tuple(st, line_info).

6.例子:compile()的模拟

虽然许多有用的操作可能发生在解析和字节码生成之间,但最简单的操作是什么都不做。为此,使用parser模块产生中间数据结构就相当于代码

代码语言:javascript
复制
>>> code = compile('a + 5', 'file.py', 'eval')
>>> a = 5
>>> eval(code)
10

使用该parser模块的等效操作稍长一些,并允许将中间内部分析树保留为ST对象:

代码语言:javascript
复制
>>> import parser
>>> st = parser.expr('a + 5')
>>> code = st.compile('file.py')
>>> a = 5
>>> eval(code)
10

一个需要ST和代码对象的应用程序可以将这些代码打包成一些可用的函数:

代码语言:javascript
复制
import parser

def load_suite(source_string):
    st = parser.suite(source_string)
    return st, st.compile()

def load_expression(source_string):
    st = parser.expr(source_string)
    return st, st.compile()

扫码关注腾讯云开发者

领取腾讯云代金券