使用运算符优先级对字符串进行pyparsing

时间:2015-11-11 10:58:20

标签: pyparsing

我想使用pyparsing模块来解析表达式,例如:

carbo *或oxy *或nitro *

解析后,这些表达式应转换为:

carbo(universe).select([*])|氧气(宇宙).select([*])|硝基(宇宙)。选择([*])

进一步评估。

我构建的语法仅适用于字符串中的第一个,但不适用于后续的。这是我的语法:

from pyparsing import *

def parse_keyword(token):

    return '"%s"(universe).select' % token[0]

def parse_arguments(token):

    return "(%s)" % str(token)

def operator_and(token):

    token[0][1] = "&"

    return " ".join(token[0])

def operator_or(token):

    token[0][1] = "|"

    return " ".join(token[0])

def parse_expression(self, token):

    return "".join([str(t) for t in token])

expression = 'carbo * or oxy * or nitro *'

linkers   = oneOf(["and","or",], caseless=True)
keyword   = oneOf(['carbo','oxy','nitro'], caseless=True).setParseAction(parse_keyword)
arguments = Optional(~linkers + delimitedList(Word(printables,excludeChars=","),combine=False)).setParseAction(parse_arguments)

selector = OneOrMore((keyword+arguments))

grammar = Forward()

grammar << selector.setParseAction(parse_expression)

grammar = operatorPrecedence(grammar, [(oneOf(["and"],caseless=True), 2, opAssoc.LEFT , operator_and),
                                       (oneOf(["or"] ,caseless=True), 2, opAssoc.LEFT , operator_or)],
                             lpar="(",
                             rpar=")")

parsedExpression = grammar.transformString(expression)

print parsedExpression
你会知道它有什么问题吗?

感谢

埃里克

1 个答案:

答案 0 :(得分:0)

语法的问题是在运算符优先级定义中使用LEFT关联而不是RIGHT。 这是完成工作的最终语法:

from pyparsing import *

def parse_keyword(token):

    return '"%s"(universe).select' % token[0]

def parse_arguments(token):

    return "(%s)" % str(token)

def operator_and(token):

    token[0][1] = "&"

    return " ".join(token[0])

def operator_or(token):

    token[0][1] = "|"

    return " ".join(token[0])

def parse_expression(self, token):

    return "".join([str(t) for t in token])

expression = 'carbo * or oxy * or nitro *'

linkers   = oneOf(["and","or",], caseless=True)
keyword   = oneOf(['carbo','oxy','nitro'], caseless=True).setParseAction(parse_keyword)
arguments = Optional(~linkers + delimitedList(Word(printables,excludeChars=","),combine=False)).setParseAction(parse_arguments)

selector = OneOrMore((keyword+arguments))

grammar = Forward()

grammar << selector.setParseAction(parse_expression)

grammar = operatorPrecedence(grammar, [(oneOf(["and"],caseless=True), 2, opAssoc.RIGHT , operator_and),
                                       (oneOf(["or"] ,caseless=True), 2, opAssoc.RIGHT , operator_or)],
                             lpar="(",
                             rpar=")")

parsedExpression = grammar.transformString(expression)

差异很微妙(对我来说仍然有点不清楚),但它确实有效。

埃里克