ことのは

日本語の文章で書く、アクター型の並列プログラミング言語

プログラムを日本語の文章として書きます。同じプログラムは、字下げで構造を示す構造化形式にも書けて、二つの書き方は機械的に行き来できます。

文章形式
フォークが「返す」というメッセージを受け取ったとき、待ち行列が空でなければ、待ち行列の先頭から次の哲学者を取り出し、次の哲学者に「渡す」というメッセージを送る。そうでなければ、使用中をいいえに変更する。
▲ ▼ 同じ構文木を経由して相互に変換
構造化形式
「返す」を受け取ったとき、
    もし 待ち行列 が 空 でない ならば、
        次の哲学者 は 待ち行列 の先頭を取り出す。
        次の哲学者 に「渡す」を送る。
    そうでなければ、
        使用中 は いいえ。
    以上。
以上。

特徴

自然な日本語に見えて、読み方はひと通りにしか決まらない──そのための言語設計です。

文

文章がそのままプログラム

字下げも括弧も使いません。「〜を受け取ったとき、」「〜ならば、」「〜を送る。」といった日本語の言い回しで構造を表します。

ア

アクターとメッセージ

処理の単位は独立したアクター。状態を共有せず、メッセージを送り合って協調します。このページの中で実際に動かせます。

⇅

二つの書き方を行き来

文章形式と、字下げで構造を示す構造化形式。どちらで書いても同じ構文木になり、片方からもう片方を機械的に作れます。

一

一文方式

「〜ならば、」の本体はその一文だけ。二文以上は「次のことを行う。…以上。」で囲みます。これで日本語の曖昧さを文法から締め出します。

0

衝突 0 の LR(1) 文法

文法は bison で検査済み。衝突は 0 件で、正しい文章なら読み方は必ずひと通りに決まります(全 85 規則)。

名

名前は宣言から切り出す

日本語には空白がないので、宣言された名前(「先のフォーク」など)と予約語を、長いものから優先して切り出します。

二つの書き方

5 人の哲学者問題の「フォーク」アクターを、二つの形式で並べました。左を解析すると右が得られ、右を逆変換すると左に戻ります。

文章形式(インデントなし)

フォークというアクターを定義する。
フォークは番号と使用中と待ち行列を持つ。
番号の初期値は0とし、使用中の初期値はいいえとし、待ち行列の初期値は空とする。

フォークが「取りたい」というメッセージと哲学者を受け取ったとき、使用中がいいえならば、使用中をはいに変更し、哲学者に「渡す」というメッセージを送る。そうでなければ、哲学者を待ち行列の末尾に追加する。

フォークが「返す」というメッセージを受け取ったとき、待ち行列が空でなければ、待ち行列の先頭から次の哲学者を取り出し、次の哲学者に「渡す」というメッセージを送る。そうでなければ、使用中をいいえに変更する。

これでフォークの定義を終わる。

構造化形式(インデントあり)

「フォーク」というアクターを定義する。
    状態は 番号、使用中、待ち行列。
    初期状態は
        番号 は 0。
        使用中 は いいえ。
        待ち行列 は 空。
    以上。
    「取りたい」と 哲学者 を受け取ったとき、
        もし 使用中 が いいえ ならば、
            使用中 は はい。
            哲学者 に「渡す」を送る。
        そうでなければ、
            待ち行列 に 哲学者 を追加する。
        以上。
    以上。
    「返す」を受け取ったとき、
        もし 待ち行列 が 空 でない ならば、
            次の哲学者 は 待ち行列 の先頭を取り出す。
            次の哲学者 に「渡す」を送る。
        そうでなければ、
            使用中 は いいえ。
        以上。
    以上。
定義を終わる。

哲学者は、番号の小さいフォークから先に取ります。そのため哲学者5だけはフォーク1を先に取り、全員が片方のフォークを握って待ち合う輪ができません(デッドロックしない)。フォークもアクターなので、隣り合わない哲学者は同時に食事できます。全文は「試してみる」の見本で読めます。

試してみる

サーバは使いません。このページに入っている解析器・逆変換器・実行系が、ブラウザの中で変換し、実行します。どちらの欄も書き換えられます。

⌘ / Ctrl + Enter で、カーソルのある欄から反対側へ変換
文章形式(インデントなし)
構造化形式(インデントあり)

逆変換で戻ってくるのは標準の書き方です。「その哲学者」の「その」や、文をどこで「。」で切ったかは構文木に残らないので、元の言い回しとは少し違うことがあります。構造化形式のほうは、往復しても一字も変わりません。
実行は、文章形式の欄のプログラムを構文木にして解釈します。アクターはそれぞれ受信箱を持ち、届いたメッセージを一通ずつ処理します。どのアクターが次に動くかは「動く順」で選びます。「ばらばら」は種つきの乱数なので、同じ種なら何度でも同じ動きを再現できます。種を変えると、並列ならではの別の動きになります。

文法

文章形式の文法は、文脈自由文法(BNF)で書けます。インデントを使わないので、Python のような字下げの扱いも要りません。

