为了娱乐,我想为未类型化的Lambda演算编写一个解析器。的 最简单的方法可能是编写手写解析器,但是我想知道 如果还有更Python化的方式?具体来说,我想使用 转换语言语法描述的Python库 解析器。这是该语言的BNF定义:
<term> ::= <var>
| <term> <term>
| λ <var> <term>
为简单起见,我省略了括号规则。应用助理
到左侧,这样x y z
是(x y) z
。
哪个Python库可以采用上述语法描述,或某些 从中衍生出的文法(如我所写,文法是 模棱两可且左递归,因此实现起来并非易事),并且 产生解析器?我想看看它是如何使用代码完成的,所以请 不要仅仅回答“小偷就能做到”。请沿着 以下行:
>>> G = """syntax description here..."""
>>> parser = build.the_parser(G)
>>> parser.parse("λ x. (y z)")
Abs('x', App(Id('x', Id('y'))))
最后一行是所产生的抽象语法树的内容。腹肌 代表抽象(lambda),代表应用程序,代表ID 标识符。我认为PEG packrat解析器生成器在这里可以很好地工作。
答案 0 :(得分:1)
这个ANTLR4语法可以达到目的:
grammar T;
program
: term EOF
;
term
: Lambda Id '.' term
| '(' term ')'
| term term
| Id
;
Lambda
: '\u03BB'
;
Id
: [a-z] [a-zA-Z0-9]*
;
Spaces
: [ \t\r\n] -> skip
;
将以上内容放置在名为T.g4
的文件中。将ANTLR4 jar下载到同一文件夹中并执行以下操作:
java -cp antlr-4.7.2-complete.jar org.antlr.v4.Tool -Dlanguage=Python3 T.g4
这将创建词法分析器和解析器文件。
现在运行:
from antlr4 import *
from playground.TLexer import TLexer
from playground.TParser import TParser
tests = [
'λ x. (y z)',
'x y z w'
]
for test in tests:
lexer = TLexer(InputStream(test))
parser = TParser(CommonTokenStream(lexer))
tree = parser.program()
print("{}".format(tree.toStringTree(recog=parser)))
将打印:
(program (term λ x . (term ( (term (term y) (term z)) ))) <EOF>)
(program (term (term (term (term x) (term y)) (term z)) (term w)) <EOF>)
答案 1 :(得分:0)
这里是删除左递归的替代方法。尽管访问语法树是OP的一种练习。
.2.
.3.
.4.