You are here:  Home » Python » parser- 访问Python解析树 – Python语言服务(Python教程)(参考资料)

parser– 访问Python解析


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

注意

从Python 2.5开始,使用astmodule.

关于这个模块,有一些注意事项对于使用所创建的数据结构很重要。这不是编辑Python代码的parsetrees的教程,而是一些使用parser模块出现了

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

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

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

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

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

另见

模块symbol
有用的常量表示解析树的内部节点.
模块token
有用的常量表示解析树的叶节点和函数强制节点值.

 

创建ST对象

可以从源代码或从解析树创建ST对象。从源创建ST对象时,使用不同的函数来创建"eval""exec"形式。

parser.exprsource
expr()函数解析参数source,好像它是compile(source, "file.py", "eval")。如果解析成功,则创建一个STR对象来保存内部解析树表示,否则会引发不适当的异常.
parser.suite (source
suite()函数解析参数source,好像它是compile(source, "file.py", "exec")。如果解析成功,则创建一个STR对象来保存内部解析树表示,否则会引发不适当的异常.
parser.sequence2st (sequence )
此函数接受表示为序列的解析树,并在可能的情况下构建内部表示。如果它可以验证树符合Python语法并且所有节点都是主机版本的Python中的有效节点类型,则从内部表示创建ST对象并返回到被调用者。如果创建内部表示时出现问题,或者无法验证树,则会引发ParserError异常。不应假设以这种方式创建的AnST对象正确编译;当ST对象被传递到compilest()时,仍可以启动编译引发的规范化。这可能表明与语法无关的问题(例如MemoryError异常),但也可能是由于构造的结果,例如解析del f(0)的结果,它逃脱了Python解析器但被字节码缺失了compiler.

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

parser.tuple2st (sequence)
这与sequence2st()。这个入口点是为了向后兼容而维护的.

 

转换ST对象

无论用于创建它们的输入如何,ST对象都可以被转换为表示为列表或元组树的粗糙树,或者可以被编译成可执行代码对象。可以在有或没有亚麻布信息的情况下提取解析树.

parser.st2listst, line_info=False, col_info=False
这个函数在st并返回表示等效分析树的aPython列表。生成的列表表示可用于检查或创建新的解析树inlist表单。只要内存可用于构建列表表示,此函数就不会失败。如果解析树只用于检查,st2tuple()应该使用它来减少内存消耗和碎片。当需要列表表示时,此函数明显快于检索元组表示并将其转换为嵌套列表.

如果line_info为真,则将包含所有终端令牌的行号信息作为第三个表示令牌的列表元素。请注意,提供的行号指定了令牌ends的行。如果标志为false或省略,则省略此信息.

parser.st2tuple (st, line_info=False, col_info=False )
此函数在st中接受来自调用者的ST对象,并返回表示等效分析树的aPython元组。除了返回atuple而不是列表之外,此函数与st2list().

相同如果line_info为真,则将包含所有终端令牌的行号信息,作为表示令牌的列表的第三个元素。如果标志为假或省略,则省略此信息.

parser.compilest (st, filename=”<syntax-tree>” )

可以在ST对象上调用Python字节编译器来生成代码对象,这些代码对象可以用作对内置exec()eval()功能。这个函数提供了编译器的接口,从st到解析器,使用filename参数。为filename提供的默认值表示源是ST对象.

编译ST对象可能导致与编译有关的异常;例如SyntaxErrordel f(0)的解析树引起的:这个语句在Python的形式语法中被认为是合法的,但不是法律语言结构。SyntaxError为此条件引发的实际上是由Python字节编译器正常生成的,这是为什么它可以在这时被parser模块。编辑失败的大多数原因可以通过检查parsetree来编程诊断.

 

ST对象的查询

提供了两个函数,允许应用程序确定ST是否被创建为表达式或套件。这些函数都不能用于确定ST是通过expr()suite()从源代码创建的,还是通过sequence2st().

parser.isexprst)从解析树创建的

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

parser.issuite//(st
这个函数镜像isexpr(),因为它报告一个ST对象是否表示"exec"表单,通常称为“套件”。这个函数是不安全的。相当于not isexpr(st),因为将来可能会支持extraalsyntactic片段.

 

例外和错误处理

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

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

注意函数compilest(), expr()suite()可以解析通常由解析和编译过程引发的异常。这些包括内置的例外MemoryError,OverflowError, SyntaxErrorSystemError。在这些例子中,这些例外具有通常与它们相关的所有含义。详细信息请参阅每个功能的描述.

 

ST对象

ST对象之间支持有序和相等比较。还支持酸洗ST对象(使用pickle模块).

parser.STType
expr(), suite()sequence2st().

ST对象有以下方法:

ST.compilefilename=”<syntax-tree>”
与…一样 compilest(st, filename).
ST.isexpr
与…一样 isexpr(st).
ST.issuite
与…一样 issuite(st).
ST.tolistline_info=False, col_info=False
与…一样 st2list(st, line_info, col_info).
ST.totupleline_info=False, col_info=False
与…一样 st2tuple(st, line_info, col_info).

示例:的仿真compile()

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

>>> code = compile("a + 5", "file.py", "eval")
>>> a = 5
>>> eval(code)10

使用parser模块稍长,并允许中间内部分析树保留为ST对象:

>>> import parser
>>> st = parser.expr("a + 5")
>>> code = st.compile("file.py")
>>> a = 5
>>> eval(code)10

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

import parserdef 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()

评论被关闭。