2017-04-06 6 views
1

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」の機能があるよう

+0

'number'を' pyparsing_common.number'に置き換えてください。あなたの 'str_to_num'解析アクションと同じようにintまたはfloatに変換されますが、より重要なのは、コンバインでラップされた一連の小さな式の代わりに単一のRegexを使って構文解析を行うことです。私は、この単純な変更が測定可能なパフォーマンスの差を生み出すことができることを発見しました。 – PaulMcG

+0

それだけで削った〜.5ms – user3747260

+0

あなたは限界に近づいているかもしれません - パイピングの美徳はランタイムスピードではありません。 – PaulMcG

答えて

1

に見えますWordの2つの引数の形式を使用する - ちょうどWord(alphanums+"_")を使用すると、私はは、はあなたの意志だと思う普通の整数に一致するだろう。もしこれが間違っていたら、あなたが持っていたものを戻してください。

+0

ご協力ありがとうございます。これは約3.8msにまで下がりましたし、私のトークン処理のロジックをよりシンプルにしました。 – user3747260