2015-11-11 3 views
2

Я хотел бы использовать Pyparsing модуль для разбора выражений, таких как:Pyparsing строку с оператором старшинства

карбо * или окси * или нитро *

После того, как синтаксический анализ, эти выражения должны быть преобразованы в:

carbo (вселенный) .select ([*]) | oxy (вселенная) .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 

у вас есть какие-либо идеи о том, что с ним не так?

благодаря

Eric

ответ

0

Проблема с грамматикой было использование ЛЕВЫХ ассоциаций вместо 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) 

Различие является тонким (и еще немного неясно, для меня), но это работает.

Eric

Смежные вопросы