【发布时间】:2019-09-25 13:08:53
【问题描述】:
我正在尝试创建将解析以下表达式的语法:
func()func(a)func(a) + func(b)func(func(a) + func()) + func(b)
我为 (1) 和 (2) 实现了它,但是一旦我将 rvalue << (identifier | function_call) 扩展为 operation,它就会停止工作,原因是:
Exception raised:Expected W:(ABCD...), found ')' (at char 5), (line:1, col:6)
Exception raised:maximum recursion depth exceeded
谁能解释一下为什么?据我了解,表达式rvalue << (identifier | function_call | operation) function_call 应该在operation 之前匹配,并且不应该发生递归。
代码:
from pyparsing import Forward, Optional, Word, Literal, alphanums, delimitedList
rvalue = Forward()
operation = rvalue + Literal('+') + rvalue
identifier = Word(alphanums + '_')('identifier')
function_args = delimitedList(rvalue)('function_args')
function_name = identifier('function_name')
function_call = (
(function_name + Literal("(") + Optional(function_args) + Literal(")"))
)('function_call')
rvalue << (identifier | function_call | operation)
function_call.setDebug()
def test_function_call_no_args():
bdict = function_call.parseString("func()", parseAll=True).asDict()
assert bdict['function_name'] == 'func'
assert 'function_args' not in bdict
def test_function_call_one_arg():
bdict = function_call.parseString("func(arg)", parseAll=True).asDict()
assert bdict['function_name'] == 'func'
assert 'function_args' in bdict
def test_function_call_many_args():
bdict = function_call.parseString("func(arg1, arg2)", parseAll=True).asDict()
assert bdict['function_name'] == 'func'
assert 'function_args' in bdict
【问题讨论】:
-
像
func(a + b)这样的东西也有效吗? -
为你的小解析器写一个 BNF 并寻找左递归。请注意,“|”表示“MatchFirst”,而不是“MatchLongest”,因此在函数之前解析标识符通常是一个问题(您将匹配标识符,然后您将处于“(”并且解析器将“嗯?”)。提示:这是左递归的:
rvalue ::= rvalue '+' rvalue. -
这很困难,因为
function_call以identifier开头,而 pyparsing 不做回溯,所以 pyparsing 无法区分identifier和function_call- 我们永远无法使用identifier | function_call或function_call | identifier之类的替代,因为 pyparsing 甚至永远不会尝试解析右侧。 -
@Aran-Fey 是的,好地方,
func(a + b)也是有效的。