1
  for(int k = 0 ; k < 5.25;k++)
     {
      cout<<"hello"<<endl;
      }
    return 0;

C++ コードを含む単純なテキスト ファイルで字句解析用の C++ プログラムを作成しています。例えば

次に、プログラムがファイルからコードを抽出した後、コンソールに出力します。

   for: keyword
     (: separator
     int: keyword
     k: identifier
     =: operator
     0: integer
     ;: separator
     k: identifier
     <: operator
     5.25: real
     and so forth.
    I already have "(\\w+)" for words, "(\\d+)" for integers, however I don't
    know how to write any of the rest.

私の実際のコードが正規表現でどのように見えるかを示すために、ここに示します。

     void lexical_integer(string seq)
     {

regex digits("(\\d+)");
regex_iterator<string::iterator> itd(seq.begin(), seq.end(), digits);
regex_iterator<string::iterator> end;

for (; itd != end; ++itd)
{
    cout << itd->str() <<" " <<" integer"<< endl;
}
     }

C ++の正規表現で使用できる正規表現を探しているので、「(\ w +)」整数:「(\ d +)」セパレータ:?演算子: ? 実数: ?

4

1 に答える 1

0

正規表現は、トークン化中に維持する必要がある状態/コンテキストがあるため、正しく取得するのが難しくなります。入力を 1 文字ずつ読み取り、手動でトークンを作成することをお勧めします。

C の場合は次のようになります (C++ については後で詳しく説明します)。

表示された場合は/、先を見る必要があり、別の がある場合/は、行末まですべてをスキップします。

/の後に が続く場合は*、別の まですべてをスキップします*。次の*char がそうでない場合は/、 までスキップに戻り、オープニングとクロージング*が一致したときに終了します。/**/

そのようなもので、すべてのコメントをスキップします。

または/が続いていない場合は、 とを区別するために が続いているかどうかをさらに確認する必要があります。/*=//=

これらのいずれかが表示された場合、それはトークンです: ,;?:()[]{}

が表示された場合は、 または のいずれか!になる可能性があるため、先を見る必要があります。 が表示された場合は、 または のいずれかになる可能性があるため、先を見る必要があります。 が表示された場合は、 または のいずれかになる可能性があるため、先を見る必要があります。 が表示された場合は、 または のいずれかになる可能性があるため、先を見る必要があります。 が表示された場合は、 または のいずれかになる可能性があるため、先を見る必要があります。!!=
***=
%%%=
^^^=
~~~=

表示される場合は、またはまたは+のいずれかになる可能性があるため、先を見る必要があります。++++=

表示された場合は、またはまたはまたは-のいずれかになる可能性があるため、先を見る必要があります。----=->

表示された場合は、またはまたはまたは<のいずれかになる可能性があるため、先を見る必要があります。 表示された場合は、またはまたはまたはのいずれかになる可能性があるため、先を見る必要があります。<<=<<<<=
>>>=>>>>=

表示される場合は、またはまたは&のいずれかになる可能性があるため、先を見る必要があります。 表示される場合は、またはまたはのいずれかになる可能性があるため、先を見る必要があります。&&&&=
|||||=

L(または小文字の ) が表示されている場合は、リテラル文字または文字列定数またはlを開始できるため、先読みする必要があります。それ以外の場合は、何らかの識別子の開始です。L'c'L"string"

_または ASCII 文字の from atozまたは from Atoが表示された場合Z、それは何らかの識別子の始まりです。この後に任意の数のアンダースコア、文字、または 10 進数を続けることができます。この方法で解析された識別子は、、、、、などの予約済みキーワードのセットに対してさらにチェックする必要がintあります。constifswitch

0からまでの 10 進数が表示される場合は、9複数のオプションがあります。8 進整数定数、10 進整数定数、16 進整数定数、浮動小数点定数です。上記と同様に、それらを解析する方法を理解できるはずです。定数には、、、、、および の接尾辞を付けることができることにU注意ULULLLください。LLF

表示される場合は、またはまたは のようなもの.になる可能性があるため、先を見る必要があります。.....5

リテラル文字または文字列定数の解析とトークン化については説明しません。内部にはエスケープ シーケンスなどのロジックがいくつかあります。

現在、C++ では、(解析の拡張)、(解析の拡張)、(解析の拡張) などの追加の::解析:.*行う必要があります。.->*-newvirtualandbitornot_eq

そして、C++ には驚きがあります。テンプレートの山かっこは、間にスペースを入れずに組み合わせることができるようになりました。

X<Y<Z> >

合法的に次のように書けるようになりました:

X<Y<Z>>

>>パーサーは、最後のテンプレートが 2 つの別々のであることを理解するために、このテンプレート ビジネスを十分に理解する必要があり>ます。

いくつかのプリプロセッサ関連のトークン (たとえば#and ##includeifdefifなどundef) と醜いトライグラフ シーケンスもあります。そしてもちろん、 との行連結があり\ます。

これは楽しい小さな (またはそれほど少なくない) プロジェクトであり、特に受け入れられる入力の種類を制限する場合は、それほど手間をかけずに実行できます。

いずれにせよ、実際にはプロセスにいくつかのステート マシンを実装する必要がありますが、それらがどれほど単純であっても (ほとんどのマシンは単純になります)。

于 2012-09-25T04:00:37.820 に答える