マンションの近くの自販機で、なんかもう見た感じ破滅してる飲み物を見つけた。
かなり終わってる味がするので俺はきっとこいつを口にすることは金輪際ないだろうが、それでも世の中にはこの味が堪らないという人がいるかもしれないので、そういう人とは一緒にご飯を食べに行きたくないなーと思ったりした。
全然話は変わるけど、誰か俺のお古のギター要らない? ずっと前に買った安物の SG がどうも馴染めなくて処分しようと思ってたんだけど、どうせなら「安物でもいいからギター欲しい」という人に譲ろうかと思ってね。え、 Jackson Stars の方をくれ? なに寝言いってんだ。
というわけでギター本体とソフトケースにピックをいくつかと、あと amPlug の Classic Rock と Metal のセット。廃物処理の一貫としての事なので、お代は一切いただきません。
ボディには結構傷が付いてる気がするけど、目立たないのでまあ気にするな。
フィンガーボードはローズウッドだけど、 Jackson の方と比べるとなんか大分みすぼらしい気がしなくもない。まあ安物だしな。
というか廉価ギターの代名詞である Photo Genic なんだからそこはいろいろ察してくれ。一応フォローしておくと、まったく使えないわけじゃないというか普通に弾けるよ。ただ俺にはいろいろ合わなかっただけの事で。
あと宅急便で送るとか俺には敷居が高すぎるので、現物を手渡しすることになるかと思います。そのため東京か千葉かその辺に住んでる人でないと多分無理です。というわけで、ボロギターをタダで手に入れるためにノコノコと俺に合いにきてやってもいいぜという奇特な方は、メールなり twitter なりで連絡をください(ちなみに早い者勝ちです)。とりあえず一週間ぐらい様子を見て、誰も名乗り出なかったら普通に処分します。
追記:チューナーとかストラップとかギタースタンドは自分で買ってください。
追記2:さっそく貰い手が現れたので締切り。
ANTLR を使う上で気をつけないといけないことの一つは、他のツール(ってか yacc/lex)と違って字句解析と構文解析のコードを同時に生成するということだ。俺はまず字句解析を作ってから構文解析を作るという頭でやっていたので、ちょっとハマった部分がある。
以下のコードは適当に書いた構文解析のサンプルからの抜粋で、いわゆる if 文に相当する部分にマッチしたら、 IF というタイプを設定するコードだ。
class FooLexer extends Lexer;
ACTION :
COMMENT { $skip; }
| "if"! (' '!)+ EXPR (' '!)* ':'! { $setType(IF) } // if $cond: などにマッチ
;
// $foo.bar[1] とかいうのにマッチする。
protected
EXPR : '$' ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')*
(
("[" ('0'..'9')+ "]")
| ("." ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')*)
) *
;
こいつを ANTLR にかけると FooLexer が作られるが、実際に使ってみるとエラーになる。そしてその理由は「IF が未定義」というもので、 ANTLR では <RULE>: で指定されたルールに対応した名前の定数を自動で定義するが、それ以外のものは antlr パッケージからインポートされるもの以外は一切定義しない(まあ当たり前か)。
ところがこれを次のように修正すると、これはこれで上手くいかない。
class FooLexer extends Lexer;
ACTION :
COMMENT { $skip; }
| IF { $setType(IF) } // if $cond: などにマッチ
;
// $foo.bar[1] とかいうのにマッチする。
protected
EXPR : '$' ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')*
(
("[" ('0'..'9')+ "]")
| ("." ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')*)
) *
;
IF : "if"! (' '!)+ EXPR (' '!)* ':'!
こうしてしまうと、 if $cond: にマッチしたときの getText メソッドの戻り値が "if $cond:" と文全体になってしまう。実際には IF タイプで $cond という値のトークンが必要なのであり、むしろ if 文全体が生の文字列のまま取れてきてしまうのは都合が悪い。
というわけで、以下のように構文解析部分で IF というトークンの宣言を行うことでこの問題を回避した。
class FooParser extends Parser;
tokenDefinitions:
IF
;
こうすれば、最初のコードを動かすと「IF タイプで $cond という値のトークン」が取れてくる。
まだ ANTLR に不慣れなので実はちゃんとしたやり方があるのかもしれないけど、とりあえず今はこの方法で凌ぐことにする。
この怪文書はクリエイティブ・コモンズ・ライセンスの元でライセンスされています。引用した文章など Kuwata Chikara に著作権のないものについては、それらの著作権保持者に帰属します。