質問

私はLexとYACC(実際にはFlexとバイソン)とコンパイラを作成しています。言語は(C#のような)任意のシンボルに無制限の前方参照を可能にします。問題は、それが識別子が何であるかを知らずに言語を解析することは不可能だということです。

私の知っている唯一の解決策は、クラス宣言と関数宣言のような高いレベルのものは、それらを使用する関数の前に解析されますので、全体のソースをlexの、そして「幅優先」の解析を行うことです。しかし、これは大きなファイルのために大量のメモリを取るだろうし、(私が宣言/体の種類ごとに別々の文法を作成する必要があります)YACCで処理するのは難しいだろう。私はまた、(問題のそれほどではありません)レクサーを、書く手なければならないだろう。

私は、私はそれを終えたら、自分自身でコンパイラを書き換えるするつもりですので、私は、(それはまだ重要であるが)効率についての全体の多くを気にしませんが、私はしたいバージョンは高速であること(そうがある場合レックス/ YACCで行うことができませんが、手で行うことができます任意の高速の一般的な技術は、)も、それらを提案してください。だから、今、開発のしやすさは、最も重要な要因である。

この問題に対して何か良い解決策はありますか?これは通常、C#やJavaのような言語のためのコンパイラではどのように行われる?

役に立ちましたか?

解決

これは、それを解析するために完全に可能です。識別子とキーワード間のあいまいさがありますが、lexが喜んキーワードの優先度を与えることによって、その対処します。

私はそこにある他のどのような問題が表示されません。識別子が構文解析段階で有効であるかどうかを判断する必要はありません。あなたが解析して(この議論の目的のために違いは微妙ですが、無関係な)解析ツリーまたは抽象構文木のいずれかを構築しています。その後、あなたは解析中に発生したAST上のパスを実行して、ネストされたシンボルテーブルの構造を構築します。次に、あなたが使用される識別子が有効であることを確認するためにASTの上に別のパスを行います。出力コード、またはいくつかの他の中間データ構造を生成するために、ASTの上に1つの以上の追加のパースでこれに従ってください、あなたは完了です。

EDIT:あなたはどのように行うのを見たい場合は、モノC#コンパイラのソースコードを確認してください。これは、実際にはむしろ、CまたはC ++よりもC#で記述されたが、それはyaccのに非常によく似ているジェイの.NETポートを使用しているます。

他のヒント

1つのオプションは、あなたがどのように本当の(一種の「パニックモード」エラー回復など)とに知っている何かを打つまでちょうどスキャンとキャッシュトークンによって前方参照に対処することです。あなたは完全なファイルを考えて実行したら、戻って、前に解析されませんでしたビットを解析し、再してみます。

レクサーを書く手に持つこととして、 、使用lexが通常のパーサを生成し、ちょうどあなたが戻って、LEXが作るもの、キャッシュからパーサを養うだけでなく、することができます手書きのシムを経由して、そこから読み取ることがありません。

のyaccファイルのプリプロセッサで、いくつかの文法、ささやかな楽しみを作り、あなたが同じオリジナルソースからそれらすべてを作ることができるはずに関しては、

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top