2024-05-15 22:12:29 发布
网友
我无法将这个EBNF表达式转换成Pyparsing,知道吗?在
token:: [A-Z] P:: !|token;P|(P^P)|(P*P)
问题是当使用递归时,解释器失败。 这样的表达式应该是有效的:
这使得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构建递归语法,您必须使用Pyparsing的Forward类从内到外进行思考。使用Forward,可以为稍后定义的表达式定义一个空占位符。以下是针对这个BNF的pyparsing的一个开始:
EXCLAM,SEMI,HAT,STAR = map(Literal,"!;^*") LPAR,RPAR = map(Suppress,"()") token = oneOf(list(alphas.upper()))
我使用Literal来定义运算符,但是取消分组(),我们将使用pyparsing Group将结果物理地分组到子列表中。在
现在我们用Forward定义占位符表达式:
现在,我们可以使用这个占位符来构建表达式(我们必须使用'<;<;='作为赋值运算符,这样expr就可以作为转发而不是返回到表达式本身)。这是我的第一个通行证,按原样使用您的BNF:
expr <<= (EXCLAM | token + SEMI + expr | Group(LPAR + expr + HAT + expr + RPAR) | Group(LPAR + expr + STAR + expr + RPAR))
结果如下:
(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', ';', '!']]
在您的BNF中似乎有一个不成文的规则,一个或多个代币也可以同时存在,很容易确定为:
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
最后一点:我假设“AAA”是连续的3个“A”代币。如果你想让标记是1个或多个字母的单词分组,那么将表达式中的“OneOrMore(token)”更改为“word”(字母表上部())'-然后您将获得第一个测试用例的以下结果:
[[['ASD', ';', '!'], '^', ['FFF', ';', '!']]]
这使得Lisp符号可以工作xD!!在
要使用Pyparsing构建递归语法,您必须使用Pyparsing的Forward类从内到外进行思考。使用Forward,可以为稍后定义的表达式定义一个空占位符。以下是针对这个BNF的pyparsing的一个开始:
我使用Literal来定义运算符,但是取消分组(),我们将使用pyparsing Group将结果物理地分组到子列表中。在
现在我们用Forward定义占位符表达式:
^{pr2}$现在,我们可以使用这个占位符来构建表达式(我们必须使用'<;<;='作为赋值运算符,这样expr就可以作为转发而不是返回到表达式本身)。这是我的第一个通行证,按原样使用您的BNF:
结果如下:
在您的BNF中似乎有一个不成文的规则,一个或多个代币也可以同时存在,很容易确定为:
现在给出:
但看起来我们可以从额外的分组中获益,这样二进制“^”和“*”运算符的操作数分组得更清楚。所以我决定:
我认为这个版本的输出现在会更容易处理:
以下是完整的脚本:
最后一点:我假设“AAA”是连续的3个“A”代币。如果你想让标记是1个或多个字母的单词分组,那么将表达式中的“OneOrMore(token)”更改为“word”(字母表上部())'-然后您将获得第一个测试用例的以下结果:
相关问题 更多 >
编程相关推荐