BNF 全 85 規則を見る(bison の文法から自動生成)
  1 <プログラム>       ::= <定義の並び> "実行を始める。" <文の並び> "これで" "実行を終わる。"
  2 <定義の並び>       ::= ε
  3                 | <定義の並び> <アクター定義>
  4 <アクター定義>      ::= "名前" "というアクターを定義する。" <状態宣言> <定義本体> "これで" "名前" "の定義を終わる。"
  5 <状態宣言>        ::= "名前" "は" <名前の並び> "を持つ。"
  6 <名前の並び>       ::= "名前"
  7                 | <名前の並び> "と" "名前"
  8 <定義本体>        ::= ε
  9                 | <定義本体> <定義の項目>
 10 <定義の項目>       ::= <初期値文>
 11                 | <受信の頭> <文>
 12                 | <文>
 13 <初期値文>        ::= <初期値の並び> "とする。"
 14 <初期値の並び>      ::= <初期値>
 15                 | <初期値の並び> "とし、" <初期値>
 16 <初期値>         ::= <式の並び> "の初期値は" <式>
 17 <受信の頭>        ::= <式> "が" "「文字列」" "というメッセージ" "を受け取ったとき、"
 18                 | <式> "が" "「文字列」" "というメッセージ" "と" "名前" "を受け取ったとき、"
 19 <文の並び>        ::= ε
 20                 | <文の並び> <文>
 21 <文>           ::= <一文の中身> "。"
 22                 | "その後、" <一文の中身> "。"
 23                 | <条件文>
 24                 | "その後、" <条件文>
 25                 | <繰り返し文>
 26 <一文の中身>       ::= <終止節>
 27                 | <連用節> "、" <一文の中身>
 28 <条件文>         ::= <条件> <本体>
 29                 | <条件> <本体> "そうでなければ、" <本体>
 30 <本体>          ::= <一文の中身> "。"
 31                 | "次のことを行う。" <文の並び> "以上。"
 32 <条件>          ::= <式> "が" <式> "ならば、"
 33                 | <式> "が" <式> "でなければ、"
 34                 | <式> "が" <式> "より小さければ、"
 35 <繰り返し文>       ::= "数" "から" "数" "までの各番号について、" <本体>
 36 <終止節>         ::= <表示の前半> "表示する"
 37                 | <送信の前半> "送る"
 38                 | <変更の前半> "変更する|設定する"
 39                 | <加算の前半> "加える"
 40                 | <追加の前半> "追加する"
 41                 | <取り出しの前半> "取り出す"
 42                 | <名付けの前半> "名付ける"
 43 <連用節>         ::= <表示の前半> "表示し"
 44                 | <送信の前半> "送り"
 45                 | <変更の前半> "変更し|設定し"
 46                 | <加算の前半> "加え"
 47                 | <追加の前半> "追加し"
 48                 | <取り出しの前半> "取り出し"
 49                 | <名付けの前半> "名付け"
 50 <表示の前半>       ::= <式の並び> "を"
 51 <送信の前半>       ::= <式の並び> "に" "「文字列」" "というメッセージ" <添え物> "を"
 52                 | <式の並び> "に" "それぞれ" "「文字列」" "というメッセージ" <添え物> "を"
 53                 | <式> "の全員" "に" "「文字列」" "というメッセージ" <添え物> "を"
 54 <添え物>         ::= ε
 55                 | "と" <式>
 56 <変更の前半>       ::= <式の並び> "を" <式> "に"
 57 <加算の前半>       ::= <式の並び> "に" <式> "を"
 58 <追加の前半>       ::= <式の並び> "を" <式> "に"
 59                 | <式の並び> "を" <式> "の末尾" "に"
 60 <取り出しの前半>     ::= <式> "の先頭から" "名前" "を"
 61 <名付けの前半>      ::= <作るもの> "、" "名前" "と"
 62 <作るもの>        ::= "名前" "というアクター" "を" "1つ" "生成し"
 63                 | <式の並び> "を" "用意し"
 64 <式の並び>        ::= <式>
 65                 | <式の並び> "と" <式>
 66 <式>           ::= <項>
 67 <項>           ::= "名前"
 68                 | "その" "名前"
 69                 | "数"
 70                 | "「文字列」"
 71                 | "「文字列」" "という文字列"
 72                 | "はい"
 73                 | "いいえ"
 74                 | "なし"
 75                 | "空"
 76                 | "空の配列"
 77                 | "自分"
 78                 | "自分自身"
 79                 | "現在の番号"
 80                 | <項> "の" "名前"
 81                 | <項> "の" <位置> "番目"
 82 <位置>          ::= "数"
 83                 | "現在の番号"
 84                 | "(" <式> ")"
 85                 | "(" <式> "に" <式> "を" "加えた数" ")"

「次のことを行う。」で囲まずに条件を直接入れ子にできる版も作りました。この版は if‑then‑else の衝突がちょうど 1 件出ます。C 言語と同じく「一番近い『ならば』に付く」と決めれば、読み方はひと通りに決まります。この版は、文章の読み手がそう読むとは限らないので、標準にはしていません。

検証

「通るはず」ではなく、道具で確かめた結果です(2026 年 11 月 11 日)。

確かめたこと結果
bison 3.8.2 で文法を検査(LALR(1))衝突 0(状態 171)
条件を直接入れ子にできる版の文法衝突 1(else の付き先だけ)
見本 4 本(文法違反の例を除く)を「文章 → 構造化 → 文章 → 構造化」と往復構造化形式は 4 本とも一字一句同じ
逆変換した文章をもう一度変換4 本とも変わらない
このページの変換器(JavaScript)と C 版・Python 版の出力の突き合わせ(見本 5 本)5 本とも一致
(違反の例は両方とも同じ所で止まる)
5 人の哲学者(番号の小さいフォークから取る版)を、乱数の種 1〜1000 で実行1000 回とも全員が 3 回食べて満腹で終了
同じ問題で、全員が左のフォークから取る版を種 1〜1000 で実行721 回はデッドロックで停止
(止まると待ちの輪を表示)
哲学者の文章から文を消す・入れ替える・重ねた変異 300 本を、両方の解析器に通す300 本とも判定と出力が一致
(通った 103/弾いた 197)

このページの解析器は、bison に渡した文法ファイルそのものから jison(bison 互換の生成器)で作っています。手で別の解析器を書いていないので、文法がずれることはありません。