Python py解析中的递归
我无法将这个EBNF表达式翻译成Pyparsing,知道吗Python py解析中的递归,python,recursion,pyparsing,ebnf,Python,Recursion,Pyparsing,Ebnf,我无法将这个EBNF表达式翻译成Pyparsing,知道吗 token:: [A-Z] P:: !|token;P|(P^P)|(P*P) 问题是当使用递归时,解释器会失败。 这样的表达式应该是有效的: (ASD;!^FFF;!) A;B;C;! (((A;!^B;!)^C;D;!)*E;!) 要使用Pyparsing构建递归语法,您必须使用Pyparsing的Forward类从内到外进行一些思考。使用“前进”,可以为稍后定义的表达式定义空占位符。以下是此BNF的pyparsing的开始:
token:: [A-Z]
P:: !|token;P|(P^P)|(P*P)
问题是当使用递归时,解释器会失败。
这样的表达式应该是有效的:
(ASD;!^FFF;!)
A;B;C;!
(((A;!^B;!)^C;D;!)*E;!)
要使用Pyparsing构建递归语法,您必须使用Pyparsing的Forward类从内到外进行一些思考。使用“前进”,可以为稍后定义的表达式定义空占位符。以下是此BNF的pyparsing的开始:
EXCLAM,SEMI,HAT,STAR = map(Literal,"!;^*")
LPAR,RPAR = map(Suppress,"()")
token = oneOf(list(alphas.upper()))
我使用Literal来定义运算符,但不使用grouping(),我们将使用pyparsing Group将结果物理地分组到子列表中
现在我们用Forward定义占位符表达式:
expr = Forward()
现在我们可以使用这个占位符来构建表达式(我们必须使用“”,这使得Lisp符号工作xD
from pyparsing import *
def pushFirst( strg, loc, toks ):
toks[0][2], toks[0][1] = toks[0][1], toks[0][2]
def parseTerm(term):
"""
EBNF syntax elements
EXCLAM = !
HAT = ^
STAR = *
SEMI = ;
LPAR = (
RPAR = )
"""
EXCLAM,HAT,STAR = map(Literal,"!^*")
LPAR,RPAR = map(Suppress,"()")
SEMI = Suppress(";")
token = oneOf(list(alphas.upper()))
expr = Forward()
expr <<= (
EXCLAM |
Group(Word(alphas.upper()) + SEMI + ungroup(expr)) |
Group(LPAR + expr + HAT + expr + RPAR).setParseAction( pushFirst ) |
Group(LPAR + expr + STAR + expr + RPAR).setParseAction( pushFirst )
)
try:
result = expr.parseString(term)
except ParseException as pe:
print ' '*pe.loc + '^'
print pe
return result[0]
def computeTerm(term):
print term
term = (parseTerm("(((AXX;!^B;!)^C;D;!)*E;!)"))
computeTerm(term)
从pyparsing导入*
def推送优先(strg、loc、toks):
toks[0][2],toks[0][1]=toks[0][1],toks[0][2]
定义解析术语(术语):
"""
EBNF语法元素
感叹号=!
帽子=^
星=*
半=;
LPAR=(
RPAR=)
"""
感叹号、帽子、星星=地图(文字“!^*”)
LPAR,RPAR=map(抑制“()”)
半自动=抑制(“;”)
token=list(alphas.upper())中的一个
expr=Forward()
expr-Woow你做到了!还有一个问题……我想将二进制运算符,如*和^to-prefix-notation,如Lisp更新。在文档中有一个使用字符串的示例,但不确定如何将其转换为数组。类似于:`Group(LPAR+expr+HAT+expr+RPAR)到Group(LPAR+expr+expr+HAT+RPAR)`expr-expr-HAT
对我来说听起来像后缀符号。这不就是你的工作方式吗?如果你想让STAR和HAT具有同等的优先级,试试Group(LPAR+expr+expr+(STAR | HAT)+RPAR)
。好吧,这是蛮力,但看起来你已经超越了PyParsiness的第二个层次,使用解析操作。恭喜你,PyParsiness玩得很开心!
(ASD;!^FFF;!)
^
Expected ";" (at char 2), (line:1, col:3)
A;B;C;!
['A', ';', 'B', ';', 'C', ';', '!']
(((A;!^B;!)^C;D;!)*E;!)
[[[['A', ';', '!', '^', 'B', ';', '!'], '^', 'C', ';', 'D', ';', '!'], '*', 'E', ';', '!']]
expr <<= (EXCLAM |
OneOrMore(token) + SEMI + expr |
Group(LPAR + expr + HAT + expr + RPAR) |
Group(LPAR + expr + STAR + expr + RPAR))
(ASD;!^FFF;!)
[['A', 'S', 'D', ';', '!', '^', 'F', 'F', 'F', ';', '!']]
A;B;C;!
['A', ';', 'B', ';', 'C', ';', '!']
(((A;!^B;!)^C;D;!)*E;!)
[[[['A', ';', '!', '^', 'B', ';', '!'], '^', 'C', ';', 'D', ';', '!'], '*', 'E', ';', '!']]
expr <<= (EXCLAM |
Group(OneOrMore(token) + SEMI + ungroup(expr)) |
Group(LPAR + expr + HAT + expr + RPAR) |
Group(LPAR + expr + STAR + expr + RPAR) )
(ASD;!^FFF;!)
[[['A', 'S', 'D', ';', '!'], '^', ['F', 'F', 'F', ';', '!']]]
A;B;C;!
[['A', ';', 'B', ';', 'C', ';', '!']]
(((A;!^B;!)^C;D;!)*E;!)
[[[[['A', ';', '!'], '^', ['B', ';', '!']], '^', ['C', ';', 'D', ';', '!']], '*', ['E', ';', '!']]]
from pyparsing import *
EXCLAM,SEMI,HAT,STAR = map(Literal,"!;^*")
LPAR,RPAR = map(Suppress,"()")
token = oneOf(list(alphas.upper()))
expr = Forward()
expr <<= (EXCLAM |
Group(OneOrMore(token) + SEMI + ungroup(expr)) |
Group(LPAR + expr + HAT + expr + RPAR) |
Group(LPAR + expr + STAR + expr + RPAR) )
tests = """\
(ASD;!^FFF;!)
A;B;C;!
(((A;!^B;!)^C;D;!)*E;!)""".splitlines()
for t in tests:
print t
try:
print expr.parseString(t).dump()
except ParseException as pe:
print ' '*pe.loc + '^'
print pe
print
[[['ASD', ';', '!'], '^', ['FFF', ';', '!']]]
from pyparsing import *
def pushFirst( strg, loc, toks ):
toks[0][2], toks[0][1] = toks[0][1], toks[0][2]
def parseTerm(term):
"""
EBNF syntax elements
EXCLAM = !
HAT = ^
STAR = *
SEMI = ;
LPAR = (
RPAR = )
"""
EXCLAM,HAT,STAR = map(Literal,"!^*")
LPAR,RPAR = map(Suppress,"()")
SEMI = Suppress(";")
token = oneOf(list(alphas.upper()))
expr = Forward()
expr <<= (
EXCLAM |
Group(Word(alphas.upper()) + SEMI + ungroup(expr)) |
Group(LPAR + expr + HAT + expr + RPAR).setParseAction( pushFirst ) |
Group(LPAR + expr + STAR + expr + RPAR).setParseAction( pushFirst )
)
try:
result = expr.parseString(term)
except ParseException as pe:
print ' '*pe.loc + '^'
print pe
return result[0]
def computeTerm(term):
print term
term = (parseTerm("(((AXX;!^B;!)^C;D;!)*E;!)"))
computeTerm(term)