Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
雰囲気でコンパイラを書いたら大変だった話
Search
MiZUP
October 20, 2017
Programming
2
2.2k
雰囲気でコンパイラを書いたら大変だった話
2017年10月20日に発表した社内勉強会の資料です
MiZUP
October 20, 2017
Tweet
Share
More Decks by MiZUP
See All by MiZUP
RUBYでアッカーマン関数の計算をがんばる方法 / How to write ackermann function in ruby
mizukmb
0
1.4k
新卒がオンプレミスとクラウドコンピューティングを触って感じたこと
mizukmb
0
870
Other Decks in Programming
See All in Programming
英語文法から学ぶ、クリーンな設計の秘訣
newnomad
1
260
PHPによる"非"構造化プログラミング入門 -本当に熱いスパゲティコードを求めて- #phperkaigi
o0h
PRO
0
720
2025/3/18 サービスの成長で生じる幅広いパフォーマンスの問題を、 AIで手軽に解決する
shirahama_x
0
130
아직도 SOLID 를 '글'로만 알고 계신가요?
sh1mj1
0
340
The Evolution of Enterprise Java with Jakarta EE 11 and Beyond
ivargrimstad
0
290
読もう! Android build ドキュメント
andpad
1
190
イベントソーシングによってインピーダンスミスマッチから解放された話
tkawae
1
270
AtCoder Heuristic First-step Vol.1 講義スライド
terryu16
2
700
RCPと宣言型ポリシーについてのお話し
kokitamura
2
130
Return of the Full-Stack Developer
simas
PRO
1
300
AI Agentを利用したAndroid開発について
yuchan2215
0
190
Cloudflare Pagesのサイトを NotebookLMから読みやすくする Cloudflare Meet-up Tokyo Vol.7
xiombatsg
0
110
Featured
See All Featured
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Designing for humans not robots
tammielis
250
25k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Typedesign – Prime Four
hannesfritz
41
2.6k
Automating Front-end Workflow
addyosmani
1369
200k
The Cult of Friendly URLs
andyhume
78
6.3k
Thoughts on Productivity
jonyablonski
69
4.5k
Designing Experiences People Love
moore
140
23k
Why You Should Never Use an ORM
jnunemaker
PRO
55
9.3k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
30
2.3k
Product Roadmaps are Hard
iamctodd
PRO
52
11k
RailsConf 2023
tenderlove
29
1k
Transcript
雰囲気でコンパイラを書いたら 大変だった話 @mizukmb 20, October
コンパイラとは ある規則に沿って書かれた文字列を機械可読可能なコードに翻訳すること var foo = 100; ~~~~~~ ソースコード コンパイル オブジェクト
コード
モチベーション - コンパイラ書いたことがない - コンピュータサイエンスをあまり勉強したことがない - プログラマとして、やっておくべきか… - 枯れた技術の習得 -
この辺の記事を読んで影響を受けている - [二週間で簡単なインタープリタ言語を実装してみた (日記) - プログラムモグモ グ](http://itchyny.hatenablog.com/entry/2017/01/23/100000) - [Cコンパイラをスクラッチから開発してみた(日記) - Qiita](https://qiita.com/ruiu/items/4d471216b71ab48d8b74)
コンパイラの動き
コンパイラの動き 原始プロ グラム 読み込み 字句解析 構文解析 中間語作 成 最適化 コード生成
目的プロ グラム
今回実装した部分 原始プロ グラム 読み込み 字句解析 構文解析 中間語作 成 最適化 コード生成
目的プロ グラム
今回実装した部分 原始プロ グラム 読み込み 字句解析 構文解析 中間語作 成 最適化 コード生成
目的プロ グラム 中間語から Ruby コードを呼び出して直接実行
成果物 mizukmb/my-compiler mizukmb/train-make-ruby-by-ruby - 読み込み〜字句解析〜構文解析〜中間語生成 まで - ↑中間語から Ruby コードを発行し、実行する
- 書籍 『RubyでつくるRuby ゼロから学びなおすプログラミ ング言語入門』 の写経
各処理の詳細
字句解析 規則に沿って並んだ文字や数字の列を意味のある単位に分解していく 空白・インデント・改行などはいい感じに削除する(意味を持たないので) `x = 1 + 10` x …
変数 = … 演算子 1 … 数値リテラル + … 演算子 10 … 数値リテラル
字句解析 - How? 決められた規則を定義する → 決定性有限オートマトンで表現 q2 q0 q1 ‘
英数字 ‘
字句解析 - How? 決められた規則を定義する → 決定性有限オートマトンで表現 →正規表現で書ける `/\A\w*\z/` q2 q0
q1 ‘ 英数字 ‘
字句解析 - How? 種類が定まったらラベルを付けたペアとしてトークンにする ‘foo’ -> (字句解析) -> [‘lit’, ‘foo’]
構文解析 字句解析したトークン列を構文木に変換する [ [ ‘lit’, 1 ], [ ‘op_plus, ‘+’
], [ ‘lit’, 2 ] ] ‘+’ 2 1
構文解析 - How? 解析手法はいっぱいある - 再帰的下向き構文解析 - 上向き構文解析 - LR
構文解析
構文解析 - How? 解析手法はいっぱいある - 再帰的下向き構文解析 ←今回はこれを採用 - 上向き構文解析 -
LR 構文解析
再帰的下向き構文解析 - 解析木を上(根)から下向き(葉に向かって)に作り上げていく - 比較的わかりやすいプログラムが書ける - バックトラック、左再帰性といった問題がある + * 5
[ [ ‘lit’, 5 ], [ ‘op_multi, ‘+’ ], [ ‘lit’, 10 ], [ ‘op_multi’, ‘*’ ], ... ]
再帰的下向き構文解析 - 左再帰性 文法を表現する際、即座に自分自身を呼び出して、無限再帰に陥る問題 ``` E -> E + T
E() { E(); // <- 無限再帰が発生 ‘+’; T(); } ```
再帰的下向き構文解析 - 左再帰性 - 解決策 自分自身を後で読み込むように書き換えれば良い ``` E -> TE’
E’ -> +TE’ | ε T -> i (任意の数列) ```
再帰的下向き構文解析 - バックトラック `A -> α | β` のような「または」という規則があるとき、どちらで解析すればよいか 判断できず、解析に失敗して後戻りが発生してしまうこと。
→解析効率が悪い
再帰的下向き構文解析 - バックトラック - 解決策 解析するトークンのk個先のトークンを先読みして、文法の曖昧さを除去してい く → LL (k)
文法の変換
LL (1) 文法 1個先のトークンを先読みして文法が一意に定まるようになる - First 集合 … 先頭に現れる終端記号の集合 -
Follow 集合 … ある非終端記号の直後に現れる終端記号の集合 - Director 集合 … ある非終端記号を特定の終端記号に展開してよいか判 断できる終端記号の集合 - First 集合と Follow 集合から求まる LL (1) かは全ての Director 集合の積集合が空集合であれば良い
中間語〜コード実行 構文解析済みの中間語を上から順番に実行するだけ 詳しくは書籍『RubyでつくるRuby ゼロから学びなおすプログラミング言語入門 』
製作日記
製作日記 期間: 9月24日〜10月19日
9月24日〜10月10日 様々な誘惑[^1] に負けつつも、書籍『RubyでつくるRuby ゼロから学びなおす プログラミング言語入門』のコードを写経し続ける mizukmb/train-make-ruby-by-ruby [^1]: Splatoon 2, beatmania
IIDX
10月11日 コンパイラを作り始める とりあえず数値リテラルを字句解析できるようにした mizukmb/my-compiler
10月12日 インデントやスペースを使いたかったので大丈夫なように実装 全角スペースも使える。便利ではないと思う mizukmb/my-compiler
10月14日 四則演算ができるように、 + - * / % 演算子を字句解析できるようにした ``` ”1
+ 2" => [[“lit", 1], ["operator_plus", "+"], ["lit", 2]] ``` mizukmb/my-compiler
10月15日 最低限の計算はできるようになったので、数値リテラルと四則演算の構文解析 を実装。四則演算のできる小さなプログラミング言語の完成 ``` ”1 + 2" (字句解析) => [[“lit",
1], ["operator_plus", "+"], ["lit", 2]] (構文解析) => ["+", ["lit", 1], ["lit", 2]] ``` mizukmb/my-compiler
10月16日 数値リテラルと演算子の間にスペースが無くても字句解析できるようにバグ修 正 ``` - 1 + 2 # =>
[["lit", 1], ["operator_plus", "+"], ["lit", 2]] - 1+2 # => [["lit", 1], ["operator_plus", "+"], ["lit", 2]] ``` mizukmb/my-compiler
10月17日 比較演算子 < <= == >= > != の実装 四則演算のときと実装はあまり変わらず。順序だけ気にしていればおk
発表までに FizzBuzz できそう…みたいな叶わぬ夢を見だす mizukmb/my-compiler
10月18日 複文を実装する。字句解析で改行(\n)もトークンとして扱うようにして複文を解 析できるようにした。 ``` “1 + 2\n3 - 4” (字句解析)
=> [[“lit", 1], ["operator_plus", "+"], ["lit", 2], ["newline", "\\n"], ["lit", 3], ["operator_minus", "-"], ["lit", 4]] (構文解析) => [“stmts", ["+", ["lit", 1], ["lit", 2]], ["-", ["lit", 3], ["lit", 4]]] ``` mizukmb/my-compiler
10月18日 - 続き 複文の実装を泥臭くやりすぎて、新しい文の追加や、リファクタリングがやりづ らくなった LL (1) ではない気がする… mizukmb/my-compiler
10月18日 - 続き if 文を実装する。が、前述の通り、複文が動かなくなったり、トークンの読み込 みがおかしくなってすごい悩んだ ``` if (10 >
9 ) { 5 * 100 } ``` mizukmb/my-compiler
10月19日 else を実装しようと試みるが、複文の(ry 実装を断念した。 文字列リテラルを忘れていたので実装 mizukmb/my-compiler
最終成果
最終成果 実装した - 数値、文字列リテラル - 四則演算、比較演算子 - if 文 -
複数式の評価
実演
感想 0からコンパイラ作るのは難しい。けど、オリジナルのプログラミング言語が 様々なプロセスを経て実行されると嬉しい。 一気に実装するのではなく、小さなパーツから少しづつ組み立てていくインクリ メンタルな開発は良かった。コンパイラが少しずつ言葉を覚えて育っていく様子 が見られるのは楽しい
感想(つらい) 理論を十分理解しないまま実装したので途中からコードの設計に無理が出てき た プログラミング言語として実用的ではない。せめて変数は欲しかった
None