py解析简单语言表达式

2024-09-30 10:34:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图写一些东西来解析一些代码。我能够成功地解析foo(spam)和{},但是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)'))

Tags: 代码编译器foogroupbarspameggs术语
2条回答

几个问题: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']]。我还删除了多余的反斜杠,因为逻辑行接续无论如何都是在括号内出现的;它们是无害的,但确实妨碍了可读性。在

我发现,在Forwards中使用“<;<;”运算符时,一个好习惯是始终将RHS括在括号中。即:

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

最好是:

^{pr2}$

这是我不幸地选择了'<;<;'作为将表达式插入Forward的“insertion”运算符的结果。在这种特殊情况下,括号是不必要的,但在这种情况下:

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

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

(总有一天我会写pyparsing 2.0—它将允许我破坏与现有代码的兼容性—并将其更改为使用“<;<;=”运算符,它修复了所有这些优先级问题,因为“<;=”的优先级低于pyparsing使用的任何其他运算符。)

相关问题 更多 >

    热门问题