4

Cは厳密に順番に解析されます。つまり、使用する前にすべてを宣言する必要があります。特に、型はそれらの型の変数の前に宣言する必要があります。型の名前が何であるか、何がそうでないかがわからない場合、たとえば、型に名前を付けるa * bかどうかによって、文法があいまいになるため、これは理にかなっていますa

一方、一部のCファミリ言語には、この制限を緩和するという望ましい特性があります(したがって、ヘッダーファイルの手動ジャグリングを排除します)。同様にその制限を緩和することを目的としたCスーパーセット言語のパーサーを書いているので、今度はそれを行う方法を理解する必要があります。

私が思い浮かぶ1つの方法は、2つのパスを実行することです。最初のパスは、トップレベルのすべてがステートメントではなく宣言でなければならないという事実を利用して、すべてを通過し、すべてのタイプを取得します。この段階では、関数本体は検査されずに残され、中括弧を一致させることによって区切られたトークンストリームとして取得されます。2番目のパスは、関数本体を解析します。関数内のローカル宣言は適切である必要がありますが、それは実際には問題ではありません。

その方法で私が考えていなかった障害はありますか?

C ++、Java、C#などのコンパイラは、通常、宣言を順番に必要としない言語の部分に対してどのように処理しますか?

4

3 に答える 3

2

解析時に名前解決を行う必要はありません。まず、(新しい C 実装とは対照的に) "C に似た" 言語を設計している場合は、構文を定義して、宣言、式、メソッドなどがすべて構文内で明確になるようにすることができます。その場合、解析順序は重要ではありません。(これにより、構造化された方法でプリプロセッサを言語に統合することで、プリプロセッサ病も修正されます)。

C に似た構文を主張する場合は、あいまいさを許容するパーサーを使用できます。たとえば、"x*y;" を喜んで処理します。さらにデータを取得するまで、式と宣言の両方として保持します。極端な場合は、これを制約ベースの解決と考えてください。C と C++ は最初に定義を知ることを主張しました。もともとコンパイラのメモリ空間はかなり制限されていて、すべてを保持することはできなかったからです。それはもはや真実ではありません。解析時に答えを知っていると主張する必要はありません。

これには、DMS ソフトウェア リエンジニアリング ツールキットで GLR パーサーを使用します。C と C++11 を問題なく解析できて、非常に満足しています。解析後に名前解決を行います。これにより、解析と名前解決が分離され、フロントエンドがよりクリーンで管理しやすくなります。

于 2013-02-05T16:45:08.100 に答える
1

C++では順序宣言が必要です。

C と C++ はまったく別の球技であることに注意してください。彼らは積極的に古いリンカー技術を使用しています(C古いため、C++はほとんど同じように古く、Cリンカーと互換性があるため)。どちらも、CPU で直接実行されるバイナリになり、ランタイム サポートはありません。

Java と C# には、依存するリンカーが大幅に改善されており、使用する巨大なランタイム サポート システムがあります。

どちらにも長所と短所があります。C/C++ アプローチの短所の 1 つは、実行時にアプリケーションが独立しているため、コンパイル時にすべてを解決する必要があることです。長所は、すべてがコンパイル時に解決されるため、実行時にアプリケーションをそのままにしておくことができることです。

于 2013-02-05T14:49:29.753 に答える
0

ほとんどすべてのコンパイラは 2 つのパスを実行します。もう 1 つの方法は、文法自体で変数の宣言を許可することです。これにより、文法を手動で解析するのが非常に難しくなりますが、2 回目のパスが不要になります。

于 2013-02-05T14:47:28.973 に答える