如何在 Pyparsing 中进行正确的递归?
How to do proper recursion in Pyparsing?
我目前正在解析一种自定义编程语言,并且在创建用于解析的 "expression" 规则时,我正在努力寻找一种不会因递归而非常缓慢的方法。
我的问题是函数调用可以在表达式中,表达式可以在函数调用(参数)中。所以我最终得到的是一个基于 Forward()
的糟糕系统,在 func1(var1+1) + 1
上需要几秒钟,在 func1(func1(var1+1)+1) + 1
上需要几分钟,这肯定是不可接受的。
这是我目前的错误做法:
expression = Forward()
functionCall = Forward()
value = literal ^ identifier ^ Group(functionCall)
expression << Group(infixNotation(value, [
(memberOP, 2, opAssoc.LEFT),
...
]))
arguments = ZeroOrMore(delimitedList(expression))
...
functionCall << identifier + Literal("(").suppress() + Group(arguments) + Literal(")").suppress()
PyParsing 可以记住以前的解析结果并使用 Packrat 优化重新使用它们。这为递归语法或通常在元素可能适用于不同上下文的情况下提供了性能优势。
Packrat 必须手动启用,因为它可能与具有副作用的解析器冲突(例如,修改全局状态的解析操作)。
import pyparsing
pyparsing.ParserElement.enablePackrat()
我目前正在解析一种自定义编程语言,并且在创建用于解析的 "expression" 规则时,我正在努力寻找一种不会因递归而非常缓慢的方法。
我的问题是函数调用可以在表达式中,表达式可以在函数调用(参数)中。所以我最终得到的是一个基于 Forward()
的糟糕系统,在 func1(var1+1) + 1
上需要几秒钟,在 func1(func1(var1+1)+1) + 1
上需要几分钟,这肯定是不可接受的。
这是我目前的错误做法:
expression = Forward()
functionCall = Forward()
value = literal ^ identifier ^ Group(functionCall)
expression << Group(infixNotation(value, [
(memberOP, 2, opAssoc.LEFT),
...
]))
arguments = ZeroOrMore(delimitedList(expression))
...
functionCall << identifier + Literal("(").suppress() + Group(arguments) + Literal(")").suppress()
PyParsing 可以记住以前的解析结果并使用 Packrat 优化重新使用它们。这为递归语法或通常在元素可能适用于不同上下文的情况下提供了性能优势。
Packrat 必须手动启用,因为它可能与具有副作用的解析器冲突(例如,修改全局状态的解析操作)。
import pyparsing
pyparsing.ParserElement.enablePackrat()