数しか話せない言語

よみもの+手を動かす時間:およそ30分

最小の言語を、定義する

今日作る言語の仕様書は、2行で書き終わります。

  • 文法:プログラムとは、1個の数である
  • 意味:数は、その数を表す

42 は正しいプログラムで、意味は 42。3.14 も正しいプログラムで、意味は 3.14。それだけ。笑ってしまうほど小さい。でも「正しい文のかたち」と「その意味」が両方定まっているので、これはまぎれもなく言語です。

① ことばの粒(トークン)
42
③ 評価された値
42

hello1 + 2 を打ってみてください。この言語は、きっぱり断ります。何を断るかが決まっていることも、言語が言語であることの一部です。

工程①を、自分の手で書く

この言語の処理系は、工程①(粒に分ける)がほぼすべてです。やることは「文字を1つずつ見て、数字なら集める」。JavaScriptで本当に書いてみます。これは飾りのコードではなく、動く字句解析器です。

JavaScript
// 数を読み取る、世界最小の字句解析器
const source = "42";

let i = 0;
let digits = "";
while (i < source.length && "0123456789.".includes(source[i])) {
  digits = digits + source[i];
  i = i + 1;
}

if (digits === "" || i < source.length) {
  console.log("読めませんでした:" + source);
} else {
  console.log("読めた数:", Number(digits));
}

Ctrl+Enter でも実行できます

1行目の "42" をいろいろ変えて実行してください。"3.14" は読める。"abc" は断られる。"42x" も断られる——途中までしか読めなかったからです。

コードを目で追うと、やっていることは「数字が続くかぎり digits に集める」だけだと分かります。字句解析は、根気のいい単純作業です。だからこそ、機械にやらせる価値があります。

よりみち:「42x」を断るかどうか

「42xは、42まで読めたから42でいいのでは」という設計もありえます。実際、ゆるく読む言語も世の中にはあります。でも「最後まで読み切れない入力は断る」ほうが、書き手のまちがい(タイプミス)に早く気づけます。どちらにするかは、言語設計者——つまりあなた——の選択です。

意味のほうは、どうした

工程③(意味にする)はどこへ行ったのでしょう。実は上のコードの Number(digits) がそれです。「数字の並びという文字」を「数という」へ。地味な一歩ですが、"42"42 は別ものです。文字の世界から値の世界への、国境越えです。

これで、字句解析(読む)と評価(意味にする)が揃いました。あなたはいま、ひとつの言語の処理系を、端から端まで理解しています。

「言語を作った」と言っていい

冗談ではなく、本当に言っていいのです。正しい文の集合が定まっていて、それぞれの意味が定まっていて、処理系が動く。これからのレッスンは、この小さな核に語彙を足していく作業です。ゼロから一を作る仕事は、もう終わりました。

演習:言語を、すこしだけ拡張する

上の字句解析器を改造して、マイナスの数(例:"-42")も読めるようにしてください。

ヒント1(考え方)

マイナスの数は「先頭にだけ - があってもよい」と言いかえられます。最初の1文字が ”-” だったら、それを覚えてから、残りをいままでどおり読みます。

ヒント2(かたち)

whileの前にこんな形を足します:if (source[i] === "-") { digits = "-"; i = 1; }

こたえ(の一例)

whileループの前に上の2行を入れるだけで動きます。"-3.5" も読めるはずです。ただし "4-2" は途中で止まって断られます——「-は先頭にだけ」という決めごとが、ちゃんと効いている証拠です。

別の書き方をしたとしても、"-42" が読めて "abc" が断られるなら、あなたの設計は成立しています。

このレッスンで分かったこと

  • 言語の定義=正しい文のかたち+その意味。小ささは欠点ではない
  • 字句解析は「数字が続くかぎり集める」のような、根気のいる単純作業
  • "42"(文字)と 42(値)は別もの。評価とはその国境越え
  • あなたは今日、言語をひとつ作った