1

正規表現を使用して .h ファイルから .cpp ファイルを生成し、正規表現を使用して結果を戻り値の型と関数の 2 つに分割する perl スクリプトを作成しています。

ほとんど機能する戻り値の型を見つけるための正規表現を作成しました。

^(\s*&?\w*\s*(\<{1}.*\>{1})*\s)

編集:正規表現文字列をより適切に機能するものに更新しましたが、この質問に関する限り変更はありません。

これは、次のようなほとんどの cpp プロトタイプで機能します。

int funky();
int funky(int something);
&int funky(int something);
&int <vector *> funky();

これらの場合、正規表現が一致します

int
int
&int
&int <vector *>

これは完璧ですが、関数の引数内に一致する文字列がある場合は次のようになります。

int <vector> funky(int <vector> i);
int <vector> funky(int <vector *> i);
int <vector> funky(const int <vector> i);

正規表現が一致します

int <vector> funky(int <vector>
int <vector> funky(int <vector *>
int <vector> funky(const int <vector>

返してほしいとき

int <vector>
int <vector>
int <vector>

そして、最初の閉じ括弧 '>' の終わりを超えてホエーが続いていることがわかりません. 私は正規表現が初めてで、これを理解できません。

申し訳ありませんが、これには答えがあります。検索しても見つかりませんでした。おそらく、どの用語を探すべきかさえわからないためです:(。

Edit2: この質問が予想よりも複雑である場合、最初の <.*> を超えて続く理由を誰かが説明できますか? なぜこれが機能しないのかわかりません。

4

3 に答える 3

3

正規表現は素晴らしいです-正規言語の場合。ただし、ほとんどのプログラミング言語は規則的ではありません。ある種の中括弧と再帰を持つものはすべて、文脈自由言語であり、文脈依存ですらあります。(これらのCS用語が混乱する場合は、ウィキペディアで調べてください。便利です)。

特にCは非常に複雑な文法を持っています。

ただし、Perlの正規表現は正規表現に制限されていません。文脈自由文法を表現できます。つまり、文字列が一致しなければならない一連のルールを定義できます。各ルールでは、他のルールを参照できます。このため、再帰や、ネストされた親のマッチングなどを行うことができます。

m{
   ^ (?&NESTED_PAREN) $
   (?(DEFINE)
     (?<NESTED_PAREN> [(] (?: [^()]+ | (?&NESTED_PAREN) )* [)] )
   )
}x;

この正規表現は、最上位のルールを定義します。最初から最後までの文字列全体は、ネストされた親である必要があります。次に、DEFINEブロックに従います。NESTED_PARENaで始まり、(任意の数の非親文字とネストされた親を含むことができる1つのルールを定義します。その後に。が続き)ます。無限に再帰する文法を書くのは簡単であることを考慮に入れる必要がありますが、幸いなことに、この例では、各再帰が文字を消費するか失敗します。

Perlで文法を書くためのより良いインターフェースとして、CPANのRegexp::Grammarsを強くお勧めします。

これで、Perlで文法を書く方法がわかり、関数宣言用の文法を作成できるようになりました。空白のない記号表記は次のとおりです。

FUNCTION ::= TYPE VECTOR? NAME '(' ARGUMENTS ')'
VECTOR   ::= '<' vector '*'? '>'
ARGUMENTS::= ( ARGUMENT (',' ARGUMENT)* )?
ARGUMENT ::= TYPE VECTOR? NAME

引数リスト内の関数のルールの一部を再利用できることに気付いたかもしれません。これで、この文法を一連の(DEFINE)ルールにマップし、最上位のルールを作成するだけで、準備が整います。繰り返しになりますが、Regexp :: Grammarsを使用すると、この作業がはるかに簡単になりますが、学習する必要のある別の言語が提供されます。

Perl正規表現に組み込まれている機能の最終的なリファレンスについては、 perldocperlreを参照してください。

(特にプリプロセッサのために)C(およびC ++)構文は規則的でも文脈自由でもないことに注意してください。プリプロセッサを実行する以外のすべては、良い試みになるでしょう…</ p>

于 2012-09-22T21:59:02.837 に答える
2

正規表現は貪欲です。使う ?あなたの .* に続いて貪欲ではなく、最後の一致ではなく最初の一致で停止します。

^(\s*&?\w*\s*(\<{1}.*?\>{1})*\s)

詳細はhttp://perldoc.perl.org/perlre.html#Regular-Expressionsをご覧ください:

于 2012-09-22T22:39:35.523 に答える
1

これを行う別の方法は次のとおりです。

/^\s*&?\w*(\s+\<[^\>]+\>)?/

括弧内の部分は(\s+\<[^\>]+\>)?、スペースで始まり、「<」、「>」(否定文字クラス[^\>]+)、「>」以外の文字が続くテキストです。

">"の否定文字クラスは、<>部分が終了するとすぐにマッチングが終了することを保証します。また、括弧の後には「?」が続きます。式のオプション部分にします。

于 2012-09-23T14:32:54.013 に答える