Diese Verwendung von infixNotation
hat nur 3 Ebenen der Betreiber, so packratting wird für Sie nicht viel tun. Die Verbesserungen sind normalerweise mit 5 oder mehr Ebenen von Operatoren, wie etwa mit arithmetischen Operationen.
Wenn Sie wirklich versuchen, die Leistung Kurbel aus infixNotation
, schreiben Sie Ihre eigene abgespeckte Version:
"""
BNF
operand = ~and ~or ~not (A-Za-z0-9)... | quoted_string
atom = 'not'? (operand | '(' expr ')')
and_term = atom 'and' atom
or_term = and_term 'or' and_term
"""
_and_ = CaselessKeyword('AND')
_or_ = CaselessKeyword('OR')
_not_ = CaselessKeyword('NOT')
keyword = (_and_ | _or_ | _not_)
search_term = ~keyword + Word(UNICODE_CHARS) | QuotedString('"', endQuoteChar='"', unquoteResults=False)
# use this instead of infixNotation - this is essentially what infixNotation will
# generate, but with fewer FollowedBy's (used to collapse degenerate levels)
LPAR,RPAR = map(Suppress, "()")
expr = Forward()
atom_ = search_term | Group(LPAR + expr + RPAR)
atom = Group(_not_ + atom_) | atom_
and_term = Group(atom + ZeroOrMore(_and_ + atom))
or_term = Group(and_term + ZeroOrMore(_or_ + and_term))
expr <<= or_term
# some simple test cases
tests = """
p and not q
p and not q or r
p and not (q or r)
"""
print("compare with using infixNotation")
expr.runTests(tests)
print("compare with using infixNotation")
search_expr = infixNotation(
search_term,
[
(_not_, 1, opAssoc.RIGHT),
(Optional(_and_), 2, opAssoc.LEFT),
(_or_, 2, opAssoc.LEFT),
]
)
search_expr.runTests(tests)
Die hartcodierte Version ausgegeben geben wie:
p and not q
[[['p', 'AND', ['NOT', 'q']]]]
[0]:
[['p', 'AND', ['NOT', 'q']]]
[0]:
['p', 'AND', ['NOT', 'q']]
[0]:
p
[1]:
AND
[2]:
['NOT', 'q']
p and not q or r
[[['p', 'AND', ['NOT', 'q']], 'OR', ['r']]]
[0]:
[['p', 'AND', ['NOT', 'q']], 'OR', ['r']]
[0]:
['p', 'AND', ['NOT', 'q']]
[0]:
p
[1]:
AND
[2]:
['NOT', 'q']
[1]:
OR
[2]:
['r']
p and not (q or r)
[[['p', 'AND', ['NOT', [[['q'], 'OR', ['r']]]]]]]
[0]:
[['p', 'AND', ['NOT', [[['q'], 'OR', ['r']]]]]]
[0]:
['p', 'AND', ['NOT', [[['q'], 'OR', ['r']]]]]
[0]:
p
[1]:
AND
[2]:
['NOT', [[['q'], 'OR', ['r']]]]
[0]:
NOT
[1]:
[[['q'], 'OR', ['r']]]
[0]:
[['q'], 'OR', ['r']]
[0]:
['q']
[1]:
OR
[2]:
['r']
Infixnotation Verwendung wird geben:
p and not q
[['p', 'AND', ['NOT', 'q']]]
[0]:
['p', 'AND', ['NOT', 'q']]
[0]:
p
[1]:
AND
[2]:
['NOT', 'q']
p and not q or r
[[['p', 'AND', ['NOT', 'q']], 'OR', 'r']]
[0]:
[['p', 'AND', ['NOT', 'q']], 'OR', 'r']
[0]:
['p', 'AND', ['NOT', 'q']]
[0]:
p
[1]:
AND
[2]:
['NOT', 'q']
[1]:
OR
[2]:
r
p and not (q or r)
[['p', 'AND', ['NOT', ['q', 'OR', 'r']]]]
[0]:
['p', 'AND', ['NOT', ['q', 'OR', 'r']]]
[0]:
p
[1]:
AND
[2]:
['NOT', ['q', 'OR', 'r']]
[0]:
NOT
[1]:
['q', 'OR', 'r']
Die FollowedBy Begriffe, die InfixNotation fügt degenerierte Ebenen für Kollaps hinzu, indem sichergestellt wird, dass zwei oder mehr Begriffe gruppiert sind, bevor sie tatsächlich gruppiert werden. Sie verhindern auch die aufrufenden Analyseaktionen für Atome auf jeder Ebene der Operationsprioritätsdefinition.
Wenn Ihnen das egal ist, versuchen Sie es mit der abgespeckten Version.
(Bitte machen Sie auch ein wenig Zeit für Ihre Definition von UNICODE_CHARS - diese Zeichenfolge ist ein wenig zeitaufwändig zu generieren. Sie können diese Zeichenfolge in einem separaten Modul vorgenerieren und einfach importieren.)
Vielen Dank für Ihre Beratung. Ich könnte es schneller machen 3/4. Aber ich muss es schneller 1/10 machen. Ich werde versuchen, Psyco oder etwas .. –
Psyco ist nicht am Leben. Pypy ist auf Python 3.5 nicht verfügbar. –
Ich verschiebe Grammer-Definitionen aus dem Funktionsumfang heraus. Die Leistung ist verbessert. Es ist 1/20. Vielen Dank! –