需要使用 pyparsing 制作递归解析器的帮助

发布于 2024-07-14 19:37:11 字数 757 浏览 5 评论 0原文

我正在尝试使用 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 初始化对象

所以我将有 2 个类

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

class object2(object):
       This will hold cross elements

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

I am trying the python pyparsing for parsing. I got stuck up while making the recursive parser.

Let me explain the problem

I want to make the Cartesian product of the elements. The syntax is

cross({elements },{element})

I put in more specific way

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

So the general form is first group will have n elements (a,b,c,d). The second group will have one element that so the final output will be Cartesian Product.

The syntax is to be made recursive because it can go to n level like

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

This means cross a,b with c1. Lets say outcome us y. We again cross y it with c2

This can be till n level cross(cross(cross(cross......

What i want is to have object to be initialized using setparseAction

So i will have 2 class

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

class object2(object):
       This will hold cross elements

I need help on this i am not able to make the recursive parser.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

杀お生予夺 2024-07-21 19:37:11

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

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

不是

{expression} * {expression}

因为递归很难处理,并且没有隐含的从左到右的排序。 您更经常看到的是诸如

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

“Which 放置优先级”以及围绕运算符从左到右排序的内容。

看看类似 http://www.cs.man.ac .uk/~pjj/bnf/c_syntax.bnf 有关此类内容通常如何构造的示例。

You should look at definitions of other languages to see how this is usually handled.

For example, look at how multiplication is defined.

It isn't

{expression} * {expression}

Because the recursion is hard to deal with, and there's no implied left-to-right ordering. What you see more often are things like

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

Which puts priorities and a left-to-right ordering around the operators.

Look at something like http://www.cs.man.ac.uk/~pjj/bnf/c_syntax.bnf for examples of how things like this are commonly structured.

南薇 2024-07-21 19:37:11

我同意@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']

I agree with @S.Lott you should reconsider your grammar.

Recursive definitions can be introduced using 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})")

Output:

['cross', 'cross', 'a', 'b', 'c1', 'c2']
噩梦成真你也成魔 2024-07-21 19:37:11

我不知道这是否有任何帮助,但这就是你如何在 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']

I don't know if this is any help, but here is how you would do what you want in lepl. Since the grammar appears to be correct I assume that it would be easy to translate to 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})')

The output is:

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']
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文