Oマークアップ言語
本稿ではOマークアップ言語 (O Markup Language; OML) を規定します。
ファイルの拡張子は.omlを推奨します。
文書の記述には、後述するアスキーの記号の文字が含まれる
任意の文字コードを使用して構いません。
実装では少なくともUTF-8に対応することを推奨します。
表す文書はノードの系列よりなります。 ノードはテキストないし要素です。 要素には札と0以上の子ノードの系列があります。
左右で対をなすアスキーの記号の文字
(<[{
(}]>))
を左(右)嘴とします。
そうでないアスキーの記号の24種類の文字
!"#$%&'*+,-./:;=?@\^_`|~
を2個ないし1個連ねたものを眼とします。
2文字の眼は1文字の眼に対して優先します。
アスキーの空白に属す文字、すなわち
水平タブ (HT, 0x09)、
改行(LF, 0x0A)、
垂直タブ (VT, 0x0B, \v)、
改ページ (FF, 0x0C, \f)、
行頭復帰 (CR, 0x0D, \r)
半角空白 (SP, 0x20)
の1つ以上の系列を頬とします。
空文字 (NUL, 0x0) は構文解析後の表現において、
文字コードが対応していれば置換文字――
例えばユニコードであればREPLACEMENT CHARACTER (U+FFFD) ――で置き換えるか、
そうでなければ除かれます。
構文解析は逐次に処理されます。 また以降で「潜在的な」としているものは 最終的に要素にならなければテキストになります。 嘴と眼と省略可能な頬の出現は潜在的な左頭です。 省略可能な頬と眼と嘴の出現で後述の要素の作成を試みます。 それ以外の類型の出現はテキストです。
左頭には照応する札を持つものがあります。
この対応付けの集合を語彙とします。
語彙を変更する特別な要素を語彙変化とします。
その既定の左頭は<!です。
左頭に札がもしあれば備わります。
要素の作成の条件は、それより前の系列に最も近い左頭が存在し、 同じ種類の嘴かつ眼が一致するときです。 眼が一致するのは、眼の個数が同じであり、 眼が1つのとき左頭の眼と同じ、 または眼が2つのとき左(右)眼が左頭の右(左)眼と同じときです。 条件を満たすとき、その左頭より後から左眼より前の系列について、 左頭の札が語彙変化であるなら後述の処理を行い、 左頭の札が空でないなら系列を子に持つ要素を作成し、 左頭の札が空でありかつ 潜在的な語彙変化の直接の子要素であるなら潜在的な要素になります。
語彙変化の処理ではその中身の系列のそれぞれについて、 可能なら次の操作を1度まで行います。 すなわち要素であるなら中身の系列について、 テキストなら要素が対応する札とし、 左頭なら左頭への対応付けを要素の左頭に移します。
以上で言語が規定されました。 以降は非規範的な内容です。
実例
本節では実例を示します。 ここではJSONによる出力を併記します。 これにより、本文書を使った適合性試験を行えます。 JSONによる出力は抽象構文木を表す次のJSONスキーマにしたがいます。 これは参照実装の実行プログラムが生成する形式ですが、 準拠する実装では必ずしもこの構造を生成しなくて構いません。
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "urn:local:oml-ast.schema.json",
"title": "Sample AST",
"type": "array",
"items": { "$ref": "#/$defs/node" },
"$defs": {
"node": {
"anyOf": [
{ "type": "string" },
{ "$ref": "#/$defs/element" }
]
},
"element": {
"type": "object",
"properties": {
"label": { "type": "string" },
"children": {
"type": "array",
"items": { "$ref": "#/$defs/node" }
}
},
"required": ["label", "children"],
"additionalProperties": false
}
}
}
任意の文字列は適正な原稿です。
Case 1:a
["a"]
著作権表示のマークは要素ではなく、これは眼がないためです。 素の文字列そのままです。
Case 2:(C)
["(C)"]
語彙になければ要素になりません。
Case 3:(+a+)
["(+a+)"]
最小の語彙変化は次の通りです。
Case 4:<!(*a*)!>(*b*)
[{"label":"a","children":["b"]}]
眼が2つのときは次の通り。
Case 5:<!(:~a~:)!>(:~b~:)
[{"label":"a","children":["b"]}]
語彙変化で移動があった場合、元の語彙はなくなります。
Case 6:<!(+a+)(* (+ *)!>(+b+)(*c*)
["(+b+)",{"label":"a","children":["c"]}]
要素にならない場合、頬になる可能性があった部分は保たれます。
Case 7:(+ (* +)
["(+ (* +)"]
要素になる場合、頬は除かれます。
Case 8:<!(+a+)!>(+ (* +)
[{"label":"a","children":["(*"]}]
語彙変化もまた別の要素に変更できます。
Case 9:<! <? <! ?> !><? (+a+) ?><!a!>(+b+)
["<!a!>",{"label":"a","children":["b"]}]
閉じていない左頭は素のテキストです。
Case 10:<
["<"]
<!
["<!"]
<!?
["<!?"]
左頭のない右頭は素のテキストです。
Case 13:!
["!"]
!>
["!>"]
?!>
["?!>"]
変更履歴
2023年5月21日に第1版が書かれました。 着想の元となったのはTeX、XML、Djotです。 2025年4月27日に本言語の頭字語をOMLにしました。 2026年5月17日に第8版となり空白の扱いが追加されました。 2026年5月21日に本言語および参照実装を一般公開しました。 2026年6月21日に空文字の扱いで置換文字への置き換えを追記しました。使用許諾
Copyright (C) 2023-2026 gemmaro. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without any warranty.