我想编写 PyParsing 代码,能够解析任何 Python 代码(我知道 AST 模块存在,但那只是一个起点 - 我最终想解析的不仅仅是 Python 代码。)
无论如何,我想先从编写能够解析经典的开始。
当我这样做时,它只是输出:
现在我收到了一个"最大递归深度超过限制"的错误信息。这也很合理:
- 检查它是否为 "expr"。
- 检查它是否为 "string",它不是。 - 检查它是否为 "call"。
- 它必须以 "expr" 开头,返回到外部列表的起点。
那么我的问题是... 我该如何定义 "call" 和 "expr",以便不会出现无限递归,但同时也不会在检测到名称时停止并忽略参数?
Python 代码对 PyParsing 来说太复杂了吗?如果不是,那么 PyParsing 可以处理的内容是否有限制?
(注意 - 我包含了一般标签parsing, abstract-syntax-tree和bnf,因为我怀疑这是一个普遍的递归语法定义问题,不一定是特定于pyparsing的。)
无论如何,我想先从编写能够解析经典的开始。
print("Hello World!")
所以这就是我写的内容:
from pyparsing import (alphanums, alphas, delimitedList, Forward,
quotedString, removeQuotes, Suppress, Word)
expr = Forward()
string = quotedString.setParseAction(removeQuotes)
call = expr + Suppress('(') + Optional(delimitedList(expr)) + Suppress(')')
name = World(alphas + '_', alphanums + '_')
expr <<= string | name | call
test = 'print("Hello World!")'
print(expr.parseString(test))
当我这样做时,它只是输出:
['print']
这在技术上是一个有效的expr
- 你可以在REPL中输入它,而且没有问题解析它,即使它是无用的。
所以我想也许我想要的是在我的expr
定义中翻转name
和call
,这样它会更喜欢返回call
而不是name
,就像这样:
expr <<= string | call | name
现在我收到了一个"最大递归深度超过限制"的错误信息。这也很合理:
- 检查它是否为 "expr"。
- 检查它是否为 "string",它不是。 - 检查它是否为 "call"。
- 它必须以 "expr" 开头,返回到外部列表的起点。
那么我的问题是... 我该如何定义 "call" 和 "expr",以便不会出现无限递归,但同时也不会在检测到名称时停止并忽略参数?
Python 代码对 PyParsing 来说太复杂了吗?如果不是,那么 PyParsing 可以处理的内容是否有限制?
(注意 - 我包含了一般标签parsing, abstract-syntax-tree和bnf,因为我怀疑这是一个普遍的递归语法定义问题,不一定是特定于pyparsing的。)