Razorパーサーは、既存のASPXパーサーとは大きく異なります。 実際、構文が解析するのに十分単純であるため、ASPXパーサーはほぼ完全に正規表現に基づいて構築されています。 Razorパーサーは、3つのコンポーネントに分かれています。
- HTML構文の基本的な理解を持つマークアップパーサー。
- C#またはVBの基本的な表現を持つコードのパーサー。
- そして、2つのパーサーを接続する方法を知っているメインの「指揮者」。
「基本的なプレゼンテーション」と言うとき、私は基本を意味しますが、完全に独立したC#およびHTMLパーサーについては話していません。 私たちのチームでは、「マークアップ識別子」と「コードインタープリター」と呼んで冗談を言います:)
合計で、Razorステージでは、カーネルパーサー、マークアップパーサー、コードパーサーの3つの「アクター」が再生されます。 3つすべてが連携して、Razorドキュメントを解析します。 それでは、Razorファイルを使用して、アクターデータを使用した解析手順の完全な概要を説明しましょう。 次の例を使用します。
それでは、上から始めましょう。 実際、Razorパーサーは、ドキュメントのマークアップの解析、ブロックのマークアップの解析、コードブロックの解析など、解析のどの時点でも状態の1つにあります。 最初の2つはマークアップパーサーによって処理され、最後の2つはコードパーサーによって処理されます。 カーネルパーサーを初めて起動すると、マークアップパーサーが呼び出され、ドキュメントのマークアップを解析して結果を返すように求められます。 これで、パーサーはドキュメントのマークアップを解析する状態になりました。 この状態では、彼は「@」文字を検索するだけで、どのタグに遭遇するか、HTMLに関するすべてを気にしません。主な目標は「@」です。 @を見つけたとき、彼は決定します-コードまたは電子メールアドレスに切り替えますか? このソリューションは、@の前後の文字に基づいており、メールアドレスの有効性をチェックします。 これは単なる標準的な手順であり、コードモードに切り替える一連のチェックがあります。
この場合、最初の「@」文字が表示されると、その前にスペースが付きますが、これは電子メールアドレスには無効です。 したがって、コードモードに切り替える必要があることは確かです。 マークアップパーサーは内部でコードパーサーを呼び出し、コードブロックの解析を要求します。 Razorパーサーの定義におけるブロックは、基本的に明確な開始と終了を持つ単一のコードまたはマークアップです。 したがって、この場合の「foreach」はコードブロックの例です。 文字「f」で始まり、「}」で終わります。 コードパーサーはこれを理解するのに十分なC#を知っているため、コードの解析を開始します。 コードパーサーはC#ステートメントの簡単な追跡を行うため、「<li>」に到達すると、タグがC#式の先頭にあることを認識します。 「<li>」をC#式の先頭に配置することはできないため、コードパーサーはマークアップブロックがこのポイントから開始することを認識しています。 したがって、HTMLブロックを解析するために、マークアップパーサー呼び出しに戻ります。 これにより、コードパーサーとマークアップパーサーの間に一種の再帰的なピンポンが作成されます。 一連の呼び出しの結果が得られるまで、マークアップから始めて、内部のコードを呼び出し、次にマークアップを再度呼び出します。
(もちろん、リストから多くのヘルパーメソッドを除外しました:)。
これにより、ASPXとRazorの根本的な違いが明らかになります。 aspxファイルでは、コードとマークアップを2つの並列スレッドと考えることができます。 マークアップを記述し、ジャンプしてコードを記述し、戻ってマークアップを記述します。 ツリーと同じファイルをかみそり。 マークアップを記述してからコードを挿入し、コードにマークアップを挿入します。
したがって、マークアップブロックを解析するためにマークアップパーサーを呼び出しました。ブロックは「<li>」で始まり、「</ li>」で終わります。 「</ li>」が見つかるまで、マークアップブロックは終了したと判断します。 したがって、「<li>」内のどこかに「}」がある場合、「foreach」は完了しません。スタックを十分に進めていないからです。
「<li>」の解析中、マークアップパーサーは多くの「@」文字を認識します。これは、コードパーサーへの多くの呼び出しを意味します。 したがって、呼び出しスタックは大きくなります。
プロセスは少し複雑なので、後で処理ブロックの詳細を掘り下げます。その結果、これらのブロックはコードで終わり、「<li>」ブロックに戻りました。 次に、「</ li>」が表示されるため、このブロックを完了して「foreach」ブロックに戻ります。 「}」ブロックを閉じるので、再びスタックの最上位、マークアップドキュメントになります。 その後、ファイルの最後に到達するまで読み取り、「@」文字が見つからなくなるまで読み取ります。 そして出来上がり! このファイルを解析しました!」
解析アルゴリズムの一般的な構造が明確であることを願っています。 主なことは、コードパーサーとマークアップが別々のスレッドで機能するという考えをやめることです。代わりに、構造は互いに配置されます。 PowerShellからインスピレーションを得たことを示唆します;)。