2011-12-22 22 views
0

私は現在、自分のニーズに遅すぎる(例えば、私が望むより40倍遅い)パーサーに取り組んでおり、スピードを上げる方法についてアドバイスをしたいと考えています。私は試して、strscanner classを使用しているカスタムパーサーと同様にcustom regex parserを現在使用しています。私はtreetopに関する多くの肯定的なコメントを聞いて、すべてのマッチをカバーする1つの巨大な正規表現に正規表現を組み合わせようと考えましたが、パーザをもう一度書き直す前にいくつかのフィードバックを得たいと思います。私は解析い文字列解析の最適化:ruby

文字列の基本的なルールは次のとおり

  • 3セグメント(BOL演算子、メッセージ、行末演算子)
  • 〜6ボル演算子を BOLオペレータは、任意の順序であってもよい
  • 2行末演算子行末演算子は、任意の順序で任意の特定のオペレータの
  • 数量残りが除去される0,1、又は> 1のみ1に使用されることができ、Tで
  • 演算子を廃棄することができます彼は、文字列の「メッセージ」セクションがキャプチャされていない/
  • の空白がオペレータの後&前に許可されますが、一部BOL事業者が私の現在の正規表現のパーサがすることによって動作設定

に空白を持つことができます

  • を必要とされていません削除私はそう...

    loop{ 
    if input =~ /^\s+/ then input.gsub!(/^\s+/,'') end 
    if input =~ /reges for operator_a/ #sets 
        sets operator_a 
        input.gsub!(/regex for operator_a)/, '') 
    elsif input =~ /regex for operator_b/ 
        sets operator_b 
        input.gsub!(/regex for operator_b/,'') 
    elsif input =~ /regex for operator_c/ 
        sets operator_c 
        etc .. etc .. etc.. 
    else 
    break 
    end 
    } 
    

    として質問を一度にボルまたは行末オペレーター1をチェックするループを文字列を実行し、それらを切り出し、与えられたタイプのこれ以上の事業者が存在しない場合、ループを終了しますこのコードを最適化するにはどうすればよいでしょうか?私がまだ見つけていない別のライブラリ/宝石、ループを1つの巨大な正規表現に組み合わせる、何か他のもの?

    すべての回答を制限してRuby言語に入力してください。私はこの仕事のための「最良の」ツールではないことを知っています。それは私が使用する言語です。

    もっと具体的な文法/例が役立ちます。 これは、ユーザーがゲームに送信した通信コマンドを解析するためのものです。これまでのところ、唯一のコマンドはsay、whisperです。受け入れられるライン演算子のbegenningは:: {target}、:{adverb}、= {verb}、#{direction of}です。行末演算子は{emoticon(別名:D :(:)}で、副詞はまだ設定されていない場合に設定され、行末には動詞が設定されていない場合に設定されます。 文字 ' #私の実権を握っボルコマンドオペレーターの仕事として=幸せ::私の剣

    {:action=>:say, :adverb=>"happily", :verb=>"ask", :direction=>"my helm", :message=>"Bol command operators work."} 
    

    うん作品を言う言う:

    」とsaytoは言う:: 例の別名です。

    {:action=>:say, :message=>" yep say works"} 
    

    sayto私の剣yep saytoはEoL演算子と同様に動作します!:)

    {:action=>:say, :target=>"my sword", :adverb=>"happily", :verb=>"say", :message=>"yep sayto works as do EoL operators!"} 
    

    ささやき::私の友人:幸せボルコマンドオペレータが ささやきで動作します。

    {:action=>:whisper, :target=>"my friend", :adverb=>"happily", :message=>"Bol command operators work with whisper."} 
    

    whisp:幸せ::ティンカーベル、彼らは異なる順序で動作します。

    {:action=>:whisper, :adverb=>"happily", :target=>"tinkerbell", :message=>"and they work in a different order."} 
    
    「:バッシュ=叫ぶ::あまりにもこの順でハンマーボルオペレーターの仕事。鐘= sayto

    {:action=>:say, :adverb=>"bashfully", :verb=>"exclaim", :target=>"hammer", :message=>"BoL operators work in this order too."} 
    

    言う:悲しい#wontworkボル> EOLと監督を指向 と連携!? :)

    {:action=>:say, :verb=>"say", :adverb=>"sadly", :direction=>"wontwork", :message=>"Bol > Eol and directed !work with directional?"} 
    

    「すべての行末を使用して再挿入末端に最も近いを削除しました。 !! ??!?....... :) ? :(

    {:action=>:say, :adverb=>"sadly", :verb=>"ask", :message=>"all EoL removed closest to end used and reinserted?"} 
    
  • +1

    regexpsをループの前に変数に展開すると、少し改善が見られるかもしれません: 'op_a_re =/regex for operator_a /; loop {... input〜= op_a_re ...}';暗黙の 'Regexp.new'をループごとに1回ではなく1回繰り返します。非常に単純なベンチマークは1.9.2で5%だけスピードアップしました。 – Amadan

    +0

    @Amadan非常に良い点!私は、コードのクリーンアップ段階に入ったときにそのことを考えていましたが、スピードにも影響するとは考えていませんでした。 TY – JosephRuby

    +0

    あなたが解析しようとしていることをあまり知らずに、質問に答えるのは難しいです。実際の文法が有益であるように聞こえるように聞こえますが、必ずしもそれが*より速くなるとは限りません。例がなければ、理論化するのは難しいです。 –

    答えて

    3

    たぶん、この構文は、あなたの場合に有用である:

    emoti_convert = { ":)" => "happily", ":(" => "sadly" } 
    re_emoti = Regexp.union(emoti_convert.keys) 
    str = "It does not work :(. Oh, it does :)!" 
    
    p str.gsub(re_emoti, emoti_convert) 
    #=> "It does not work sadly. Oh, it does happily!" 
    

    しかし、あなたは文法を定義しようとしている場合、これは進むべき道ではありません(@Daveニュートンに同意コメント)。

    +0

    私は正直なところ、正規表現のハッシュが非常に素晴らしいテクニックのようなgsubで使用できることを知らなかった!この場合でも助けになるとは思わないでください。 – JosephRuby