2014-01-26 6 views
8

Pyparsing отлично работал для очень маленькой грамматики, но по мере роста грамматики производительность снижалась и использование памяти через крышу.Эффективность пирапов и использование памяти

Мой текущий gramar является:

newline = LineEnd() 
minus = Literal ('-') 
plus = Literal ('+') 
star = Literal ('*') 
dash = Literal ('/') 
dashdash = Literal ('//') 
percent = Literal ('%') 
starstar = Literal ('**') 
lparen = Literal ('(') 
rparen = Literal (')') 
dot = Literal ('.') 
comma = Literal (',') 
eq = Literal ('=') 
eqeq = Literal ('==') 
lt = Literal ('<') 
gt = Literal ('>') 
le = Literal ('<=') 
ge = Literal ('>=') 
not_ = Keyword ('not') 
and_ = Keyword ('and') 
or_ = Keyword ('or') 
ident = Word (alphas) 
integer = Word (nums) 

expr = Forward() 
parenthized = Group (lparen + expr + rparen) 
trailer = (dot + ident) 
atom = ident | integer | parenthized 
factor = Forward() 
power = atom + ZeroOrMore (trailer) + Optional (starstar + factor) 
factor << (ZeroOrMore (minus | plus) + power) 
term = ZeroOrMore (factor + (star | dashdash | dash | percent)) + factor 
arith = ZeroOrMore (term + (minus | plus)) + term 
comp = ZeroOrMore (arith + (eqeq | le | ge | lt | gt)) + arith 
boolNot = ZeroOrMore (not_) + comp 
boolAnd = ZeroOrMore (boolNot + and_) + boolNot 
boolOr = ZeroOrMore (boolAnd + or_) + boolAnd 
match = ZeroOrMore (ident + eq) + boolOr 
expr << match 
statement = expr + newline 
program = OneOrMore (statement) 

Когда я анализирую следующее

print (program.parseString ('3*(1+2*3*(4+5))\n')) 

Это занимает довольно много времени:

~/Desktop/m2/pyp$ time python3 slow.py 
['3', '*', ['(', '1', '+', '2', '*', '3', '*', ['(', '4', '+', '5', ')'], ')']] 

real 0m27.280s 
user 0m25.844s 
sys 0m1.364s 

И использование памяти доходит до 1.7 GiB (sic!).

Я допустил какую-то серьезную ошибку в реализации этой грамматики или как еще можно сохранить память в допустимых границах?

+0

То же самое с lex и yacc в течение нескольких секунд. – Hyperboreus

ответ

11

После импорта Pyparsing включить Packrat разбора memoize синтаксического анализа поведения:

ParserElement.enablePackrat() 

Это должно сделать большое улучшение производительности.

+0

Спасибо, я попробую. – Hyperboreus

+1

Для записи это составляет от 3,5 секунд до 0,036 секунды на моем компьютере, что почти в 100 раз улучшается. Есть ли причина, по которой memoization не включается автоматически - не удается ли в некоторых случаях? – Hooked

+1

@Hooked: подробности о разборке пакетов с помощью pyparsing см. В [этом элементе в FAQ по pyparsing] (http://pyparsing-public.wikispaces.com/FAQs#toc3). См. Также [этот поток SO] (https://stackoverflow.com/q/1410477/857390) для анализа парсера в целом. –

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