このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

Catyコマンド宣言の構文

仕様待ちで実装が滞るなんてのは情けない話なので、取り急ぎ。味気ないBNFのみ。

補助的な定義

型 ::= 型変数 | 任意のJSON型表現 | 'never'
スカラー型 ::= integer型 | number型 | string型 | boolean型 | null型
             | 簡易列挙型
             | 'anyScalar'
/*
 * スカラーの各型は、型名予約語にオプショナルなスキーマ属性
 * never の意味は、出力が存在しないこと(voidとは違う!)
 * anyScalar の意味は、(number|string|boolean|null) 
 */

簡易列挙型 ::= 値 | '(' 値 ('|' 値)* ')'
/* 値は、nullを除く組み込みスカラー型のリテラル、
 * ただし、同じ種類の値で重複はなし 
 */

型変数 ::= アンダスコアからはじまる名前
コマンド名 ::= いずれ定義する(当面、単純な名前)
オプション名 ::= いずれ定義する(当面、任意の文字列リテラル)

コマンド宣言全体の構造

コマンド宣言 ::= 'command' コマンド呼び出しパターン '::' 宣言本体
宣言本体 ::= プロファイル 大域脱出宣言 資源使用宣言 ';'

コマンド呼び出しパターン

コマンド呼び出しパターン ::= コマンド名 オプションパターン 引数パターン

/* 
 * オプション引数のパターン
 */
オプションパターン ::= '{' オプションパターン指定並び '}'
オプションパターン指定 ::= オプション名 ':' スカラー型
オプションパターン指定並び ::= 
    固定長オプションパターン指定並び 
    | 
    可変長オプションパターン指定並び

固定長オプションパターン指定並び ::= 
    空 | オプションパターン指定 (',' オプションパターン指定)*
可変長オプションパターン指定並び ::= 
    '*' ':' スカラー型
    | 
    オプションパターン指定 (',' オプションパターン指定)* ',' '*' ':' スカラー型

/* 
 * プレーン引数(位置引数)のパターン
 */
引数パターン ::= '[' 引数パターン指定並び ']'
引数パターン指定 ::= スカラー型
引数パターン指定並び ::= 
    固定長引数パターン指定並び 
    | 
    可変長引数パターン指定並び

固定長引数パターン指定並び ::= 
    空 | 引数パターン指定 (',' 引数パターン指定)*
可変長引数パターン指定並び ::= 
    スカラー型 '*' 
    | 
    引数パターン指定(',' 引数パターン指定)* ',' スカラー型 '*'

宣言本体

プロファイル ::= 型 '->' 型 (',' 型 '->' 型)*

大域脱出宣言 ::= (throws節 | breaks節)*
資源使用宣言 ::= (reads節 | updates節 | uses節)*

throws節  ::= 'throws' 例外型
breaks節 ::= 'breaks' 出力型

reads節 ::= 'reads' 資源名
updates節 ::= 'updates' 資源名 
uses節  ::= 'uses' 資源名

例外型 ::= 型 | '[' 型並び ']'
出力型 ::= 型 | '[' 型並び ']'
型並び ::= 空 | 型 (',' 型)*

資源名 ::= 名前 | '[' 名前並び ']'
名前並び ::= 空 | 名前 (',' 名前)*

/* 型宣言は省略 */

// オブジェクトの指定されたフィールドの値を取得
command getpv {} [string] :: anyObject -> any;

// 配列の指定された項目を取得
command geti {} [integer(minumum = 0)] :: anyArray -> any;

// オブジェクトから指定されたフィールドだけを抜き取って
// 新しいオブジェクトを作る
command selecto {} [string, string*] 
        :: anyObject -> anyObject;

// 配列から指定された項目だけを抜き取って
// 新しい配列を作る
command selecta {} [integer(minimum = 0), integer(minimum = 0)*] 
        :: anyArray -> anyArray;

// オブジェクトのマージ
command merge {}  
        :: (list[anyObject] | object {*:anyObject}) -> anyObject;

// 連接
command concat {}  
        :: list[string] -> string, list[anyArray] -> anyArray;

// JSONデータのechoコマンド
command jecho {} [string] :: void -> _T;

// なにもしない
command pass {} [] :: _T -> _T;

// データベースを引いて商品情報
command getiteminfo {} [string] :: 
           void -> ItemInfo
           reads mysql;

// リダイレクト
command redirect {} [string] :: void -> never 
                               breaks WebOutput;


[追記]

補足と注意

型変数を含む型表現

型 ::= 型変数 | 任意のJSON型表現 | 'never'

「任意のJSON型表現」のなかに型変数を入れてもいいか? 例えば、list [_T] とか array [_S, _T*] はいいのか? 曖昧でした。最終的に扱わざるをえないでしょうが、まー、ボチボチ考えるでもいいかと。

ユーザー定義スカラー型

スカラー型 ::= integer型 | number型 | string型 | boolean型 | null型
             | 簡易列挙型
             | 'anyScalar'

ユーザー定義のスカラー型もいずれ認めます。例えば、filename型のような型を認めないと不便です。が、とりあえずは組み込みスカラー型からはじめます。

型変数の具体的な形

型変数 ::= アンダスコアからはじまる名前

単純な名前の定義は以下のとおりです(「Jcentric型システムの宣言スタイル・スキーマ構文」参照)。

名前 ::= [a-zA-Z][a-zA-Z0-9]*

従って:

型変数 ::= '_'[a-zA-Z][a-zA-Z0-9]*

コマンド名とオプション名が曖昧

コマンド名 ::= いずれ定義する(当面、単純な名前)
オプション名 ::= いずれ定義する(当面、任意の文字列リテラル)

このへんがハッキリしないのは、「同じ名前って何だよ!? 名前のポータビリティ問題」で述べたような事情が絡んでいます。

プロファイル

プロファイル ::= 型 '->' 型 (',' 型 '->' 型)*

これは意味論がハッキリしない。ユニオン型で片づけるわけにもいかないし。

{}との省略

{}とは、省略可能にするかもしれません。省略しても特に問題はないでしょう。

引数変数名

プレーン引数(位置引数)は名前を持ちません。しかし、名前を持たせておくと、変数の意味を伝える助けになります。また、引数の値をプロファイルや宣言節内で引用するときにも便利でしょう。現状、どういう書き方がいいか分かりません。

統一性

JSONリテラル構文、スキーマ定義の構文、コマンド宣言の構文、Catyスクリプトの構文をなるべく一致させたいわけですが、目的が違うので同一構文にするのは無理です。似ていた方がいいとは思うのですが、なまじ似ている(が少し違う)と混乱を引き起こすかもしれません。あー、バランスが難しい。

[/追記]