1

のような文字列を解析する必要がありますfunc1(arg1, arg2); func2(arg3, arg4);。これはそれほど複雑な構文解析の問題ではないので、flex/bisonまたは同様のユーティリティに頼るのは避けたいと思います。

私の最初のアプローチは、POSIXCregcomp/regexecまたはC++のBoost実装を使用することでしたstd::regex。次の正規表現を作成しましたが、機能しません(理由については後で説明します)。

 "^"
 "[ ;\t\n]*"
 "(" // (1) identifier
    "[a-zA-Z_][a-zA-Z0-9_]*"
 ")"
 "[ \t\n]*"
 "(" // (2) non-marking
    "\["
    "(" // (3) non-marking
       "[ \t]*"
       "(" // (4..n-1) argument
          "[a-zA-Z0-9_]+"
       ")"
       "[ \t\n]*"
       ","
    ")*"
    "[ \t\n]*"
    "(" // (n) last argument
       "[a-zA-Z0-9_]+"
    ")"
    "]"
 ")?"
 "[ \t\n]*"
 ";"

1グループは識別子をキャプチャし、グループ4..n-1はグループによってキャプチャされる最後の引数を除いて引数をキャプチャすることを目的としていることに注意してくださいn

この正規表現をに適用するとfunc(arg1, arg2, arg3)、得られる結果は配列であると言い{func, arg2, arg3}ます。入っていないのでこれは間違ってarg1います!

問題は、標準の正規表現ライブラリでは、サブマーキングは最後の一致のみをキャプチャすることです。つまり、たとえば正規表現を"((a*|b*))*"適用した場合"babb"、内部一致の結果は次のようにbbなり、以前のすべてのキャプチャは忘れられます。

ここで私を悩ませているもう1つの点は、エラーが発生した場合、入力が拒否されたときのパーサーの状態に関する情報がほとんど提供されないため、どの文字が認識されなかったかを知る方法がないことです。

だから私はここで何かが欠けているかどうかわかりません...この場合sscanf、代わりにまたは同様のものを使用する必要がありますか?

私はC/C ++標準ライブラリを使用することを好むことに注意してください(そしておそらくブースト)。

4

3 に答える 3

2

正規表現を使用する場合は、2 つのステップに分割する方が簡単でしょうか。ステップ1で見つけます

func1(stuff);

そしてそれをに変えfunc1stuff

次のステップでは、「stuff」を解析して、関数の個別の引数をすべて見つけます。

于 2010-04-19T14:41:53.543 に答える
2

ブーストスピリットはどうですか?

于 2010-04-19T14:37:26.023 に答える
1

これが Ruby だったら、マッチングから始めます

%r{
   ([a-zA-Z_][a-zA-Z0-9_]*)   #identifier
   \s*                        #whitespace after the identifier
   \(                         #open paren
     ([^)]*)                  #all arguments as one string
   \)                         #close paren
}x

次に$2.split(/\s*,\s*/)、引数を分割するために使用します。C++ 標準ライブラリには同等のものはないと思いますがsplit、boost::regex_split でできると思います。

于 2010-04-19T14:40:43.040 に答える