Habrahabrでの自作マークアップ言語の週。 AXONに関する記事は、私のot
プロジェクト-オブジェクトテンプレート言語-を思い出しました。 その中で、XML、YAML、その他の興味深いアイデアを組み合わせました。
何、もう一つ?
自転車は違います。 たとえば、データ記述言語と、ある程度マークアップ言語を作成することに興味がありました。
TL; DR
<note status="saved"> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</body> </note>
note: status :: saved; to: "Tove"; from: "Jani"; heading: 'Reminder'; body: `Don't forget me this weekend!`; ;
コンセプト
最初は、コードが常に特定のノードのコンテキストで実行されるように、DOM内のプログラミング言語のようなものが必要でした。これにより、DOMコンテキストノードなどの言語制御命令、変数、ランタイムマップピットオブジェクトでDOMをナビゲートできます。 など その結果、コンセプトの最初のバージョンはメモリから正常に飛び出しました。
2番目のオプションははるかに単純で、一般にそのようなプログラミングに関するものではありません。 xhtmlがコントロールと混在している場合、JSPテクノロジーで表示される形式のテンプレートについて詳しく説明します。 同時に、jspはプログラミングなしの純粋なテンプレート化に適していることがわかりました。 しかし、XMLは素晴らしくひどいものです。
また、JSON、YAML、TOML(ステロイドの.ini)を除いて、何を置き換える必要がありますか? 最初はプリミティブ型、オブジェクト、javascript配列を説明し、2番目は同じことをしますが、中括弧なしで、3番目はそれについてまったくありません。
それらは、ただ1つのことでXMLと区別されます;それらはそのプロパティを通してオブジェクトを記述します。 必要に応じて、ユーザーはオブジェクトにtype
フィールドを追加し、オブジェクトのクラスを説明すると想定されています。 XMLでは、オブジェクトはクラスのインスタンスとして直接記述され、必要に応じて、識別子などの追加フィールドを指定できます。
YAMLのシンプルさとXMLのオブジェクトの概念を組み合わせるとどうなりますか? そうです-オブジェクトテンプレート言語は、データ、構造、およびテンプレートを記述するための実験的な人間が読める言語です。
Ot
概略的には、OT全体を1行のmodule~class(id): content;
記述することができます〜class module~class(id): content;
つまり、再帰オブジェクトテンプレートのモジュラー言語です。 さらに、文字列に加えて追加のデータ型があり、非概念エンティティとしてのJSONのオブジェクトのような連想配列はありません。
テキスト識別子、文字列、ブール、整数、および実定数に加えて、オブジェクトのツリー構造(オブジェクトモデル)を記述することができるいくつかの文字があります。 他のタイプのグラフ構造を構築するための参照タイプもあります。
識別子、識別子グループ、マークアップ文字、および定数間の空白は無視され、意味のある文字を区切るために使用されますが、オブジェクトのコンテンツには含まれません。 引用符内では、空のスペースが考慮されます。
オブジェクトモデル
テンプレートは、ルートである単一のオブジェクトです。 を含む任意のオブジェクト ルートでは、少なくともオブジェクトのクラスの識別子で表され、オプションでモジュールの識別子とオブジェクトの一意の識別子で表されます。
module~class(id)
たとえば、htmlページの場合、 body
クラスのオブジェクトがあり、このクラスの取得元モジュールの識別子( html~body
)を前に付けることができます。 このオブジェクトには識別子index-page
が与えられ、これにより@index-page
リンクを介してオブジェクトとの接続を確立でき@index-page
。
body html~body html~body(index-page) @index-page
オブジェクトは互いにネストできるため、最初のオブジェクトには2番目のオブジェクトが含まれ、親子関係が確立されます。
html: body ;
オブジェクトの内部コンテンツは、シンボル:
後に始まります:
対応する文字までのすべてのコンテンツ;
親オブジェクトに属すると見なされます。 オブジェクトがコンテンツを想定していない場合、文字:;
示されていません。
オブジェクトのクラスの識別子は、すべてのオブジェクトに必須であることに注意してください。つまり、テンプレート内の2つ以上の同一のクラス識別子は、クラスの2つ以上のインスタンスに対応します。
html: body: br br br; ;
再利用
テンプレートの複数の場所でコンテンツを記述できるオブジェクトの場合、クラスの新しいインスタンスが作成されず、すべてのコンテンツが親オブジェクト内のこのクラスの1つのインスタンスに属するコンテンツを記述するモードを指定できます。 これは、コンテンツを開くために::
記号を使用することで実現されます。
xml: attr :: id: "my-xml"; ; attr :: xmlns: "urn:oberon:ot"; ; ;
再利用モードでは、クラスだけでなく、オブジェクトの他のパラメーター、そのモジュール、および識別子も考慮されます。
その他のコンテンツ
子孫オブジェクトに加えて、さまざまな定数とオブジェクト参照を親オブジェクトに含めることができます。 同時に、個々のコンテンツ要素を区切るために空のスペースが使用されます。
html: head: title: ", !"; ; body: p: 2 "+" 2 "=" 4.0; concat: "Hello":':':"World":"!"; ; ;
テキストの内容は、 "
'
、 "
'
、 "
などのさまざまなタイプの引用符で示され、テキストの単一文字を単一引用符で0DU
、末尾に修飾子U
を付けた16進コード(たとえば、 0DU
)を使用することができます。テキストには、改行やその他の文字が含まれる場合がありますunicode。文字列の2つ以上の部分の間にある文字を使用して、文字列と文字を連結することができ、結果の文字列はオブジェクトモデルで単一の文字列として表されます。
モジュール性
最も単純な形式のモジュール性により、異なる性質のオブジェクトの同じクラスを視覚的に分離できます。 たとえば、 html~body
およびhtml~body
です。 オブジェクトモデルのモジュール性は、一部のモジュールのコンテキストサポートの存在も意味し、その拡張機能により、実行時にテンプレートを操作する可能性を拡張できます。
標準モジュールとクラス
標準モジュールは、オブジェクトモデルに追加のランタイム機能を提供します。
コア
core
モジュールは統合モジュールであり、基本モジュールでもあります。 core
モジュールの使用を開始するには、テンプレートテンプレートのルートオブジェクトとしてcore~template
クラスをインスタンス化する必要があります。 したがって、ルート要素のコンテンツ全体がcore
モジュールのクラスにアクセスできます。 それ以外の場合、 core
モジュールの機能は無効になります。
core~template: (* *) ;
core
モジュールはimport
クラスを提供します。これにより、サードパーティのテンプレート(標準、カスタム、仮想など)に対するテンプレートの依存関係を記述できます。
core~template: import: context; ;
タイプがcore〜templateのオブジェクト内では、 import
などの既知のクラスの暗黙的なモジュール指定が動作し、インポートされたクラスには同じルールが適用されるため、毎回core
モジュールと他のインポートされたモジュールを指定する必要はありません(可能性は残ります)。
例:
core~template: import: html; html: body: p: ", !";;; ;
html
、 body
およびp
クラスはhtml
モジュールに属し、それらの所有権はランタイムによって制御されますが、それらのモジュールを明示的に指定する必要はありません。
テンプレートとユーザーデータ
コンテキスト
core
モジュールは、 context
モジュールの識別子であるcontext
クラスを提供します。
context
モジュールは、オブジェクトモデルの存在のコンテキストデータへのアクセスを提供します。 context
モジュールの特別なクラスを介してモデルオブジェクトにアクセスすると、ランタイムからテンプレートコンテンツにデータを配置できます。
たとえば、 context~$
クラスを使用すると、識別子または識別子の階層セットによってコンテキストデータにアクセスできます。
core~template: import: context; $(hello-world-text)`, `$(user-names/hello-world-user)`!` ;
したがって、何らかの方法でコンテキストに配置され、特定の識別子によってアクセス可能なデータに応じて、テンプレートテキストを処理し、オブジェクトモデルを構築した後、特定の値を持つ最終オブジェクトを取得します。
core~template: import: context; `` `, ` `` `!` ;
実装
パーサーの最初のプロトタイプはgolangで記述され、いくつかのテンプレートモジュールはもちろんcore
実装され、zbase32文字列の形式でバイナリ情報を保存するための別のモジュール、優れた形式、この形式のデザインドキュメントは特別な言及に値し、人々がbaseXXX形式で状況を慎重に分析した方法。
将来、Javascript用のOTパーサーの不完全なプロトタイプが実装されました。これは、言語で構造原子を記述するための言語の基礎になりましたが、これは別の話です。
参照資料
- リポジトリhttps://github.com/kpmy/ot
- nedotest https://github.com/kpmy/ot/blob/master/ot_test.goの形式の追加例
- ディスカッションzbase32 http://philzimmermann.com/docs/human-oriented-base-32-encoding.txt