24

さて、コンパイラを書くために必要なものを見つけようとしているうちに、ちょっとした障害にぶつかりました。私が見つけたすべてのテクノロジーやツールには、どこかで何らかの反対があるようです。

現在 Bison と Flex を使用していますが、この方法は時代遅れだと感じています。これは本当ですか?これは、本格的なプログラミング言語の作成を進めるための優れた前方互換性のある方法ですか?

さまざまな概念とツールの海 (ANTLR、LL(k)、GLR、LALR、LLVM、Flex、Bison) コンパイラを作成するための現在の傾向とベスト プラクティスは何ですか? ドラゴンブックは時代遅れですか?

4

8 に答える 8

30

真に単純なコンパイラーを書きたくないのでない限り、あなたの焦点は間違っています。

コンパイラを書くことは、パーサーを書くことのほんの一部にすぎません。パーサーを持つことは、問題がエベレスト登頂であるときに、ヒマラヤ山脈のふもとを登るようなものです。ふもとの丘の頂上にたどり着き、上を見上げると、あと 20,000 フィートしかありません。そして、山麓の頂上に到達するために必要な技術は、残りの道を行くために必要な技術よりもはるかに簡単であることに気付くでしょう.

(参考までに: 現在最高の構文解析技術はGLRであり、文法をハッキングすることなく、あいまいな文法を簡単に受け入れることができます。GLR は C++ を簡単に構文解析することさえできます。これは、C++ は構文解析が難しいという一般的な定理に違反しています。一般的な定理は、YACC を使用しようとする人々から生まれました。 ANTLR を使用して解析します)。

コンパイラを構築するには、多くの機械が必要です。

  • アストビル
  • シンボルテーブルの構築
  • 制御フロー分析
  • データフロー分析
  • 基本的にデータ フロー計算 (SSA またはトリプル) としてのプログラム コードの表現
  • ターゲット マシンのモデル
  • プログラム コードを機械語命令にマップする手段
  • 登録割付
  • 最適化: 定数伝播、ループ展開、...

グローバル フロー解析、グローバル最適化、または SIMD 命令やキャッシュ最適化を含む現代の命令セットの特別な処理にはまだ近づいていません。... リストは延々と続きます。Dragon book は、基本的なトピックについては適切に紹介していますが、高度なトピックについては触れていません。Cooper の "Engineering a Compiler" と Muchnick の "Advanced Compiler Design" が参考になるでしょう。始める前にそれらをざっと目を通しておけばよいでしょう。

最新のコンパイラを構築することは、エンジニアリングの偉業です。

于 2009-11-06T03:48:26.203 に答える
11

構文解析は、十分に研究されていますが、コンパイルの最も重要でない部分です。(例外:独自の具体的な構文を設計していて、言語を継続的に改良および変更しています。)

Yacc、Bison、およびその仲間たちは、64Kのメモリを搭載したマシンの時代のために設計されました。メモリが限られているマシンで高速に実行するのに最適です。しかし、文法をLALR(1)形式に強制するために必要な人間工学の量は、今日ではばかげています。Ira Baxterは、GLRがおそらく最高の、最も柔軟な解析テクノロジであるということは正しいですが、PEG(Parsing Expression Grammars)も優れています。どちらの場合も、人間工学は古いツールよりも光年進んでいます。

解析を却下したので、今度は別のテクノロジーフードファイトを開始します:-)コンパイルは、最終的にアセンブリコードまたはマシンコードに到達するまで、プログラムをあるフォームから別のフォームに何度も書き直すことで構成されます。この種の問題では、CまたはC++を実際には使用したくありません。

Q :(デイブハンソンがクリスフレイザーと一緒にlccに関する素晴らしい本を出版したときに尋ねられました)「あなたとクリスは、これまでに作られた中で最も注意深く設計されたコンパイラの1つであるかもしれないものを構築するのに10年を費やしました。あなたは経験から何を学びましたか?」

A:「まあ、Cはコンパイラを書くのにひどい言語です。」

HaskellやStandardMLなどの人気のある関数型言語の1つを試してみることをお勧めします。この分野で働く人々は、コンパイラーが関数型言語の「キラーアプリ」であると広く信じています。代数的データ型とパターンマッチングは、抽象構文を中間コードから機械語に書き込むためにカスタマイズされています。これらのテクニックの力を見るのに良い場所は、AndrewAppelの本CompilingWithContinuationsです。(Appelのコンパイラの教科書もよく読まれており、非常にエレガントなデザインですが、なぜデザインがそのようになっているのかを常に説明しているわけではありません。)

于 2009-11-07T03:15:52.177 に答える
7

コンパイラを構築するには、巨人の肩の上に立つことを強くお勧めします。コンパイラを作成するために組み合わせることができる優れたものがたくさんあります。私は C/C++ 用のコンパイラーのパートタイムに取り組んでいます。解析に GLR を使用し、AST を構築し、SSA を中間形式として使用し、手続き間の最適化を行い、X86、ARM、MIPS、PowerPC、Sparc などのコードを生成します。

秘密?いくつかのソースからコードを借りました。

  • clang からのプリプロセッサーとエラー報告
  • Elkhound および Elsa コンパイラ ジェネレータと C/C++ コンパイラ
  • 最適化とコード生成のための LLVM システム

