遂に、自作言語kaprinoが無事完成したのでその記念に、自作言語を実装するにあたって 使った物をこの記事で紹介したいと思います。実際に自作言語を作ろうと思っても 何から手を付けていいのか分からなくなってしまうことがあることは想像に難くないので、 その様な人への羅針盤のような記事になることを期待しています。
ただ、それぞれの使い方まで言及すると記事の量がどえらい事になるので、使い方はいずれ書こうと思います。

これから自作言語作る予定がある方は必見です!
もう既に自作言語を実装した経験がある方はお手柔らかにお願いします。

自作言語kaprinoのソースコードを管理しているrepositoryへのリンクと自作のオンラインコンパイラ(この話はまた別の記事で)です。もし良かったら見てみてください。
Github kaprino-lang
Kaprino Online Compiler

まず自作言語を何故作ろうと思ったのか 見出しへのリンク

なぜでしょうね。
自作言語を作る人がよく言うのは、使っている既存の言語に不満があって自分の好みにあった言語を作ってみたい、という感じでしょうが、 私が自作言語を作ろうと思った理由は、本当になんとなくです。自作言語という言葉の響きによるものだと言えるかもしれませんし、 単純に自分は気付いていないだけで言語に不満があったのかもしれません。
これは本題ではないのでこれくらいにしておきます。

言語を動かすまでを大雑把に把握 見出しへのリンク

さて本題に入りましょう。
これから言語を作るまでに使ったものを紹介してゆく訳ですが、そもそも私の自作言語kaprinoが どのように動いているか説明したいと思います。

まず、kaprinoは静的な型付けの言語で、実行前にコンパイルを必要とします。
コンパイル とはソースコードを機械語に変換することです。このコンパイルは通常、以下の様な作業を行います。

  1. Lexer (字句解析器) と呼ばれるものでソースコードを Token (小さい文字列)に分解
  2. Parser (構文解析器) と呼ばれるものでTokenを AST (抽象構文木)に変換
  3. ASTを低級言語(機械語やアセンブリ言語)に変換

ということはこの三つを行うプログラムを書くことが出来れば自作言語のコンパイラを手にする事ができます!

しかし、愚直にこれらを一から実装すると途轍もない時間がかかります。そこでライブラリを使って実装していくことになります。

以下、C++で書くことを前提として話を進めます
C#とかJavaとかRustとかでもいいんですがそれらは記事の対象外ということで

1. Lexerを実装する 見出しへのリンク

Lexerはこれから行う3つの事の中では最も簡単に実装ができます。自力実装もそこまで難しくないです。
しかし、今回のテーマはツール紹介ということなので自力でやりたいよ、という方は無視します。
頑張って下さい。応援しています。

LexerをC++で実装する時に使われる有名なツール(ライブラリ)として挙げられるのはこの三つです。

  • lex (伝統的)
  • flex (再構築されたlex)
  • Antlr4 (新勢力)

flexはlexと構文がほとんど同じなので、lexを使うくらいならより新しいflexを使ったほうがいいと思います。
flexとAntlr4について言えば、どちらを選んでも困ることは起こらないので、それぞれ検索してみて、サンプルコードにシンパシーを感じた方を使えばいいと思います。

個人的にはAntlr4で書いた方が読みやすいと思ったので、kaprinoにもAntlr4を使っています。

2. Parserを実装する 見出しへのリンク

ParserをC++で実装する時に使われる有名なツール(ライブラリ)として挙げられるのはこの三つです。

  • yacc (伝統的)
  • bison (再構築されたyacc)
  • Antlr4 (新勢力)

ぱっと見でわかると思いますがlexとyacc、flexとbisonはセットで使うもので、Antlr4はLexerとParserどちらの実装にも使えます。
別のパターンを組み合わせても出来ないことはないですが、デメリットしかないので大人しくLexerで選択したものと合うものを選びましょう。

3. ASTから低級言語に変換する 見出しへのリンク

これが一番の難所で、自力実装はとても厳しいものとなります。

ここで使うのが LLVM です。とても有名なので聞いたことがあるかもしれません。
LLVMはLLVM独自の中間表現であるLLVM IRというものから任意のプラットフォーム(WindowsとかMacintoshとかLinuxとか)への出力を担ってくれます。
有名な使用例を挙げると、C++のコンパイラの一つであるClangもこのLLVMを用いて作られています。

LLVMはコードの最適化を行う処理にとても強く、この分野で右に出るものはいません。
ただLLVMを使うのはそう簡単ではないので根気強い資料探しを求められます。

まとめ 見出しへのリンク

自作言語を作るまでにどういうものを使えばいいのか、この記事で大雑把なイメージがつかめたと思います。
使い方はこちらの都合でカットしましたが、これに関してはググって下さい。
「俺の好みのライブラリが紹介されてないぜ!」とか「誤字あるよ」とかはコメントにお願いします。