最近のこと。

これは生きたログだから,最近のことをかき殴ろうというわけだ。
● プログラム紀
始まる。
久しぶりに,プログラムを趣味でカタカタやる。
もっぱら
● flex & bison in C++
というやつだ。
flexとbisonを使って,簡単すぎるインタプリタぐらいまでは作れそうな感じに。
bison -> flex へのヘッダファイル提供。
実際には,bisonで言語ルールまで書いて%tokenや%typeで宣言した部分を,
後に flex で#includeして使うということのよう。
これには,
● これに

めっぽうお世話になりました。
動物の柄のこの本,学生時代から憧れの象徴。
実際には,2年前ぐらいか。秋ぐらいから寝床で読んでは
単語がわからずiphoneとかで調べる。
- precedence:優先順位(計算機演算ではpriorityて言わないのかな)
- arbitrary:任意の
- adequate:十分な
- punctuation:句読点(句読法か)
- glue to:接着する
- simultaneously:同時に
- albeit:〜であるが。
(p12. “This is a hack, albeit a very useful one, since most of the time it does the right thing.”)
いくつかは入試レベルな気もし。
albeitって,そういう意味で使うんだ。など。
● 下記は,去年の夏に書いてボツにしたブログから
−−−−−−
● 学生のとき(1994〜2000年ぐらい)
大学の授業でBNF記法というのを学んだわけだが、まあ
→ 学べてなかった
単位はもらえたんだっけ。という。
bisonでは、言語仕様をBNF風に書かねばならなかったはず。
● 戸塚時代(2002年〜2007年ぐらい)
よーしいっちょう、flexでも勉強して、新種のプログラミング言語でも発明してやりますかぁ〜
と意気込み、再三挫折。
ギリflexまでは分かる。
けどbisonで何度やってもどうやっても僕の書いたBNFの言語仕様が
● ambiguous grammar
ていうエラーになる。
訳すと「曖昧な文法」。何が曖昧じゃい。曖昧な日本の私のプログラム言語の仕様。
僕にはもう、bisonを使う才能とか、生きている価値とか、死なない権利とか、笑う勇気とか、
● 何にもないに違いない
と咆哮したり呻いたりして畳の目に逆らって爪を立てたり、足の裏で敷居をゴシゴシしたりしては、とにかく、諦めていた訳だ。
−−−−−−
● という
存外に元気な感じでやってたわけだ。
やがて分かりかける。
● 飯も自炊し



再び去年の盆に書いてボツにしたブログから引用する。
−−−−−−
● で
何に感動したかというと、この『flex&bison』の「計算式を入力すると、加減乗除を優先順位を守って計算する」という
サンプルプログラムをつくる中での p.14 だ。
またしばらくすると、仕事で頭が一杯になって、何を理解したのか忘れると思うので、備忘録として残す。
Ambiguous Grammars: Not Quite
The reader may be wondering at this point whether the grammar in Example 1-5 is needlessly complicated. Why not just write this?
(読者はExample 1-5が不必要に複雑だと思っているかも知れない。こう書いてはだめかと。)
exp: exp ADD exp
| exp SUB exp
| exp MUL exp
| exp DIV exp
| ABS exp
| NUMBER
そうそう、まさにそう。↑みたく書いちゃなんでダメなんだって十年来わからなかった。
この辺、わくわくしながら読んだ。
ちなみに「Example 1-5」というのは、bisonへ渡す言語仕様を書いたもので p.11 にはこうある。
Bison’s Rule Input Language
Bison rules are basically BNF, with the punctuation simplified a little to make them easier to type. Example 1-5 shows the bison code, including the BNF, for the first version of our calculator.
(bisonに渡すコードは基本的にBNFだが、容易に書けるよう記法を少し簡単にしている。Example 1-5 に計算機の一番最初のバージョンのためのbison用のコード(BNFを含む)を示す。)
Example 1-5 Simple calculator fb1-5.y
<前略>
calclist: /* nothing */
| calclist exp EOL { printf("= %d\n", $1); }
;
exp: factor
| exp ADD factor { && = $1 + $3; }
| exp SUB factor { && = $1 - $3; }
;
factor: term
| factor MUL term { $$ = $1 * $3; }
| factor DIV term { $$ = $1 / $3; }
;
term: NUMBER
| ABS term { $$ = $2 >= 0? $2 : -$2; }
;
<後略>
そうコレなのだ。僕が戸塚時代にメロメロになったやつ。
よく入門書なんかに書いてあるやつだ。
何でこんなに分けて、わざわざ複雑に書かねばならんのだと。謎だった。
p.14でLevine先生が言う「The reader wondering at the point」こそ僕だ。
そしたらそのp.14にはこう続く。
There are two answers: precedence and ambiguity. The separate symbols for term, factor, and exp tell bison to handle ABS, then MUL and DIV, and then ADD and SUB.
(答えは2つある。優先順位と曖昧さだ。termとfactorとexpを分けて書くことで、bisonにまずABSを、その次にMULとDIVを、そしてその次にADDとSUBを処理するよう指示している。)
興奮して音読していた。
そういうことだったんだ。今までこの世のどこにもなかった答えが初めて身に染み入る。ッアー!
−−−−−−
● 何やら
感動している。
スピッツのメドレーをyoutubeで流しながら,暑い日,来る日も来る日も
● 新築の
家の中で猫と僕だけ住んでる状況。
その中で,ずっとプログラム三昧。何度かラム肉食って赤ワイン飲みまくって吐く。
● 分かったことは
C++でflex, bisonを利用することは可能ということと,
ヘッダファイルで
#undef YY_DECL
#define YY_DECL \
yy::Parser::token_type \
Scanner::scan(yy::Parser::semantic_type* yylval, \
yy::Parser::location_type* yylloc, \
ParseDriver& driver)
とかやったり,かなりトリッキーだということと。
Parser.y内で,
%{
#include "ParseDriver.hpp"
//yylex()のオーバーロード
yy::Parser::token_type
yylex(
yy::Parser::semantic_type* yylval,
yy::Parser::location_type* yylloc,
ParseDriver& driver) {
return driver.scanner->scan(yylval, yylloc, driver);
}
// parser's error routine <- it's need to be implemented by us
void
yy::Parser::error(
const yy::Parser::location_type& l,
const std::string& m) {
driver.error(l, m);
}
%}
なんていう,なかなか香ばしいことを書く必要。
● なんか
もともと flex, bison が広域変数使いまくったり,
#ifndefや#defineつかって,凄いことになってたりする中,
● flex, bison in C++も
C++のクラスを使う上で,かなり凄いことになってる。ということのよう。
勉強したのは下記。
やっと,コンパイルフリーなBison/Flexのtinyセットを作成できた。
コレを元に,ASTつくって逐次実行するサンプルができたら,
● やっと
1年以上ぶりにyoutubeのサイトを更新できそうだ。
今日はプログラム紀について。
● 次回は音楽編
そんで次は,最近の人生観について。
順次追記していく。