パートタイムで働いている私は、非常に便利なツールのシステムをまとめることができました。ゼロから始めようとしていたとしたら、パーサーはほとんど完成していなかったでしょう。;-)

http://ellcc.org

于 2009-11-06T12:44:40.080 に答える
4

あなたは私と同じ立場にいると思います。あなたは楽しみのためにコンパイラを書き、その各段階について少なくとも少し学びたいと思っています。したがって、既存のコンパイラ用のプラグインを作成するだけでは不十分です。また、既存のコンパイラモジュールが多すぎることは避けたいと考えています。ただし、それらが何をしているのかを正確に理解できる場合を除きます。私の場合、私はを使用してbisonいます。これは、私が当たり前と思っていることを少なくともいくつか実行しているため、わずかな例外です(大学で文法などを勉強しましたが、それはかなり前のことです)。一方、パーサージェネレーターは十分に一般的であるため、興味深いコンパイラーステージです。bison多くの解析コードの記述を停止する可能性がありますが、パーサーアクションコードの記述に変更が加えられます。

いくつかのアドバイスに反して、私はあなたがあなたの入力とターゲット言語についてすべてを知らなくても始めることができると思います。いくつかの例外を除いて、言語機能は後で追加するのが不可能なほど難しいことではありません。私が発見した1つの例外は、制御フローです。ツリーフォームで機能するように後の操作のほとんどを記述した場合、、、、および(構造化フォームでさえ)などbreakのステートメントに対応するのが難しい場合があります。したがって、あまり多くのことを行う前に、ツリーからCFGに変換することをお勧めします。continuegoto

  1. 入力の適度に安定したサブセットのパーサーを記述します。
  2. それの有用なメモリ内表現(通常はツリー)を構築するアクションを追加し、それを印刷するようにします。
  3. ターゲット言語に少し似た形で印刷してください。私の場合、「x = y+z;」のツリーノードを出力します。「ADDx、y、z」としてのノード; 「if(c){...}」は「bzc label1」に変わり、「...」、「label1:」の翻訳になります。
  4. 中央にオプションのステージを追加します。これらは、最適化および/またはチェック段階である可能性があります。コードを簡単に生成できるように表現を準備するものが必要になる場合があります。一時変数を追加することで、過度に複雑な式を減らすステージがあります。(「ADD」命令は単純な入力でのみ機能するため、これは実際には出力に必要です。)
  5. 戻って、その一部を改善します。たとえば、パーサーアクションにいくつかのチェックを入れて、その段階でエラーを検出できるようにします(たとえば、宣言されていない変数の使用)。

反復的なアプローチをとれば、これのほとんどを行うのは驚くほど簡単です。

于 2009-11-07T02:49:07.780 に答える
2

さまざまなアプローチを比較することはできませんが、ANTLR グループは幅広い豊富なターゲット言語をカバーしています。

これには、現在一般的なもののほとんどが含まれています。ANTLR は、さまざまな出力言語もサポートしています。CSSライクな言語に取り組む予定です

于 2009-11-06T03:12:57.223 に答える
1

誰かがドラゴンブックが古くなっている可能性があるかどうか真剣に尋ねましたか?それは独創的な仕事人です。最初の2つの章からどれだけ学んだかはわかりません(それ以来、忘れてしまったので... ba-dum-bum)。

すべてのテクノロジー(おそらくgotoステートメントを保存)には、批判者と支持者の両方がいます。「適切なツールの選択を行う」ことに夢中にならないでください。そして、概念を学び、意味のある方法でそれらを実装することに全力を注いでください。つまり、世界で最高のツールを選んだとしても、最近のFORTRANと同じくらい愛され、愛され、尊敬されているものを構築すると思いますか?

もちろん、人間ではありません...多くの学習は間違いを犯すことから来ます。それはあなたが最も学ぶところです。

あなたはそれを行うことができます!

于 2009-11-06T03:21:41.200 に答える
1

Flex と Bison には特に問題はありませんが、もう少し最新 (およびオブジェクト指向) のものを探している場合は、boost の Spirit ライブラリを検討してください。

于 2009-11-06T03:07:25.720 に答える
1

これは、1) Java や C++ のような大きな既存の言語、または 2) 派手なデータ型を持たない小さな言語のためのものですか?

1 の場合は、Ira が言及したすべてのテクノロジについて理解を深めたほうがよいでしょう。

2 の場合は、再帰降下パーサーを作成し、a) 解析時にそれをお好みの言語 (YFL) に変換するか、b) シンボル テーブルと解析ツリーを構築するかのいずれかを行えば、すぐに実行できます。それを歩いて YFL を生成します。YFL を生成したくない場合は、解析ツリーをたどるインタープリターを作成するだけです。

あなたの目標がすべてのトリッキーな技術を学ぶことであるなら、そうしてください。そうでない場合は、手早く汚れた方法を使用します。後者の場合、最適化について心配する必要はありません!!

ところで、あなたが本当に手っ取り早く行きたいと思っていて、C または C++ を持っていて、マクロを書くことにあまり誇りを持っていない場合、言語を作成する簡単な方法は、一連のマクロを書くことです。このようにして、基礎となる言語のデータ型、式の構文、効率、およびランタイム ライブラリを利用しながら、独自のステートメントを作成できます。

于 2009-11-25T04:54:23.530 に答える