syntax-switch はコントロール コンストラクトで、その構文は
switch の構文に似ています。ただし、各
case ステートメントが構文パターンである点が異なります。
パターン マッチングや
CurlSource オブジェクトの分解の際に役に立つフォームを提供します。これは、マクロ作成用に特別に設計されていますが、その使用をマクロ定義内に制限する必要はありません。
source-object は各
pattern に対して順番に照合されます。最初に一致する
pattern に対して、対応する
statements が実行されます。このとき、名前付きの各サブパターンに定義されたローカル変数が使用されます。一致するケース式がない場合、
else 句が存在すればそれに続く
statements が実行されます。
must-match? が
true に指定され、一致するパターンがない場合、
syntax-switch は
SyntaxError をスローします。
must-match? が true の場合、
else 句は許可されません。
syntax-switch は、どこまで進んでからパターン一致に失敗したかを示すなどの、意味のある構文エラーの生成を自発的に試みます。これは、
do が欠落しているような、簡単な問題を見つけるには十分です。ただし、既定の自発的なエラー生成では、すべての状況、特に他のエラー生成方法がある場合でも、意味のあるエラー メッセージを提供できないという可能性があります。
pattern は、単純パターンを表す識別子、または複合パターンを記述するプレフィックス式のいずれかで構成されます。
pattern template は、疑問符 (
?) でエスケープする一連のリテラル ソース コードから構成されます。これは、下記で説明されています。
次は単純な
pattern として選択可能なものです。
expression
単一の Curl 式に一致させます。この場合一致する中で一番大きな式が実行されます。
このパターンに名前が付けられている場合、その名前付きのソース コード オブジェクトは、
Parsed 型のオブジェクトになります。
関連パターン expressions では、ゼロ個以上の一連の式との一致になります。
statement
単一の Curl ステートメントに一致させます。この場合、解析可能な最も大きなステートメントが実行されます。
Curl のステートメントは式と同じですが、ステートメントでは let および set 式の特別な解析ルールを呼び出し、暗黙的な Curl ブラケットでこれらを囲む点が異なります。
このパターンに名前が付けられている場合、その名前付きのソース コード オブジェクトは、
Parsed 型のオブジェクトになります。
関連パターン statements は、ゼロ個以上の式のシーケンスとの一致になります。
class-member
Curl のひとつのクラスメンバとマッチします。
クラスメンバは、トップレベルで使用できるもの (フィールド、クラス変数、クラスプロシージャ、メソッド、コンストラクタ、ファクトリ、ゲッター、セッター、オプション) として、定義されます。
このパターンに名前が付けられている場合、その名前付きのソース コード オブジェクトは、
Parsed 型のオブジェクトになります。
関連パターン class-members は、ゼロ個以上の一連の識別子との一致になります。
identifier
hello などの任意の Curl 識別子に一致させます。
このパターンに名前が付けられている場合、その名前付きのソース コード オブジェクトは、
Identifier 型のオブジェクトになります。
関連パターン identifiers は、ゼロ個以上の一連の識別子との一致になります。
text
テキスト文字のシーケンスを、次の Curl ブラケット式まで一致させます。これは、テキスト プロシージャが引数を解析する方法と同じです。このパターンはすべての空白を保存し、バックスラッシュ エスケープを処理します。
このパターンに名前が付けられている場合、その名前付きのソース コード オブジェクトは、
BaseText 型のオブジェクトになります。
contents プロパティにアクセスすると、
StringInterface としてその内容を取得できます。未処理のバックスラッシュ エスケープが含まれるテキストは、
get-text メソッドを呼び出して取得できます。
関連パターン texts は、ゼロ個以上の一連のテキストとの一致になります。
token
7、+、foo、または "a string literal" などの単一の Curl トークンに一致させます。{something x, y} などのプレフィックス式は、単一トークンとしてカウントされることに注意してください。これは、プレフィックス式の内容に対するトークン化ルールが、通常、式の先頭に応じて適用されるからです。たとえば、{text hello 1.2.3} の内容は文字列として解析され、1.2.3 は有効なコード トークンではありません。
関連パターン tokens は、ゼロ個以上の一連のトークンとの一致になります。
verbatim
残りのソース コードに一致させ、コード トーカナイザが保持しない空白やその他の情報を保持します。このパターンは最後に配置する必要があります。
このパターンをコードに使用するのは、tokens または statements に比べて効率的ではないため、通常は未加工コードを解析する場合にのみ使用します。
このパターンに名前が付けられている場合、その名前付きのソース コード オブジェクトは、
CurlSource 型のオブジェクトになります。
verbatim では残りのソース コードを消費してしまうため、verbatims パターンはありません。
複合パターンを次に示します。
{pattern pattern-template}
これは、pattern template を単一の pattern に集める単純なグループ化演算子です。
次に例を示します。
{pattern while ?predicate:expression do ?body:statements}
literal
isa で指定された型の単一 Curl リテラルに一致させます。一致する式には、7、true、null、"a string literal" などを含めることができます。
このパターンに名前が付けられている場合、その名前付きのソース コード オブジェクトは、
Literal 型のオブジェクトになります。
次に例を示します。
{pattern include ?filename:{literal String}}
{one-of pattern1 [, pattern2...]}
これは、リストされたパターンの 1 つに一致させます。この場合、リストで最初に一致するパターンが優先されます。
one-of はオペランドとしてシーケンス pattern template ではなく pattern を受け取る唯一の複合パターンです。これは、カンマがオペランドを one-of に区切るものか、単にパターンの一部であるのかを明瞭にするためです。
次に例を示します。
{one-of
{pattern above},
{pattern below},
{pattern to},
{pattern downto}
}
{optional pattern-template}
これは、pattern-template に一致させるか、または何にも一致させません。(前者が優先されます)。
次に例を示します。
{pattern
while ?tag-expr:{optional tag = ?:identifier,}
?predicate:expression
do
?body:statements
}
optional は次に相当します。
{one-of {pattern pattern-template},{pattern}}
{sequence pattern-template}
これは、ゼロ個以上の pattern-template のパターンに一致させます。 この場合、できるだけ少ない (つまり欲張りではない) 一致が優先されます。
単純パターンの多くには、複数を示す省略形フォームが存在します。たとえば、statements は {sequence ?:statement} に相当します。
sequence パターンが名付けられている場合、一致により生成されたオブジェクトは for ループですべての一致を参照できるコンテナになります。size メソッドにアクセスすることにより、コンテナのサイズを取得できます。
次に、0 個以上のキーワード引数 (各引数の後にカンマを持つ) に一致させる例を示しています。
{pattern ?keywords:{sequence ?:identifier = ?:expression,}}
sequence は次に相当します。
{bounded-sequence 0, infinity, pattern-template}
{comma-sequence pattern-template}
これは、カンマで区切られているゼロ個以上の pattern-template のパターンに一致させます。できるだけ少ない (つまり欲張りでない) 一致が優先されます。
comma-sequence パターンが名付けられている場合、一致により生成されたオブジェクトは for ループですべての一致を参照できるコンテナになります。繰り返し処理ではカンマは表示されませんが、コンテナが expand-template 呼び出しで代入されると表示されます。size メソッドにアクセスすることにより、コンテナのサイズを取得できます。
次に、0 個以上の引数 (カンマで区切られた) に一致させる例が示されています。
{pattern ?arguments:{comma-sequence ?:expression}}
comma-sequence は次に相当します。
{bounded-comma-sequence
0, infinity, pattern-template
}
{bounded-sequence min, max,
pattern-template
}
これは、pattern-template で min と max 数の間の一致を実行します。できるだけ少ない (つまり欲張りでない) 一致が優先されます。範囲が必要ない場合は infinity を使用します。
bounded-sequence パターンが名付けられている場合、一致により生成されたオブジェクトは for ループですべての一致を参照できるコンテナになります。size メソッドにアクセスすることにより、コンテナのサイズを取得できます。
たとえば、次の例では 2 つ以上の識別子のシーケンスに一致させます。
{bounded-sequence 2, infinity, ?:identifier}
{bounded-comma-sequence min, max,
pattern-template
}
これは、 pattern-template で min と max 数の間の一致を実行します。パターンはそれぞれカンマで区切られています。できるだけ少ない (つまり欲張りでない) 一致が優先されます。
bounded-comma-sequence パターンが名付けられている場合、一致により生成されたオブジェクトは for ループですべての一致を参照できるコンテナになります。繰り返し処理ではカンマは表示されませんが、コンテナが expand-template 呼び出しで代入されると表示されます。size メソッドにアクセスすることにより、コンテナのサイズを取得できます。
たとえば、少なくとも 2 つのカンマで区切られた式に一致するパターンを必要とする場合、次のように記述します。
{bounded-comma-sequence 2, infinity, ?:expression}
pattern template は、完全一致を必要とする標準コードのシーケンスで、疑問符 (
?) でエスケープされた
pattern が配置されています。
たとえば、次の
pattern、
{pattern alpha ?id:identifier beta}の内容は、識別子
alpha、続いて任意の識別子、最後に識別子
beta との一致を示します。
次の
pattern は上記と同じ一致ですが、
alpha と
beta の間にゼロ個以上の任意の数の識別子が入ります。
{pattern alpha ?ids:{sequence ?:identifier} beta}最初の
pattern template では
?id:identifier であることに注意してください。この例では、
id がパターンに
名前を付けることにより、後続のコードがこのパターンに一致するソース コードにアクセスできるようになります。同様に 2 番目の例では、
?ids:{sequence ?:identifier} が一致項目の配列を生成します。
名付けられたパターンは次のように指定されます。
{syntax-switch source
case {pattern alpha ?id:identifier beta} do
{output "I matched identifier ", id.name}
else
{error "no match"}
}
ケースの本体で、
id が一致するソース コードにどのようにバインドされているかに注意してください。
通常、名付けられたパターンは、新しいソース コード オブジェクトを生成するために
expand-template に渡されます。ただし、高度なコードが
CurlSource のメソッドとそのサブクラスを使用し、さらに解析を実行する場合があります。
シーケンス パターンに一致させる場合、変数はすべての一致シーケンスを含むコンテナにバインドされます。このコンテナは、
for を使用してループできます。
{syntax-switch source
case {pattern alpha ?ids:identifiers beta} do
{output "I matched ", ids.size, " identifiers"}
case {pattern whoops} do
{output "someone said whoops!"}
else
{error "no match"}
}
前述の例で使用された
{sequence ?:identifier} に対して、この例では
identifiers 省略形が使用されていることに注意してください。これらは同じものです。
パターンの命名はオプションです。一致するソースに名前を付ける必要がない場合は名前を省略します。
{pattern alpha ?:identifier beta}名付けられたパターンは、1 つだけの一致が保証されない
sequence、
optional、あるいは その他のコンストラクト内には表示されない可能性があります。
リテラル疑問符に一致させるには、
{pattern ??} のように
? 文字を 2 つ並べます。
some-function? のような識別子の一部である疑問符は、識別子の一部と見なされ、別々に一致させることはできないことに注意してください。