parsy解析器的参数

Parameters of parsy parser

考虑以下代码,它解析和评估 Python 中的 567 +223 之类的字符串。

import parsy as pr                                                                        
from parsy import generate                                                                
                                                                                          
def lex(p):                                                                               
    return p << pr.regex('\s*')                                                           
                                                                                          
numberP = lex(pr.regex('[0-9]+').map(int))                                                
                                                                                          
@generate                                                                                 
def sumP():                                                                               
    a = yield numberP                                                                     
    yield lex(pr.string('+'))                                                             
    b = yield numberP                                                                     
    return a+b                                                                            
                                                                                          
exp = sumP.parse('567 + 323')                                                             
print(exp)

@generate 对我来说完全是个谜。有没有人有更多关于这个技巧如何工作的信息?它确实允许我们以类似于 Haskell 的 monadic do 表示法的风格来编写。是否需要代码反射来制作您自己的@generate,或者是否有一种聪明的方法来逐字解释该代码。

现在我的主要问题来了,我想将 sumP 概括为 opP,它还需要一个运算符和一个组合函数:

import parsy as pr                                                                        
from parsy import generate                                                                
                                                                                          
def lex(p):                                                                               
    return p << pr.regex('\s*')                                                           
                                                                                          
numberP = lex(pr.regex('[0-9]+').map(int))                                                
                                                                                          
@generate                                                                                 
def opP(symbol, f):                                                                       
    a = yield numberP                                                                     
    yield lex(pr.string(symbol))                                                          
    b = yield numberP                                                                     
    return f(a,b)                                                                            
                                                                                          
exp = opP('+', lambda x,y:x+y).parse('567 + 323')                                         
print(exp)

这给出了一个错误。生成的opP好像已经有两个参数了,不知道怎么处理

装饰器在 Python 中的工作方式是,它们是使用装饰方法作为参数调用的函数,然后将它们的 return 值分配给方法名称。换句话说:

@foo
def bar():
    bla

相当于:

def bar():
    bla
bar = foo(bar)

这里 foo 可以用 bar 做任何它想做的事。它可能会用某种东西包装它,它可能会反省它的代码,它可能会调用它。

@generate 所做的是将给定函数包装在解析器对象中。解析器对象在解析时将调用不带参数的函数,这就是为什么在将 @generate 应用于带参数的函数时会出现有关缺少参数的错误。

要创建参数化规则,您可以将 @generate 应用于内部 0 参数函数,并且 return 即:

def opP(symbol, f):
    @generate
    def op():
        a = yield numberP                                                                  
        yield lex(pr.string(symbol))
        b = yield numberP
        return f(a,b)

    return op