プログラミング初心者が最初の個人プロジェクトとしてプログラミング言語を作ったことについて
この記事は、mast Advent Calendar 2020 の3日目の記事です。
2日目は紫葉さんの記事『believeの中にはlieが入っているという話を聞きました! - ふわり、と浮いています。』(好きなもの紹介)でした。
皆さんこんばんはこんにちは、mast21のShoreです。
今回の話題はタイトルの通り、プログラミング初心者が右も左もわからない状態からなぜかプログラミング言語を作ったので、作る間に何が起きたか、というのを書いていきます。
まず、前提として何をしたかを話しますと
- 去年は怖くて取らなかったけど、情報メディア特別演習という講義を今年は取ってやるぜ!
- テーマどうしようか…… よし、プログラミング言語の学習環境を作ろう!
- そのためには実行系と言語が必要だな!←?
- 作るか!←????
- プログラミング言語とC#でそのインタプリタを作った!←??????????
って感じです。今考えると頭がおかしいのではないか、と思わざるを得ない。
ちなみに作った実行系に関する話とか言語とかの話は今回はしません。今回は、4→5の間に起きた、ヒヨコだったころの私がやらかしたことについて赤裸々に話していこうかと思います。
では、始めます。
プログラミング言語そのものに対する知識不足
ここからはプログラミング言語というものに対する知識がなかったために起きた問題を書いていきます。
4~5月: 構文解析、字句解析?なにそれおいしいの?
でしょうね~~~~~~~~~!!!!!!!
まず最初の問題は圧倒的知識不足でした。
当時の私は、Pythonを用いた授業であるプログラミング入門ABの知識と夏休み中のその予習、そして冬休みにちょろっとC#を触った経験だけ!(一応C言語を触った経験はあったのですがほんの少し。)
そんな人間が構文解析器なんて作れるはずも……
いやこれが意外にうまく行っちゃったんですよ。たちが悪いことに。
当時の私はなんと1000行ほどのクラスに字句解析、および構文解析器を途中まで作成しました。たぶんあのまま言ってたらキメラのような構文解析器を完成させてましたね。
これと同じことが今後も続きます。すなわち「知識ないのに調べないで我流ですべてを完成させようとする」というムーブをかましまくります。
ですが、ま~問題だらけの方法を使ってまして。
- クラスを構造体のように使い、字句を値と分類のトークンに分けるなんてもちろん知識にないので、値と分類を合わせた一つの文字列型として保持する。
例:
入力→"hoge = \"fuga\""
出力→{"variable:hoge", "operator:=", "string:\"fuga\""} - 構文解析器において、文法の問題で行頭のみでは構文を決定できなかったのであるワードが行に含まれているかでどの文法か、を判断する。
- もちろん構文解析木なんて言葉は知らないので実行時にリストの値を再帰的に分割しながら実行する。
- 関数にほとんど分けてなかったのでmain関数1つの中で上をほぼしてる。
いや~、すごい。当時の教員と先輩の苦笑していた理由がわかる。すごい間違ってる。
6月: 汎用的な構文解析器を作れ? できらぁ!
「ちょっと」勉強しました。そして私はこんなことを言ってしまいます。
「ある程度ほかの言語実行系を作るときに流用できるやつを作りたい」と。
そして担当教員にも「やろう!」と言われました。
さ~てこう言われた私は考えます。そもそも文法の記法はどうしようか。どうしたらより楽に構文解析のための文法記法の構文解析を行えるだろうか、と。そして私は閃きます(閃くな)。
「そうだ、正規表現みたいに文法を記述することにすれば簡単に構文解析器を作れそうだぞ!」と。
作りました。完成させちゃいました。バックトラックもりもりの、却ってLL(1)構文解析器作るよりも面倒なものを作ってしまったのです。意気揚々とそれをもってMTに当時の私は向かいます。
「構文解析器をつくったよ~! 文法はこんな感じで書いたら文法を記述しているファイルを読み込んで構文解析木を生成してくれるよ~!」
「ちょっと話を聞かせてくれるかな。何してるの?」
ということでまたやらかしました。その名も「調べずに我流で書いてたら正規言語の構文解析もどきを作ってたぜ!」です。逆にすごいな……
その後
その後は(比較的)普通のLL(1)構文解析器を作って実行系を作って終わりました。めでたしめでたし。確か春Cが暇だったから1か月くらいで完成させたんだったか?
プログラミングの知識不足
ここからはプログラミング技術が乏しいためにやらかしたミスを赤裸々に思い出しながら綴っていきます。
1. 複数の情報を持つ値、うーん?
上で書いた通り、クラスや構造体は知識では知っているものの使い方を知らない状態でしたので……
2. static属性ってなんすか?
なんと、すべての関数を動的メソッドとして宣言していたので、毎回呼び出すたびにクラスを宣言してました。いや、なんかC#って面倒だな、とは思ってたんだよ。思っただけで調べなかったけど。
3. ネームスペース?なんかかっこいい!
ネームスペースをむやみやたらに分けまくってました!具体的には、MainとLexerとParserとExecuteとExecute.Functionと……って感じになってました。なんかnamespaceたくさんあるとかっこいいじゃん!
まとめ
まず、情報メディア特別演習は悪くないです。なんなら非常に良い機会なので皆さんやる気があるなら取りましょう。ぜひ。正直去年取らなかったのを後悔している。
今回はやらかし先生として記事を書いているわけですが、学びとしては「やりながら学ぶ、というのも結構だけどちゃんと勉強もしましょう」ですね。こんなことになった理由の一つに、毎週MTがあったので進捗を出さねば、という強迫観念を勝手に抱いていたことがあると思います。別に、○○を勉強しました、でもよかったのに。焦っていたのでしょう。
皆さんは私みたいにならず、一歩先くらいは見える状態から始めるとよいと思います。
最後に。
この記事を書いていくうちに自分の愚かさに気が付くとともに呆れずに指導してくれた担当教員にありがたい気持ちと申し訳ない気持ちに改めてなりました。SNSをやらない方なのでおそらく読んでいませんが感謝いたします。
以上