Pyparsing: грамматика не может анализировать пробелы при анализе арифметического выражения с экспоненциальными и логарифмическими функциями.

Намерение:

Для разбора арифметических выражений с поддержкой логарифмов и экспонент. Допустимо любое из следующих выражений;

x + y
exp(x) + y
exp(x+y)
exp(log(x)+exp(z))+exp(y)
x+log(exp(y))
x + 2

Исходный код:

import pyparsing as pp
arith_expr = pp.Forward()
op = pp.oneOf("^ / * % + -")
exp_funcs = pp.Regex(r"(log|exp)(2|10|e)?")
operand = pp.Word(pp.alphas, pp.alphanums + "_") | pp.Regex(r"[+-]?\d+(:?\.\d*)?(:?[eE][+-]?\d+)?")
func_atom = operand ^ (pp.Optional(exp_funcs) + "(" + arith_expr + ")")

comp_expr = pp.Combine(func_atom + pp.ZeroOrMore(op + func_atom))

arith_expr << comp_expr
print arith_expr.parseString("exp(datasize+ 2) +3")

Наблюдение

Грамматика способна анализировать все такие арифметические выражения, но, к сожалению, не может анализировать, когда вокруг операнда или оператора появляется пробел. Грамматика не может проанализировать следующие выражения;

exp(x+ 2)
exp( x + 2 )
x + 2

Я попытался отладить грамматику с помощью setDebug() и обнаружил следующую ошибку при каждом таком сбое;

Expected ")"

Я считаю, что Pyparsing нечувствителен к пробелам после изучения его документации и моего повседневного использования. Я пробовал отлаживать все возможные изменения, которые только мог. Ни один из них не решил проблему. Я ценю ваши ценные предложения. :)


person consumer    schedule 19.11.2012    source источник
comment
если "exp(datasize+ 2) +3".replace(" ", "") работает нормально, вам, вероятно, следует просто сообщить об ошибке и рассматривать функцию как чувствительную к пробелам.   -  person Aprillion    schedule 19.11.2012
comment
Объединив все операторы в одно выражение op, вы не получите правильной группировки операций по их стандартной иерархии. Прочтите operatorPrecedence, который позаботится об этом за вас.   -  person PaulMcG    schedule 20.11.2012


Ответы (1)


Проблема в том, что вы используете Combine, который объединяет все токены в один. Пробелы между токенами игнорируются при pyparsing, а пробелы внутри токена — нет.

Чтобы это исправить, избавьтесь от Combine, а затем передайте результат ''.join, чтобы вернуть его в одну строку.

person Taymon    schedule 19.11.2012
comment
Вы также можете передать аргумент adjacent=False в Combine, чтобы отключить требование, чтобы токены были смежными. - person BrenBarn; 19.11.2012
comment
Я подозреваю, что ОП хотел использовать Group, но по ошибке использовал Combine. - person PaulMcG; 20.11.2012