一行の読まれ方
一行が一文である。.muro の一行は、
キーワード 位置引数… key:value…
の形をとる。読む側の状態は「直前の非字下げ行が何だったか」だけで、括弧も終端子も入れ子も無い。この頁は、その一行がトークンへ割られ、値へ変わるまでを書く。どの行が書けるかの一覧は .muro の全構文、位置の綴りは 位置と領域、属性の掟は 属性の三層 にある。
koyu 1.0
name 街角 の 複合ビル
unit mm
grid X 0 6400 12800
grid Y 0 5600
level L1 0 h:2700 slab:200
space /L1/ldk ldk X1..X2 Y1..Y2 name:"居間 と 食堂" acme.note:"#3 と #4"
space /L1/hall hall X2..X3 Y1..Y2 name:玄関 # 末尾コメント
space /out exterior name:外部
boundary /L1/hall /out t:150 spec:EW1
door w:900 h:2100 edge:S name:玄関戸
トークン
区切りは空白で、何個でもよい。上の例が桁を揃えているのは読むためであり、意味は変わらない。タブも空白である。空行は無視される。
行継続は無い。行末の \ も、次行への折り返しも無い。長い行は長いまま書く — 分けたいなら層に分けて import で重ねる。
位置引数は順序が意味である。space /L1/ldk ldk … の第1が パス、第2が型で、入れ替えれば別の意味になるか、読めなくなる。位置引数の数と並びはキーワードごとに違う。
コメント
引用符の外の # から行末までがコメントである。行頭に置けば行全体が消え、行末に置けばそこから先が消える。
# この行はまるごとコメント
space /L1/hall hall X2..X3 Y1..Y2 name:玄関 # ここから先もコメント
# を値として書きたければ引用符で囲む。acme.note:"#3 と #4" の値は #3 と #4 である。
引用符
" は開閉のスイッチであって、トークンを囲む器ではない。トークンのどこに現れてもよく、対で現れた区間の中では空白と # が普通の文字になる。引用符そのものは値に残らない。
| 書いたもの | 得られる値 |
|---|---|
name:"居間 と 食堂" | 居間 と 食堂 |
name:南"の"部屋 | 南の部屋 |
acme.note:"#3 と #4" | #3 と #4 |
h:"2400" | 数値 2400 — 引用符は数値の読みを止めない |
閉じない引用符はエラーである。行の終わりまで開いたままなら Unclosed quote で止まる。
字下げ
行頭に空白があれば、その行は直前の非字下げ行に従属する。深さは意味を持たない — 一段だけで、入れ子は無い。空白が一つでもあれば従属し、無ければ新しい親になる。
| 親 | 書ける字下げ行 |
|---|---|
boundary / stack | door window seg line |
space | area |
band | space (帯の要素 — 領域の代わりに w: を持つ) |
over | + - = |
親でない行の下に字下げ行を置けばエラーになり、親と噛み合わない語も同じくエラーである。over の直下に置けるのは + - = の三つだけで、door を直に字下げしても通らない。
親が複数の対象へ展開されるなら、字下げ行はその全部に効く。boundary /L3..L10/a /L3..L10/b の下の door は8階ぶんの境界すべてに一枚ずつ吊られ、stack の下の字下げ行はその積層の全ての垂直境界へ渡る (垂直境界の開口は解釈されないので、check は警告を出す)。
key:value
キーは最初の : の左、値は右である。
- 値が空ならエラー (
name:だけの書き方は無い) - キーが空ならエラー (
:xは読めない) - 同一行内で同じキーが二度出ればエラーである。後勝ちを黙認すると、綴り違いとマージ事故が隠れる
値の型は綴りが決める。-?\d+(\.\d+)? に完全一致すれば数値、それ以外は文字列になる。
h:2400 → 数値 2400
h:2400.5 → 数値 2400.5
h:24OO → 文字列 "24OO" (英字の O が混じっている)
name:0123 → 数値 123 (先頭の 0 は消える)
uid:0123 → エラー — uid に数字だけのトークンは書けない
数値として読めない値を数値の場所に書いたときは黙って落ちない。行の場で The attribute h is written as a number: 24OO になるか、属性の三層 が言う ATT01 になる。
キーを勝手に増やすことはできない。台帳に無いキーは名前空間 (acme.note のようなドット区切り) を持たなければ書けず、持たなければ ATT03 になる。詳しくは 属性の三層。
位置引数と属性の見分け
パーサは「トークンに .. が含まれるか」「/ で始まるか」「: を含むか」で位置引数と属性を分ける。行の中での並びは、ほとんどの行で自由である — space /L1/a room name:居室 X1..X2 Y1..Y2 は領域を先に書いた版と同じに読まれる。
例外が一つある。開口の先頭の非 key:value トークンはアセット参照であって、名ではない。
asset SD1 door w:800 h:2000 style:sliding name:片引き戸
boundary /L1/a /L1/b
door SD1 at:0.3 # SD1 というアセットを参照する
door w:900 name:D2 # 名は name: に書く
door D2 w:900 と書けば「D2 というアセットが未定義である」と言われる。名は必ず name: に書く。
正規化と出所
原稿は NFC として読まれる。が は一つの符号位置とも「か + 濁点」とも綴れる。正規化しなければ同じに見える二つのパスが別の空間になり、パス重複のエラーも出ないまま機械形式に見分けのつかないキーが二つ並ぶ。NFKC は採らない — ㎡ や ① を書き換えてしまい、それは書かれた表記を保つことに反する。
エラーは行を名指す。位置を持つ診断は <ファイル>:line <N>: <本文> の形で出る。層を重ねているときの <ファイル> は、その行を書いたファイルであって入口のファイルではない。