web-dev-qa-db-ja.com

単純な(おそらく最も単純な)Cコンパイラから始めますか?

私はこれに遭遇しました: Turbo Pascalを使用してコンパイラを作成する

簡単なCコンパイラの作成方法を説明するチュートリアルやリファレンスがあるかどうか知りたいです。つまり、算術演算を理解させるレベルに達していれば十分です。 Ken Thompson によるこの記事を読んだ後、私は本当に興味を持ちました。自分自身を理解する何かを書くというアイデアは刺激的です。

Googleに質問する代わりに、なぜこの質問をしたのですか?私はグーグルを試しました、そして、パスカルのものは最初のリンクでした。残りは関連していないようで、それに追加されました...私はCS専攻ではありません(そのため、yaccのようなすべてのツールで何ができるかを学ぶ必要があります)。これらよりも常にGoogleよりも優れています。上記の記事と同じ精神で書かれた記事を読みたいのですが、それは少なくとも単純なCコンパイラーの構築のブートストラップ段階を強調しています。

また、私は学ぶための最良の方法を知りません。 Cまたはその他の言語でCコンパイラを作成することから始めますか? Cコンパイラや他の言語を記述しますか?探求する方向性があれば、このような質問にはより適切に答えられると思います。助言がありますか?

助言がありますか?

40
Legend

コンパイラは3つの部分で構成されています。

  1. パーサー
  2. 抽象構文木(AST)
  3. コードジェネレーター

言語文法で始まる素敵なパーサージェネレータがたくさんあります。たぶんANTLRはあなたが始めるのに良い場所でしょう。 Cルーツに固執したい場合は、Lex/yaccまたはbisonを試してください。

Cには文法がありますが、Cは全体的に複雑だと思います。言語のサブセットから始めて、上手くいくとうまくいきます。

ASTを取得したら、それを使用して、実行するマシンコードを生成します。

実行可能ですが、簡単ではありません。

Amazonでコンパイラーの作成に関する本もチェックします。ドラゴンブックは古典的ですが、より現代的なものが利用可能です。

更新: これ のようなスタックオーバーフローに関して同様の質問がありました。これらのリソースも確認してください。

24
duffymo

このチュートリアルをお勧めします:

「小さな言語」コンパイラを実装する方法の小さな例です。ソースコードは非常に小さく、段階的に説明されています。

LLVM(プログラムの内部構造を表す低レベル仮想マシン)ライブラリ用のCフロントエンドライブラリもあります。

24
Phong

価値があるのは、 Tiny Cコンパイラ は、比較的小さなソースパッケージのかなりフル機能のCコンパイラです。たとえば、GCCのすべてのソースベースを理解しようとするよりも、はるかに理解しやすいので、そのソースを研究することにはメリットがあるかもしれません。

15
Mark Rushakoff

これは私の見解(そして推測)であり、学部生(中等後)のコンピュータサイエンスのクラスで通常カバーされるデータ構造を理解しないと、コンパイラを書くのは難しいでしょう。これができないという意味ではありませんが、リンクされたリストやツリーなどの重要なデータ構造を知っておく必要があります。

