フラペチーノを飲みに行こう
「スタバに行こう」
荷物をリュックサックに詰めていたエイリは怪訝な顔でレミを見上げた。
「なぜ?」
「新作が出たから。ツリートップ・ベリーフラペチーノ。ホイップクリームの天辺に星型のクッキーが乗ってる。しかも、ストロベリーとクランベリーの果肉入り」
「まあ、美味しそうだけれども」
エイリは頭の片隅で今月のお小遣いの残額を計算しはじめた。今日スタバに行くのであれば、来週買う予定だった技術書は来月まで我慢しなければならない。
「僕は、スタバはちょっと苦手かもしれない。注文の仕方とか難しいし」
「キャラメルマキアート、トール、ホット、エクストラキャラメルソース、エクストラホイップとか?」
「うん、そういうの」
「ダークモカチップフラペチーノ、グランデ、エクストラチョコチップ、エクストラチョコソース、エスプレッソワンショット追加とか?」
「いや、わからないが」
「意外とちゃんとルールはあるんだけどな」
「そうなの?」
「基本的な要素としては<ドリンク>、<サイズ>、<温度>、<カスタマイズ>があってそれを組み合わせる感じ」
「うーん、文脈自由言語か?」
レミは首を傾げた。
「わからない」
「とりあえず、文脈自由言語だとして構文をBNFで考えてみよう」
エイリは手元のルーズリーフにさらさらと書き出した。
<注文> ::= <ドリンク> <サイズ> <温度> <カスタマイズ>
「何これ?」
「バッカス・ナウア記法または単にBNF。いま僕たちはスタバの注文を表現する言語のことを知りたいわけだ。 BNFはその注文言語を記述するための記法のことだと思えばいい。今ここには『<注文>は<ドリンク>、<サイズ>、<温度>、<カスタマイズ>を並べたものである』と書いてある」
「ふうん」
「さらに詳しくしていこう」
<注文> ::= <ドリンク> <サイズ> <温度> <カスタマイズ>
<サイズ> ::= "S" | "M" | "L"
エイリがそこまで書いたところでレミが指摘する。
「違う」
「え?」
「<サイズ>は"S" | "M" | "L"じゃない。 "ショート" | "トール" | "グランデ" | "ベンティ"が正しい」
「ベンティ?」
「そう、Venti」
「じゃあ、こう?」
<注文> ::= <ドリンク> <サイズ> <温度> <カスタマイズ>
<サイズ> ::= "ショート" | "トール" | "グランデ" | "ベンティ"
レミは頷いた。
「そう」
「温度は? ホットかアイスでいいの?」
「うん」
<注文> ::= <ドリンク> <サイズ> <温度> <カスタマイズ>
<サイズ> ::= "ショート" | "トール" | "グランデ" | "ベンティ"
<温度> ::= "ホット" | "アイス"
「カスタマイズは難しそうだな。というか、カスタマイズって1個じゃないよね?」
「そうだね。複数かもしれないし、ないかもしれない」
「じゃあ0個以上ってことか」
<注文> ::= <ドリンク> <サイズ> <温度> { <カスタマイズ> }
<サイズ> ::= "ショート" | "トール" | "グランデ" | "ベンティ"
<温度> ::= "ホット" | "アイス"
「この波カッコは何?」
「この{ <カスタマイズ> }は、<カスタマイズ>が0個以上であることを示している」
「なるほど」
「<カスタマイズ>って何があるの?」
「ミルクとか、ソースとか、エスプレッソとか」
「全部書き出してみて」
「うん、やってみる」
エイリはレミにルーズリーフを差し出す。レミは考えながらBNFに文法を書き足していく。
<注文> ::= <ドリンク> <サイズ> <温度> { <カスタマイズ> }
<サイズ> ::= "ショート" | "トール" | "グランデ" | "ベンティ"
<温度> ::= "ホット" | "アイス"
<カスタマイズ> ::= <ミルク> | <ホイップクリーム> | <エスプレッソショット> | <シロップ> | <チョコチップ> | <シトラス> | <ソース>
レミはペンを置いた。
「こんな感じ、かな」
「なるほど。これは、ミルクやホイップクリームの量を増やしたり減らしたりできるということなのかな?」
「違う。ミルクのオプションは低脂肪、無脂肪乳、豆乳、アーモンドミルク、オーツミルク、ブレべに変更できる。ホイップクリームのオプションはノンホイップ、ホイップクリーム多め、ホイップクリーム少なめ、ホイップクリーム追加がある」
「カスタマイズ項目ごとに可能なオプションが違うのか」
<注文> ::= <ドリンク> <サイズ> <温度> { <カスタマイズ> }
<サイズ> ::= "ショート" | "トール" | "グランデ" | "ベンティ"
<温度> ::= "ホット" | "アイス"
<カスタマイズ> ::= <ミルク> | <ホイップクリーム> | <エスプレッソショット> | <シロップ> | <チョコチップ> | <シトラス> | <ソース>
<ミルク> ::= "低脂肪乳" | "無脂肪乳" | "豆乳" | "アーモンドミルク" | "オーツミルク" | "ブレべミルク"
<ホイップクリーム> ::= "ノンホイップ" | "ホイップクリーム多め" | "ホイップクリーム少なめ" | "ホイップクリーム追加"
「他のカスタマイズはどうなってるの?」
「書いてみる」
エイリはレミにペンを渡す。
<注文> ::= <ドリンク> <サイズ> <温度> { <カスタマイズ> }
<サイズ> ::= "ショート" | "トール" | "グランデ" | "ベンティ"
<温度> ::= "ホット" | "アイス"
<カスタマイズ> ::= <ミルク> | <ホイップクリーム> | <エスプレッソショット> | <シロップ> | <チョコチップ> | <シトラス> | <ソース>
<ミルク> ::= "低脂肪乳" | "無脂肪乳" | "豆乳" | "アーモンドミルク" | "オーツミルク" | "ブレべミルク"
<ホイップクリーム> ::= "ノンホイップ" | "ホイップクリーム多め" | "ホイップクリーム少なめ" | "ホイップクリーム追加"
<エスプレッソショット> ::= "エスプレッソショット追加"
<シロップ> ::= "バニラフレーバーシロップ追加" | "キャラメルフレーバーシロップ追加" | "ホワイトモカフレーバーシロップ追加"
<チョコチップ> ::= "チョコチップ追加"
<シトラス> ::= "シトラス果肉追加"
<ソース> ::= "チョコレートソース追加" | "キャラメルソース追加" | "ハチミツソース追加"
レミはペンをルーズリーフから離してひと呼吸おく。
「いまの文法だと誤った注文を作れてしまうと思う。『ダークモカチップフラペチーノ、グランデ、ホット、低脂肪乳、豆乳、豆乳、豆乳』みたいな」
エイリはしばらく考えて、それからぎこちなく頷いた。
「確かに。単にカスタマイズを0個以上とするとそうなるのか。修正する必要があるね。えーと、どうすればいいんだろう」
<注文> ::= <ドリンク> <サイズ> <温度> <カスタマイズ>
<サイズ> ::= "ショート" | "トール" | "グランデ" | "ベンティ"
<温度> ::= "ホット" | "アイス"
<カスタマイズ> ::=
[ <ミルク> ] [ <ホイップクリーム> ] [ <エスプレッソショット> ]
[ <シロップ> ] [ <チョコチップ> ] [ <シトラス> ] [ <ソース> ]
| [ <ミルク> ] [ <ホイップクリーム> ] [ <エスプレッソショット> ]
[ <シロップ> ] [ <チョコチップ> ] [ <ソース> ] [ <シトラス> ]
| [ <ミルク> ] [ <ホイップクリーム> ] [ <エスプレッソショット> ]
[ <シロップ> ] [ <ソース> ] [ <チョコチップ> ] [ <シトラス> ]
| ...
エイリはペンを止めた。ルーズリーフを睨みつけて低い声で唸る。
「この角括弧って何?」
レミが尋ねる。
「[ <ミルク> ]は<ミルク>が省略可能であることを示す」
「ふうん。今悩んでるのって、カスタマイズの順序をどうするかってこと?」
「そうだ。普通、ミルクとホイップクリームの順序は注文に関係ない。でも、そのことを記述しようとすると――」
「順列で7!通りのカスタマイズを書かないといけないってことか」
「その通り」
レミは首を傾げて少し考える。
「そこは省略してもいいんじゃない?」
「うーん、そうしようかな」
<注文> ::= <ドリンク> <サイズ> <温度> <カスタマイズ>
<サイズ> ::= "ショート" | "トール" | "グランデ" | "ベンティ"
<温度> ::= "ホット" | "アイス"
<カスタマイズ> ::= [ <ミルク> ] [ <ホイップクリーム> ] [ <エスプレッソショット> ] [ <シロップ> ] [ <チョコチップ> ] [ <シトラス> ] [ <ソース> ] | ...
<ミルク> ::= "低脂肪乳" | "無脂肪乳" | "豆乳" | "アーモンドミルク" | "オーツミルク" | "ブレべミルク"
<ホイップクリーム> ::= "ノンホイップ" | "ホイップクリーム多め" | "ホイップクリーム少なめ" | "ホイップクリーム追加"
<エスプレッソショット> ::= "エスプレッソショット追加"
<シロップ> ::= "バニラフレーバーシロップ追加" | "キャラメルフレーバーシロップ追加" | "ホワイトモカフレーバーシロップ追加"
<チョコチップ> ::= "チョコチップ追加"
<シトラス> ::= "シトラス果肉追加"
<ソース> ::= "チョコレートソース追加" | "キャラメルソース追加" | "ハチミツソース追加"
「じゃあ、こんな感じでどう?」
「まだホットのフラペチーノが注文できるよ」
「どういうこと?」
「ホットのフラペチーノが注文できるということ」
「えっと、どういうこと?」
「ホットのフラペチーノが注文できるということ」
エイリは怪訝な顔で首を傾げた。レミも同じ方向に首を傾げる。
「……ホットのフラペチーノはないの?」
「ホットの氷があるならあると思う」
「フラペチーノって何?」
「コーヒーやミルクとかを氷といっしょにミキサーにかけた飲み物」
「シェイクみたいな?」
「シェイクのスタバ版がフラペチーノ」
「なるほど」
「だから、ホットのフラペチーノはない」
「……なるほど」
「あと、チョコチップはフラペチーノにしか追加できない」
「…………なるほど」
エイリは頭を抱えた。
「大丈夫?」
レミは淡々と尋ねた。エイリは絞り出すような声で答える。
「大丈夫じゃない。前提からやり直さなきゃ。最初の段階で<注文>は<通常注文>と<フラペチーノ注文>に分けて考えなきゃいけなかったんだ」
「フラペチーノ以外にも、ホットドリンクとアイスドリンクは分ける必要がありそう」
エイリはしばらく唸って、意を決してペンを握りしめると、一気に書き上げる。
<注文> ::= <通常注文> | <ホットドリンク注文> | <アイスドリンク注文> | <フラペチーノ注文>
<通常注文> ::= <通常ドリンク> <サイズ> <温度> <共通カスタマイズ>
<サイズ> ::= "ショート" | "トール" | "グランデ" | "ベンティ"
<温度> ::= "ホット" | "アイス"
<共通カスタマイズ> ::= [ <ミルク> ] [ <ホイップクリーム> ] [ <エスプレッソショット> ] [ <シロップ> ] [ <シトラス> ] [ <ソース> ] | ...
<ミルク> ::= "低脂肪乳" | "無脂肪乳" | "豆乳" | "アーモンドミルク" | "オーツミルク" | "ブレべミルク"
<ホイップクリーム> ::= "ノンホイップ" | "ホイップクリーム多め" | "ホイップクリーム少なめ" | "ホイップクリーム追加"
<エスプレッソショット> ::= "エスプレッソショット追加"
<シロップ> ::= "バニラフレーバーシロップ追加" | "キャラメルフレーバーシロップ追加" | "ホワイトモカフレーバーシロップ追加"
<シトラス> ::= "シトラス果肉追加"
<ソース> ::= "チョコレートソース追加" | "キャラメルソース追加" | "ハチミツソース追加"
<ホットドリンク注文> ::= <ホットドリンク> <サイズ> <共通カスタマイズ>
<アイスドリンク注文> ::= <アイスドリンク> <サイズ> <共通カスタマイズ>
<フラペチーノ注文> ::= <フラペチーノドリンク> <サイズ> <フラペチーノカスタマイズ>
<フラペチーノカスタマイズ> ::= <共通カスタマイズ> [ <チョコチップ> ] | ...
<チョコチップ> ::= "チョコチップ追加"
「これでどうだ!」
エイリは荒い呼吸を繰り返している。レミは静かにBNFに目を通している。
「厳密に合ってるかは私にもわからないけど、いいんじゃない?」
「やった! ……疲れた」
エイリは椅子に座ったまま両手を挙げて天井を見上げた。
「良かった。じゃあ、スタバに行こうか」
エイリはしばらくぼうっと考える。
「そういう話だっけ?」
「そうだよ。さ、行こう。フラペチーノを飲みに」




