我正在尝试使用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})
这意味着用c1交叉a,b。让我们说结果我们。我们再次与c2交叉。
这可以直到n级交叉(交叉(交叉(交叉......)
我想要的是使用setparseAction初始化对象
所以我将有2个班级
class object1(object):
This will be used by a,b,c,d
class object2(object):
This will hold cross elements
我需要帮助,我无法制作递归解析器。
答案 0 :(得分:6)
您应该查看其他语言的定义,以了解通常如何处理。
例如,看看如何定义乘法。
不是
{expression} * {expression}
因为递归很难处理,并且没有隐含的从左到右的排序。你经常看到的是像
这样的东西{term} + {factor}
{factor} * {unary-expression}
这为操作员提供了优先顺序和从左到右的顺序。
查看http://www.cs.man.ac.uk/~pjj/bnf/c_syntax.bnf之类的内容,了解这类内容的常见结构。
答案 1 :(得分:3)
我同意@ 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']
答案 2 :(得分: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']