完全または標準に準拠したC言語コンパイラを(少なくとも最初は)作成するのではなく、一般的な演算子、整数のみのサポート、基本的な関数とポインタなど、言語の基本的なサブセットに制限することをお勧めします。この典型的な例の1つは、ロンケインの Small-C で、1980年代に Dr。Dobbs Journal で書かれた一連の記事で人気を博しました。彼らは [〜#〜] cd [〜#〜] をJames Hendrixの絶版本 A Small-C Compiler とともに発行しています。

私が提案するのは、クレンショウのチュートリアルに従うことですが、Cライクな言語コンパイラ、およびターゲットにしたいCPUターゲット(クレンショウはMotorola 68000 CPUをターゲットにする)向けに記述します。これを行うには、コンパイルされたプログラムを実行するターゲットの基本的なアセンブリを知っている必要があります。これには、68000のエミュレーター、またはMIPS(間違いなくnicerアセンブリー命令セット)がIntel x86(16/32ビット)の由緒あるCISC命令セットよりも含まれる可能性があります。

コンパイラー/トランスレーター理論(および実践)を学ぶための出発点として使用できる多くの潜在的な本があります。 comp.compilers FAQ を読み、さまざまなオンライン書店でレビューします。ほとんどの入門書は、2年生から上級レベルの学部のコンピュータサイエンスクラスの教科書として書かれているため、CSのバックグラウンドがないと読書が遅くなる可能性があります。より紹介的であるかもしれないが、より読みやすい古い本1冊 " The Dragon Book "コンパイラ構築入門by Thomas Parsons。古いので、選択したオンライン書店から中古のコピーをリーズナブルな価格で見つけることができるはずです。

だから私は、Jack Crenshawの Let's Build a Compiler チュートリアルから始めて、彼の例をガイドとして独自に記述し、simpleコンパイラ。その作業が完了したら、その時点からどこに移動するかをより適切に決定できます。

追加:

ブートストラップ処理に関して。自由に利用できる既存のCコンパイラがあるので、ブートストラップについて心配する必要はありません。個別の既存のツール(GCC、Visual C++ Express、Mingw/djgpp、tcc)を使用してコンパイラーを作成すると、ずっと後の段階でプロジェクトを自己コンパイルすることを心配できます。ケントーマスのACMチューリング賞のスピーチ Reflections on Trusting Trust を読んで、独自のコンパイラを作成するというアイデアに導かれるまで、この質問の部分に驚きましたコンパイラのブートストラッププロセス。これは、モデレートされた高度なトピックであり、単純に非常に面倒です。 Cコンパイラーを含む古いUnixシステム(64ビットAlphaのデジタルOSF/1)でGCC Cコンパイラーをブートストラップしても、遅くて時間がかかり、エラーが発生しやすいプロセスです。

もう1つの種類の質問は、Yaccのようなコンパイラツールが実際に何をするかでした。 Yacc(Yet Another Compiler CompilerまたはBison from GNU)は、コンパイラー(またはトランスレーター)パーサーの作成を容易にするために設計されたツールです。 yaccに入力したターゲット言語の正式な文法に基づいて、parserを生成します。これは、コンパイラの全体的な設計。次はLex(またはGNUのflex)で、レキシカルアナライザーまたはスキャナーを生成するために使用されます。これは、フロントのスケルトンを形成するためにyacc生成パーサーと組み合わせて使用​​されることがよくあります。コンパイラの終わり。これらのツールを使用すると、字句アナライザーとパーサーを自分で作成するよりも、間違いなくライターをフロントエンドにすることができます。 Crenshawのチュートリアルではこれらのツールを使用していません。また、その必要もありません。多くのコンパイラ作成者が常に使用するわけではありません。もちろん、Crenshawはチュートリアルのパーサーが非常に基本的であることを認めています。

Crenshawのチュートリアルは、AST(抽象構文ツリー)の生成もスキップします。これにより、チュートリアルコンパイラーが簡略化されますが、制限もされます。最適化はすべてではないにしてもほとんど欠けており、特定のプログラミング言語とコンパイラの「バックエンド」によって生成された特定のアセンブリ言語。通常ASTは、最適化を実行できる中間部分であり、コンパイラのフロントエンドとデザインのバックエンド。コンピュータサイエンスの背景がない初心者の場合は、ASTを最初のコンパイラ(または少なくとも最初のバージョン)にしないことを心配する必要はありません。私はそれを小さくシンプルに保つことで、最初のバージョンでコンパイラを書き終えるのに役立ち、そこからどのように進めたいかをそこから決めることができると思います。

12
mctylr

あなたは本/コースに興味があるかもしれませんコンピューティングシステムの要素:第一原理から現代のコンピューターを構築する

これは、neweggから購入したものから「PC」を構築することではないことに注意してください。ブール論理の基礎の説明から始まり、最低レベルの抽象化から段階的に高いレベルの抽象化まで仮想コンピューターを構築します。コース資料はすべてオンラインで提供されており、本自体はAmazonからかなり安価です。

コースでは、「ハードウェアの構築」に加えて、アセンブラ、仮想マシン、コンパイラ、および基本的なOSを段階的に実装します。これは、他の回答にリストされている一般的に推奨されるリソースのいくつかを使用して、主題領域をさらに深く掘り下げるための十分な背景を提供すると思います。

6
Joe Internet

単純なCコンパイラを[書き始める]にはどうすればよいですか?

Cをコンパイルするのは簡単なことではありません。最高のシンプルなCコンパイラは、Chris FraserとDavid Hansonによる lcc です。彼らは10年を費やして設計を可能な限りシンプルにするために設計に取り組みながら、それでも適度に優れたコードを生成しました。大学図書館にアクセスできる場合は、その本を入手できるはずです。

Cまたはその他の言語でCコンパイラを作成することから始めますか?

他の言語。ハンソン氏とフレーザー氏がlccプロジェクトに10年間費やしたことで学んだ教訓を、ハンソンに聞いたことがあります。ハンソンが言った主なことは

Cは、コンパイラーを作成するためのひどい言語です。

HaskellやMLの方言を使用したほうがよいでしょう。どちらの言語も代数的データ型に対して関数を提供します。これは、コンパイラー作成者が直面する問題に完全に適合しています。それでもCを追求したい場合は、George Neculaの [〜#〜] cil [〜#〜] から始めることができます。これは、MLで書かれたCコンパイラの大きなチャンクです。

上記の記事と同じ趣旨で書かれている記事を読みたいのですが、少なくともブートストラップ段階を強調している...

ケンのような他の記事は見つかりません。しかし、Andrew Appelが Axiomatic Bootstrapping:A Guide for Compiler Hackers と呼ばれる素晴らしい記事を書きました/私は無料版を見つけることができませんでしたが、多くの人がACMデジタルライブラリにアクセスできます。

助言がありますか?

コンパイラーを作成する場合は、

  • 実装言語としてHaskellまたはMLを使用します。

  • 最初のコンパイラーとして、 Oberon のような非常に単純な言語、またはNiklaus Wirthの本Algorithms + Data Structures = ProgramsのP0のような言語を選択します。 Wirthは、コンパイルしやすい言語を設計することで有名です。

secondコンパイラ用のCコンパイラを記述できます。

5
Norman Ramsey

nixプログラミング環境 では、KernighanとPikeは、計算機をCベースの字句解析と即時実行からyacc/Lex解析と抽象マシンのコード生成まで機能させる5回の反復を実行します。彼らはとても素敵に書いているので、私はスムーズな紹介を提案することはできません。それは確かにCよりも小さいですが、それはあなたの利点になりそうです。

5
msw

コンパイラは、以下の側面をカバーする複雑な主題です

  • 字句解析、解析を含む入力処理
  • 抽象構文ツリー(AST)などの使用されるすべての変数のシンボルストアの構築
  • ASTツリーから、構文に基づいてマシンコードバイナリを転置および構築します

これは山の頂上からの抽象的な鳥瞰図であるため、決して網羅的ではありません。つまり、構文表記を正しく取得し、不正な形式の入力がそれをスローしないようにすることになります。実際、優れた入力処理が落ちることはありません。どんな形のひどい、ひどい、虐待された入力の場合でも、ひざまずいて投げられます。また、出力がどのようになるかを判断して把握する際にも、それはマシンコード内にあります。これは、変数のメモリアドレス指定など、プロセッサの命令を詳しく知る必要があることを意味します。

ここにあなたが始めるためのいくつかのリンクがあります:

  • Jack CrenshawのCのコードの port がありました...(数か月前にダウンロードしたことを覚えています...)
  • これは、同様の質問へのリンクです here on SO。
  • また、Basicからx86へのアセンブラコンパイラ用の別の小さな コンパイラチュートリアル もあります。
  • Tiny Cコンパイラ
  • HendrixのSmall Cコンパイラが here を見つけました。
5
t0mm13b

自分でコンパイルするコンパイラの書き方を教えてくれる驚くべき体験が必要な場合は、1964からこのペーパーを読む必要があります。

META II、構文指向のコンパイラ記述言語 Val Schorre著。

10ページで、コンパイラの記述方法、メタコンパイラの記述方法、仮想メタコンパイラの命令セット、およびメタコンパイラで構築されたサンプルコンパイラについて説明しています。

この論文から60年代後半にコンパイラの書き方を学び、そのアイデアを使用して、いくつかのミニコンピュータとマイクロプロセッサ用のCのような言語を構築しました。

紙だけでは多すぎる(そうではありません!) オンラインチュートリアル があり、全体を説明します。

また、ACMメンバーではないために元のリンクから論文を取得するのが面倒な場合は、チュートリアルにすべての詳細が含まれていることがわかります。 (私見、価格のため、紙自体はそれだけの価値があります)。

10ページ!

3
Ira Baxter

コンパイラーは非常に大きなプロジェクトですが、試しても害はないと思います。

Pascalで書かれた少なくとも1つのCコンパイラを知っているので、それはあなたができるmostめちゃくちゃなことではありません。私は個人的に、Cコンパイラプロジェクトを実装するためのより近代的な言語を選択しました。どちらも単純さのためです(Python、Ruby、C、C++またはJava)と、履歴書で見栄えがよくなるからです。

ただし、コンパイラーを初心者プロジェクトとして実行するには、Agile kool-aid

何も実行しない場合でも、常に何かを実行している。ほんの少しのステップでコンパイラに物事を追加します。 (「頻繁なリリース」。)言語の悪質な小さなサブセットを選択し、それを最初に実装します。 (サポートのみi = 0;最初に、そこから物事を展開します。)

3
DigitalRoss

関数型プログラミングについても学ぶ価値があります。関数型言語は、コンパイラーinforの両方を書くのに適しています。私の学校のイントロコンパイラクラスには関数型言語のイントロがあり、割り当てはすべてOCamlで行われていました。

ほんの数日前にラムダ計算のインタプリタを書いたので、今日はおかしいでしょう。ラムダ計算はすべての関数型言語の祖父です。長さは200行(C++では、エラー報告、きれいな印刷、Unicodeを含む)であり、コードの生成に使用できる中間形式の2フェーズ構造です。

小規模から始めて、コンパイラーへの最も実用的なアプローチを構築するだけでなく、優れたモジュール化された組織的な実践も促進します。

3
Potatoswatter

実装する言語としてCから始めたり、コンパイラージェネレーターやパーサージェネレーターツールから始めることはお勧めしません。 Cは非常に扱いにくい言語であり、独自の言語を作成することをお勧めします。少しCに似ている可能性があります(たとえば、関数の本体を示したい場合はカーリーバックセットを使用し、同じ型名を使用するので、何と呼ばれたかを覚えておく必要はありません)。

コンパイラーとパーサーを作成するためのツールは素晴らしいですが、本当に省略表記であるという問題があります。ロングハンドでコンパイラーを作成する方法がわからない場合、ショートハンドは不可解で不必要に制限されているように見えます。したがって、最初に独自の単純なコンパイラーを作成してから、そこから続行してください。また、アセンブラーを食べて呼吸しない限り、実際のマシンコードの生成を開始しないことをお勧めします。 VMを使用して独自のバイトコードインタープリターを作成します。

最初のコンパイラを作成するために使用する言語について:言語がかなり完全である限り、それは本当に問題ではありません。入力テキストを読み取り、そこからデータ構造を構築し、バイナリデータを書き出します。したがって、言語がこれらのことを何らかの方法で容易にする場合、それはそれを支持するポイントです。よく知っている言語を選択してください。そうすれば、言語の学習ではなく、コンパイラの作成に集中できます。私は通常、OO言語を使用します。これにより、構文ツリーをより簡単に記述できます。関数言語も、それに慣れていれば機能するでしょう。

私はプログラミング言語についてたくさんブログを書いてきたので、ここでいくつかの有用な投稿を見つけるかもしれません: http://orangejuiceliberationfront.com/category/language-design/

特に、 http://orangejuiceliberationfront.com/how-to-write-a-compiler/ は、一般的な構文を解析し、そこから有用なものを生成する詳細と、- http://orangejuiceliberationfront.com/generating-machine-code-at-runtime/ これは、何かを実行するIntelの命令を実際に吐き出すことについて述べています。

ああ、コンパイラのブートストラップに関して:最初からそれを行うことはおそらくできないでしょう。コンパイラーの作成にはかなりの作業が伴います。したがって、ブートストラップコンパイラを作成するだけでなく、コンパイラを(他の言語で)作成する必要があり、それを入手したら、それ自体を使用してコンパイラの2番目のバージョンを作成する必要があります。これは作業の2倍です。さらに、すべてが機能するまで、既存のコンパイラとブートストラップされた新しいコンパイラで必要なデバッグを行います。とは言っても、動作するコンパイラーがあれば、その完全性をテストするのに良い方法です。 OK、たぶん2倍の作業ではなく、もっと多くの作業が必要です。私はまず簡単な成功のために行き、それからそこから先に進みます。

とにかく楽しみましょう!

2
uliwitness