【问题标题】:Need help on making the recursive parser using pyparsing在使用 pyparsing 制作递归解析器时需要帮助
【发布时间】:2010-10-12 16:13:31
【问题描述】:

我正在尝试使用 python pyparsing 进行解析。我在制作递归解析器时遇到了困难。

让我解释一下问题

我想制作元素的笛卡尔积。语法是

cross({elements },{element})

我用更具体的方式表达

cross({a},{c1}) or cross({a,b},{c1}) or cross({a,b,c,d},{c1}) or 

所以一般形式是第一组将有n个元素(a,b,c,d)。第二组将有一个元素,因此最终输出将是笛卡尔积。

语法是递归的,因为它可以像n级一样

cross(cross({a,b},{c1}),{c2})

这意味着 a,b 与 c1 交叉。让我们说结果我们y。我们再次将它与 c2 交叉

这可以到n级 cross(cross(cross(cross...

我想要的是使用 setparseAction 初始化对象

所以我会有两节课

class object1(object):
     This will be used by a,b,c,d 

class object2(object):
       This will hold cross elements

我需要这方面的帮助,我无法制作递归解析器。

【问题讨论】:

    标签: python recursion parsing pyparsing


    【解决方案1】:

    您应该查看其他语言的定义以了解通常如何处理。

    例如,看看乘法是如何定义的。

    不是

    {expression} * {expression}
    

    因为递归很难处理,并且没有隐含的从左到右的顺序。你更经常看到的是类似的东西

    {term} + {factor}
    {factor} * {unary-expression}
    

    它将优先级和从左到右的顺序放在运算符周围。

    查看http://www.cs.man.ac.uk/~pjj/bnf/c_syntax.bnf 之类的内容,了解此类内容的常见结构示例。

    【讨论】:

    • 我不需要使用表达式。我只需要在 python 中使用 pyparsing 来做到这一点。语法是固定的,我认为可以使用递归解析器来完成。
    • @asb:由于其他人不使用递归解析器来处理这种事情,我建议您更改定义(不是语法,而是定义方式)可能会更成功) 以消除令人困惑的递归。
    【解决方案2】:

    我同意@S.Lott 你应该重新考虑你的语法。

    可以使用Forward()引入递归定义:

    from pyparsing import (Literal, Word, OneOrMore, Forward, nums, alphas)
    
    def BNF():
        """
        element      :: id
        elements     :: '{' element [ ',' element ]+ '}' 
                      | 'cross' '(' elements ',' '{' element '}' ')'
        """
        lcb, rcb, lb, rb, comma = [Literal(c).suppress() for c in '{}(),']
        element  = Word(alphas, alphas+nums+"_") # id
        elements = Forward()
        elements << ((lcb + element + OneOrMore(comma + element) + rcb) 
                     | (Literal('cross') + lb + elements + comma
                        + lcb + element + rcb + rb))
        return elements
    
    print BNF().parseString("cross(cross({a,b},{c1}),{c2})")
    

    输出:

    ['cross', 'cross', 'a', 'b', 'c1', 'c2']
    

    【讨论】:

      【解决方案3】:

      我不知道这是否有帮助,但这里是你在 lepl 中如何做你想做的事。由于语法似乎是正确的,我假设它很容易转换为 pyparsing。

      from lepl import *
      
      def compile_parser():
      
          class Cross(Node): pass
      
          word = Token('[a-z0-9]+')
          par, en, bra, ket = [~Token('\\'+c) for c in '(){}']
          comma = ~Token(',')
      
          cross  = Delayed()
          vector = bra & word[1:,comma] & ket                 > list
          arg    = vector | cross
          cross += ~word('cross') & par & arg[2,comma] & en   > Cross
      
          parser = cross.string_parser()
          return lambda expr: parser(expr)[0]
      
      
      if __name__ == '__main__':
      
          parser = compile_parser()
          print parser('cross({a},{c1})')
          print parser('cross({a,b},{c1})')
          print parser('cross({a,b,c,d},{c1})')
          print parser('cross(cross({a,b},{c1}),{c2})')
      

      输出是:

      Cross
       +- [u'a']
       `- [u'c1']
      
      Cross
       +- [u'a', u'b']
       `- [u'c1']
      
      Cross
       +- [u'a', u'b', u'c', u'd']
       `- [u'c1']
      
      Cross
       +- Cross
       |   +- [u'a', u'b']
       |   `- [u'c1']
       `- [u'c2']
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-11
        • 2020-07-04
        • 2016-11-15
        相关资源
        最近更新 更多