在Python3中,最常见的解析器生成器(如ANTLR或Lark)通过从字符串的终端派生非终结符来定义语法,并构造一个lexer和一个解析器来计算字符串
相反,我正在寻找一个解析器生成器,它只处理由非终结符和终结符组成的“中间输入”,这意味着我将事先进行词法分析和部分解析
例如,如果输入语法为
S -> AB
A -> a | aA
B -> b | aB
如果大写字母是非终结符,小写字母是终结符,则可能的输入可以是aaaB
,然后可以从中构造根为S
的解析树
实际上,输入不能仅仅是像aaaB
这样的ASCII字符字符串,因为非终端必须存储关于自己子树的信息。因此,至少这些必须是任意对象,并且输入更有可能是对象列表
是否有提供此功能的库或包
注意:这不是背书。可能还有许多其他Python解析包提供类似的功能。它只是作为实现(假定的)目标的一种可能机制
Ply解析包确实包含一个lexer生成器,但您没有义务使用它;你可以自由使用任何你喜欢的函数来提供词法标记。标记只是对象类型,其中包括
value
属性。但是,除了要求value
对象存在外,Ply不会对该对象进行任何假设引用here和also here手册:
token()
方法,返回下一个令牌,如果没有更多的令牌可用,则返回None
李>token()
方法必须返回具有type
和value
属性的对象tok
。如果正在使用行号跟踪,则令牌还应定义lineno
属性李>为了将非终端传递到解析器中,需要使它们看起来像终端。最简单的方法是为每个非终端制作一个伪终端,并用一个生产单元转换伪终端。例如,假设伪终端的名称以
_
结尾(这将使它们很容易以编程方式生成),您可以修改规则进入
如果我们假设您将正确的AST值注入到
B_
终端返回的令牌对象中,那么您只需要向语法中添加一个操作函数:下面是一个完整的可运行示例,使用问题中的语法:
文件:inject.py
和一个示例运行:
在真正的语法中,键入所有这些伪标记名和单元结果可能会很繁琐。您可以利用这样一个事实,即您可以自己生成docstring,只要它在您通过调用
yacc.yacc
构建解析器之前就已经存在。您还需要将伪令牌名称添加到令牌名称列表中,以便Ply知道B_
是一个令牌Lark支持使用“自定义lexer”,您可以使用它来提供您选择的任何终端流。源不必是字符串
您可以在这里找到此功能的一个简单示例:https://github.com/lark-parser/lark/blob/master/examples/custom_lexer.py
相关问题 更多 >
编程相关推荐