2

我正在尝试编写一些可以解析一些代码的东西。我能够成功解析foo(spam)and spam+eggs,但是foo(spam+eggs)(递归下降?我的编译器术语有点生疏)失败了。

我有以下代码:

from pyparsing_py3 import *

myVal = Word(alphas+nums+'_')    
myFunction = myVal + '(' + delimitedList( myVal ) + ')'

myExpr = Forward()
mySubExpr = ( \
    myVal \
    | (Suppress('(') + Group(myExpr) + Suppress(')')) \
    | myFunction \
    )
myExpr << Group( mySubExpr + ZeroOrMore( oneOf('+ - / * =') + mySubExpr ) )


# SHOULD return: [blah, [foo, +, bar]]
# but actually returns: [blah]
print(myExpr.parseString('blah(foo+bar)'))
4

2 回答 2

4

几个问题:delimitedList 正在寻找一个逗号分隔的 myVal 列表,即标识符,作为唯一可接受的参数列表形式,所以它当然不能匹配 'foo+bar'(不是逗号分隔的 myVal 列表! ); 修复揭示了另一个问题—— myVal 和 myFunction 以相同的方式启动,因此它们在 mySubExpr 中的顺序很重要;修复它揭示了另一个——两层嵌套而不是一层。这个版本似乎还可以......:

myVal = Word(alphas+nums+'_')    

myExpr = Forward()
mySubExpr = (
    (Suppress('(') + Group(myExpr) + Suppress(')'))
    | myVal + Suppress('(') + Group(delimitedList(myExpr)) + Suppress(')')
    | myVal
    )
myExpr << mySubExpr + ZeroOrMore( oneOf('+ - / * =') + mySubExpr ) 

print(myExpr.parseString('blah(foo+bar)'))

根据需要发出['blah', ['foo', '+', 'bar']]。我还删除了多余的反斜杠,因为括号内无论如何都会出现逻辑行继续;它们是无害的,但确实妨碍了可读性。

于 2009-09-04T01:47:33.427 回答
4

我发现在使用带有 Forwards 的 '<<' 运算符时要养成的一个好习惯是始终将 RHS 括在括号中。那是:

myExpr << mySubExpr + ZeroOrMore( oneOf('+ - / * =') + mySubExpr )

更好的是:

myExpr << ( mySubExpr + ZeroOrMore( oneOf('+ - / * =') + mySubExpr ) )

这是因为我不幸选择了“<<”作为“插入”运算符,用于将表达式插入到 Forward 中。在这种特殊情况下,括号是不必要的,但在这种情况下:

integer = Word(nums)
myExpr << mySubExpr + ZeroOrMore( oneOf('+ - / * =') + mySubExpr ) | integer

我们明白我为什么说“不幸”。如果我将其简化为“A << B | C”,我们很容易看到操作的优先级导致评估被执行为“(A << B)| C”,因为'<<'的优先级高于'| '。结果是 Forward A 只获得了插入其中的表达式 B。"| C" 部分确实被执行了,但是你得到了 "A | C" ,它创建了一个 MatchFirst 对象,然后立即丢弃它,因为它没有分配给任何变量名。解决方案是将括号内的语句分组为“A << (B | C)”。在仅使用“+”操作组成的表达式中,实际上不需要括号,因为“+”的优先级高于“<<”。但这只是幸运的编码,当有人后来使用“|”添加替代表达式时会导致问题 并且没有意识到优先级含义。所以我建议只采用“A <<(表达式)”样式来帮助避免这种混淆。

(Someday I will write pyparsing 2.0 - which will allow me to break compatibilty with existing code - and change this to use the '<<=' operator, which fixes all of these precedence issues, since '<<=' has lower precedence than any of the other operators used by pyparsing.)

于 2009-09-04T07:29:36.617 回答