infixNotation
の実装は、enablePackrat
を使用しても私が望むよりも遅く実行されており、パフォーマンスが大幅に向上しました。pyparsing infixNotation最適化
解析は、文字列の次の種類を認識し、解析する必要があります。
- 基本的な算術演算、数字、否定、および括弧のグループ化 形式で
- グループ化関数呼び出しのように見える
prefix::dotted.alphanum.string -> [prefix::dotted.alphanum.string]
- 文字列を例えば
pow(some::var + 2.3, 5) -> [pow, [[some::var, +, 2.3], 5]]
私が使用しているコード:
def parse_expression(expr_str):
fraction = Combine("." + Word(nums))
number = Combine(Word(nums) + Optional(fraction)).setParseAction(str_to_num)
event_id_expr = Word(alphanums + "_") + "::"
dotted_columns = Combine(Word(alphanums + "_") + Optional("."))
column_expr = Combine(event_id_expr + OneOrMore(dotted_columns))
arith_expr = infixNotation(column_expr | number, [
(Word(alphanums + "_"), 1, opAssoc.RIGHT),
("-", 1, opAssoc.RIGHT),
(oneOf("* /"), 2, opAssoc.LEFT),
(oneOf("+ -"), 2, opAssoc.LEFT),
(Literal(","), 2, opAssoc.LEFT)
])
parsed_expr = arith_expr.parseString(expr_str).asList()[0]
return parsed_expr
def str_to_num(t):
num_str = t[0]
try:
return int(num_str)
except ValueError:
return float(num_str)
は、私はそれが実質的なパフォーマンスの改善につながることができます任意の変更はありますか?私が解析している構造はかなりシンプルですが、バッチに入っています。平均して各文字列は〜5.3msかかります。私はまた、あなたの識別子のほとんどを修正
def parse_expression(expr_str):
number = pyparsing_common.number()
event_id_expr = Word(alphas+"_", alphanums + "_") + "::"
dotted_columns = Combine(Word(alphas+"_", alphanums + "_") + Optional("."))
column_expr = Combine(event_id_expr + OneOrMore(dotted_columns))
func_name = Word(alphas+"_", alphanums+'_')
LPAR, RPAR = map(Suppress, "()")
arith_expr = Forward()
func_call = Group(func_name('name')
+ LPAR
+ Group(Optional(delimitedList(arith_expr)))("args")
+ RPAR)
arith_expr <<= infixNotation(number | func_call | column_expr, [
("-", 1, opAssoc.RIGHT),
(oneOf("* /"), 2, opAssoc.LEFT),
(oneOf("+ -"), 2, opAssoc.LEFT),
])
parsed_expr = arith_expr.parseString(expr_str)[0]
return parsed_expr
:彼らは、オペレータが、私はあなたが動い機能がinfixNotation
のためのオペランド式を呼び出したほうが良いと思いますされているかのようにあなたが「fudging」の機能があるよう
'number'を' pyparsing_common.number'に置き換えてください。あなたの 'str_to_num'解析アクションと同じようにintまたはfloatに変換されますが、より重要なのは、コンバインでラップされた一連の小さな式の代わりに単一のRegexを使って構文解析を行うことです。私は、この単純な変更が測定可能なパフォーマンスの差を生み出すことができることを発見しました。 – PaulMcG
それだけで削った〜.5ms – user3747260
あなたは限界に近づいているかもしれません - パイピングの美徳はランタイムスピードではありません。 – PaulMcG