5.1 構文文法と字句文法
5.1.1 文脈自由文法
文脈自由文法は、いくつかの生成規則から構成されます。各生成規則は、左辺として、非終端記号と呼ばれる抽象的な記号を持ち、右辺として、0個以上の非終端記号と終端記号の列を持ちます。各文法の終端記号は、指定されたアルファベットから選ばれます。
連鎖生成規則とは、その右辺に、0個以上の終端記号とともに、ちょうど一つの非終端記号を持つ生成規則です。
与えられた文脈自由文法は、開始記号と呼ばれる特定の単一の非終端記号からなる文から始めることで、ある言語を規定します。すなわち、列内の任意の非終端記号を、その非終端記号を左辺とする生成規則の右辺に繰り返し置き換えることによって得られる、終端記号のすべての可能な列の集合(無限の場合もあります)です。
5.1.2 字句文法と RegExp 文法
ECMAScript の字句文法は、箇条 12 に示されています。この文法の終端記号は、11.1 で定義される SourceCharacter の規則に適合する Unicode コードポイントです。この文法は、開始記号 InputElementDiv、InputElementTemplateTail、InputElementRegExp、InputElementRegExpOrTemplateTail、または InputElementHashbangOrRegExp から始まり、そのようなコードポイントの列が入力要素の列に変換される方法を記述する、一連の生成規則を定義します。
空白とコメント以外の入力要素は、ECMAScript の構文文法の終端記号となり、ECMAScript のトークンと呼ばれます。これらのトークンは、ECMAScript 言語の予約語、識別子、リテラル、および区切り記号です。また、行終端文字はトークンとはみなされませんが、入力要素の流れの一部となり、自動セミコロン挿入(12.10)の処理を導きます。単なる空白と単一行コメントは破棄され、構文文法の入力要素の流れには現れません。MultiLineComment(すなわち、複数行にまたがるかどうかにかかわらず、/*…*/ という形式のコメント)も、行終端文字を含まない場合は同様に単に破棄されます。しかし、MultiLineComment が一つ以上の行終端文字を含む場合は、単一の行終端文字に置き換えられ、構文文法の入力要素の流れの一部となります。
ECMAScript の RegExp 文法は、22.2.1 に示されています。この文法も、SourceCharacter で定義されるコードポイントを終端記号とします。この文法は、開始記号 Pattern から始まり、コードポイントの列が正規表現パターンに変換される方法を記述する、一連の生成規則を定義します。
字句文法と RegExp 文法の生成規則は、区切り記号として2つのコロン“::”を持つことで区別されます。字句文法と RegExp 文法は、一部の生成規則を共有します。
5.1.3 数値文字列文法
数値文字列文法は、7.1.4.1 に示されています。この文法は、SourceCharacter を終端記号とし、開始記号 StringNumericLiteral から始めて、String を数値に変換するために使用されます(これは、数値リテラルの字句文法に似ていますが、異なるものです)。
数値文字列文法の生成規則は、区切り記号として3つのコロン“:::”を持つことで区別され、ソーステキストの解析には使用されません。
5.1.4 構文文法
ECMAScript の構文文法は、箇条 13 から 16 に示されています。この文法は、字句文法で定義された ECMAScript のトークンを終端記号とします(5.1.2)。この文法は、2つの選択可能な開始記号 Script と Module から始まり、トークンの列が、ECMAScript プログラムの構文的に正しい独立した構成要素を形成する方法を記述する、一連の生成規則を定義します。
コードポイントの流れを ECMAScript の Script または Module として解析するときは、まず字句文法を繰り返し適用することで、それを入力要素の流れに変換します。次に、構文文法を一度適用して、この入力要素の流れを解析します。入力要素の流れの中のトークンを、トークンを一つも残さずに、開始非終端記号(Script または Module)の単一のインスタンスとして解析できない場合、入力の流れには構文エラーがあります。
解析が成功すると、解析木が構築されます。これは、各ノードが Parse Node である、根を持つ木構造です。各 Parse Node は、文法内の記号のインスタンスであり、その記号から導出できるソーステキストの範囲を表します。ソーステキスト全体を表す解析木の根ノードは、その解析の開始記号のインスタンスです。Parse Node が非終端記号のインスタンスである場合、それは、その非終端記号を左辺に持つ、いずれかの生成規則のインスタンスでもあります。さらに、その生成規則の右辺の各記号に一つずつ対応する、0個以上の子を持ちます。各子は、対応する記号のインスタンスである Parse Node です。
新しい Parse Node は、パーサーの呼出しごとに生成され、同一のソーステキストの解析であっても、解析間で再利用されることはありません。Parse Node が同じ Parse Nodeであるとみなされるのは、ソーステキストの同じ範囲を表し、同じ文法記号のインスタンスであり、かつ同じパーサー呼出しによって生成された場合に限られます。
注 1
同じ String を複数回解析すると、異なる Parse Node が生成されます。たとえば、次を考えます。
let str = "1 + 1;";
eval(str);
eval(str);
eval の各呼出しは、str の値を ECMAScript のソーステキストに変換し、独立した解析を実行して、それぞれ別個の Parse Node の木を作成します。各解析が、同じ String 値から得られたソーステキストに対して実行されても、それらの木は異なります。
注 2Parse Node は仕様上の構成物であり、実装が類似のデータ構造を使用する必要はありません。
構文文法の生成規則は、区切り記号として一つだけのコロン“:”を持つことで区別されます。
箇条 13 から 16 に示される構文文法は、どのトークン列が正しい ECMAScript の Script または Module として受理されるかを完全に説明するものではありません。特定の追加のトークン列も受理されます。すなわち、列内の特定の位置(たとえば、行終端文字の前)にセミコロンを追加するだけで、その文法によって記述されるようになる列です。さらに、文法によって記述される特定のトークン列も、特定の“不適切な”位置に行終端文字が現れる場合は、受理可能とはみなされません。
特定の場合には、曖昧さを避けるため、構文文法は、有効な ECMAScript の Script または Module を形成しないトークン列を許可する、一般化された生成規則を使用します。たとえば、この手法は、オブジェクトリテラルとオブジェクトの分割代入パターンに使用されます。そのような場合には、受理可能なトークン列をさらに制限する、より制約の強い補助文法が提供されます。通常、早期エラー規則は、そのうえで、特定のコンテキストにおいて“p は n を被覆しなければならない”と規定します。ここで、p は Parse Node(一般化された生成規則のインスタンス)、n は補助文法の非終端記号です。これは、以下を意味します。
- p またはその子孫には、早期エラー規則を適用しません。
- 最初に p と一致したトークン列を、n を開始記号として再度解析します。n が文法パラメーターを取る場合、それらは、p が最初に解析されたときに使用された値と同じ値に設定されます。
- トークン列を、トークンを一つも残さずに n の単一のインスタンスとして解析できる場合は、次のようにします。
- その n のインスタンス(与えられた p に対して一意の Parse Node)を、“p によって被覆される n”と呼びます。
- “被覆しなければならない”のさらなる適用によって修正されるとおりに、p によって被覆される n とその子孫に、早期エラー規則を適用します。
- そうでない場合(解析が失敗した場合)は、早期構文エラーです。
5.1.5 文法の表記
5.1.5.1 終端記号
ECMAScript の文法では、一部の終端記号は 等幅 フォントで示されます。これらは、記述されたとおりにソーステキスト内に現れなければなりません。この方法で指定されるすべての終端記号のコードポイントは、他の Unicode 範囲の外見が似たコードポイントではなく、基本ラテン文字ブロック内の対応する Unicode コードポイントとして解釈されます。終端記号内のコードポイントは、\ UnicodeEscapeSequence によって表現できません。
終端記号が個々の Unicode コードポイントである文法(すなわち、字句文法、RegExp 文法、および数値文字列文法)では、生成規則内に現れる複数の等幅のコードポイントの連続は、同じコードポイントの列をそれぞれ独立した終端記号として記述したものの、単なる短縮表記です。
たとえば、生成規則:
HexIntegerLiteral ::
0x
HexDigits
は、次の短縮表記です。
HexIntegerLiteral ::
0
x
HexDigits
一方、構文文法では、等幅のコードポイントの連続は、単一の終端記号です。
終端記号には、ほかに2つの形式があります。
5.1.5.2 非終端記号と生成規則
非終端記号は、斜体で示されます。非終端記号の定義(“生成規則”とも呼ばれます)は、定義する非終端記号の名前と、それに続く一つ以上のコロンによって導入されます。(コロンの数は、その生成規則がどの文法に属するかを示します。)その後の行には、その非終端記号の右辺の選択肢が一つ以上続きます。たとえば、構文定義:
WhileStatement :
while
(
Expression
)
Statement
は、非終端記号 WhileStatement が、トークン while、それに続く左丸括弧トークン、続く Expression、続く右丸括弧トークン、続く Statement を表すことを示します。ここに現れる Expression と Statement は、それ自体が非終端記号です。別の例として、構文定義:
ArgumentList :
AssignmentExpression
ArgumentList
,
AssignmentExpression
は、ArgumentList が、単一の AssignmentExpression、または ArgumentList にカンマと AssignmentExpression が続くもののいずれかを表せることを示します。この ArgumentList の定義は再帰的です。つまり、それ自身を用いて定義されています。その結果、ArgumentList は、カンマで区切られた任意の正の個数の引数を含むことができ、各引数式は AssignmentExpression です。このような非終端記号の再帰的な定義は、一般的に使用されます。
5.1.5.3 省略可能な記号
終端記号または非終端記号の後に現れることがある下付きの接尾辞“opt”は、省略可能な記号を示します。省略可能な記号を含む選択肢は、実際には、その省略可能な要素を省いたものと含めたものという、2つの右辺を指定します。これは、次の定義:
VariableDeclaration :
BindingIdentifier
Initializeropt
が、次の便利な省略表記であることを意味します。
VariableDeclaration :
BindingIdentifier
BindingIdentifier
Initializer
また、次の定義:
ForStatement :
for
(
LexicalDeclaration
Expressionopt
;
Expressionopt
)
Statement
は、次の便利な省略表記です。
ForStatement :
for
(
LexicalDeclaration
;
Expressionopt
)
Statement
for
(
LexicalDeclaration
Expression
;
Expressionopt
)
Statement
これは、さらに次の省略表記です。
ForStatement :
for
(
LexicalDeclaration
;
)
Statement
for
(
LexicalDeclaration
;
Expression
)
Statement
for
(
LexicalDeclaration
Expression
;
)
Statement
for
(
LexicalDeclaration
Expression
;
Expression
)
Statement
したがって、この例では、非終端記号 ForStatement は、実際には4つの右辺の選択肢を持ちます。
5.1.5.4 文法パラメーター
生成規則は、“[parameters]”という形式の下付きの注記によってパラメーター化できます。この注記は、生成規則によって定義される非終端記号の接尾辞として現れる場合があります。“parameters”は、単一の名前、またはカンマで区切られた名前のリストです。パラメーター化された生成規則は、パラメーター化された非終端記号に、各パラメーター名の前にアンダースコアを付けて追加したすべての組合せを定義する、生成規則の集合の短縮表記です。これは、次の定義:
StatementList[Return] :
ReturnStatement
ExpressionStatement
が、次の便利な省略表記であることを意味します。
StatementList :
ReturnStatement
ExpressionStatement
StatementList_Return :
ReturnStatement
ExpressionStatement
また、次の定義:
StatementList[Return, In] :
ReturnStatement
ExpressionStatement
は、次の省略表記です。
StatementList :
ReturnStatement
ExpressionStatement
StatementList_Return :
ReturnStatement
ExpressionStatement
StatementList_In :
ReturnStatement
ExpressionStatement
StatementList_Return_In :
ReturnStatement
ExpressionStatement
複数のパラメーターは、組合せの数に応じた数の生成規則を生じさせますが、完全な文法の中で必ずしもそのすべてが参照されるとは限りません。
生成規則の右辺にある非終端記号への参照も、パラメーター化できます。たとえば:
StatementList :
ReturnStatement
ExpressionStatement[+In]
は、次のように記述することと同等です。
StatementList :
ReturnStatement
ExpressionStatement_In
また:
StatementList :
ReturnStatement
ExpressionStatement[~In]
は、次と同等です。
StatementList :
ReturnStatement
ExpressionStatement
非終端記号への参照は、パラメーターリストと“opt”接尾辞の両方を持つことができます。たとえば:
VariableDeclaration :
BindingIdentifier
Initializer[+In]opt
は、次の省略表記です。
VariableDeclaration :
BindingIdentifier
BindingIdentifier
Initializer_In
右辺の非終端記号への参照において、パラメーター名の前に“?”を付けると、そのパラメーター値は、現在の生成規則の左辺の記号への参照に、そのパラメーター名が現れるかどうかに依存します。たとえば:
VariableDeclaration[In] :
BindingIdentifier
Initializer[?In]
は、次の省略表記です。
VariableDeclaration :
BindingIdentifier
Initializer
VariableDeclaration_In :
BindingIdentifier
Initializer_In
右辺の選択肢の先頭に“[+parameter]”が付いている場合、その選択肢は、その生成規則の非終端記号を参照するときに、指定されたパラメーターが使用された場合にのみ利用できます。右辺の選択肢の先頭に“[~parameter]”が付いている場合、その選択肢は、その生成規則の非終端記号を参照するときに、指定されたパラメーターが使用されなかった場合にのみ利用できます。これは、次の定義:
StatementList[Return] : [+Return]
ReturnStatement
ExpressionStatement
が、次の省略表記であることを意味します。
StatementList :
ExpressionStatement
StatementList_Return :
ReturnStatement
ExpressionStatement
また、次の定義:
StatementList[Return] : [~Return]
ReturnStatement
ExpressionStatement
は、次の省略表記です。
StatementList :
ReturnStatement
ExpressionStatement
StatementList_Return :
ExpressionStatement
5.1.5.5 one of
文法定義において、コロンの後に“one of”という語が続く場合、それは、次の行または複数の行にある各終端記号が、それぞれ定義の選択肢であることを示します。たとえば、ECMAScript の字句文法には、次の生成規則が含まれます。
NonZeroDigit :: one of 1 2 3 4 5 6 7 8 9
これは、次の便利な省略表記にすぎません。
NonZeroDigit ::
1
2
3
4
5
6
7
8
9
5.1.5.6 [empty]
生成規則の右辺として“[empty]”という表記が現れる場合、それは、その生成規則の右辺が終端記号も非終端記号も含まないことを示します。
5.1.5.7 先読み制約
生成規則の右辺に“[lookahead = seq]”という表記が現れる場合、それは、トークン列 seq が、直後の入力トークン列の接頭部分である場合にのみ、その生成規則を使用できることを示します。同様に、“[lookahead ∈ set]”は、set をトークン列の有限かつ空でない集合として、set のいずれかの要素が直後のトークン列の接頭部分である場合にのみ、その生成規則を使用できることを示します。便宜上、この集合は非終端記号として記述することもでき、その場合は、その非終端記号が展開され得るすべてのトークン列の集合を表します。その非終端記号が無限に多くの異なるトークン列に展開され得る場合、それは編集上の誤りとみなされます。
これらの条件は否定できます。“[lookahead ≠ seq]”は、seq が直後の入力トークン列の接頭部分ではない場合にのみ、それを含む生成規則を使用できることを示します。“[lookahead ∉ set]”は、set のどの要素も直後のトークン列の接頭部分ではない場合にのみ、その生成規則を使用できることを示します。
例として、次の定義が与えられている場合:
DecimalDigit :: one of 0 1 2 3 4 5 6 7 8 9
DecimalDigits ::
DecimalDigit
DecimalDigits
DecimalDigit
次の定義:
LookaheadExample ::
n
[lookahead ∉ { 1, 3, 5, 7, 9 }]
DecimalDigits
DecimalDigit
[lookahead ∉ DecimalDigit]
は、文字 n に続いて、最初の数字が偶数である一つ以上の10進数字が現れるもの、または、その後に別の10進数字が続かない単一の10進数字のいずれかと一致します。
これらの表記を構文文法で使用する場合、後続のトークンを決定するには、後の位置でどの字句開始記号を使用するかを知る必要があるため、直後のトークン列を一意に特定できない場合があることに注意してください。したがって、これらを構文文法で使用する場合、使用する字句開始記号の選択によって、seq が結果のトークン列の接頭部分になるかどうかが変わり得るならば、トークン列 seq が先読み制約に現れることは(列の集合の一部として現れる場合も含めて)、編集上の誤りとみなされます。
構文文法の生成規則の右辺に“[no LineTerminator here]”という表記が現れる場合、それは、その生成規則が制限付き生成規則であることを示します。すなわち、入力の流れの指定された位置に LineTerminator が現れる場合、その生成規則を使用できません。たとえば、生成規則:
ThrowStatement :
throw
[no LineTerminator here]
Expression
;
は、スクリプト内で throw トークンと Expression の間に LineTerminator が現れる場合、その生成規則を使用できないことを示します。
制限付き生成規則によって LineTerminator の存在が禁止されていない限り、入力要素の流れの中の連続する任意の2つのトークンの間には、スクリプトの構文上の受理可能性に影響を与えることなく、任意の個数の LineTerminator が現れてもかまいません。
5.1.5.9 but not
生成規則の右辺では、“but not”という語句を使用し、その後に除外する展開を示すことで、特定の展開を許可しないことを指定できます。たとえば、生成規則:
Identifier ::
IdentifierName but not ReservedWord
は、同じコードポイント列で ReservedWord を置き換えることができないという条件のもとで、非終端記号 Identifier を、IdentifierName を置き換えられる任意のコードポイント列で置き換えられることを意味します。
5.1.5.10 記述的な語句
最後に、すべての選択肢を列挙することが実用的ではない場合、一部の非終端記号は、サンセリフ体の記述的な語句によって説明されます。
SourceCharacter ::
any Unicode code point
5.2 アルゴリズムの規約
この仕様では、アルゴリズムの手順を規定するために、番号付きリストをよく使用します。これらのアルゴリズムは、ECMAScript 言語の構文要素に要求される意味論を正確に規定するために使用されます。これらのアルゴリズムは、特定の実装手法の使用を示唆することを意図していません。実際には、ある機能を実装するために、より効率的なアルゴリズムが存在する場合があります。
アルゴリズムは、カンマで区切られた順序付きの別名の列によって明示的にパラメーター化できます。これらの別名は、その位置に渡された引数を参照するために、アルゴリズムの手順内で使用できます。省略可能なパラメーターは、角括弧で囲んで([ , name ])示され、アルゴリズムの手順内では必須パラメーターと違いはありません。パラメーターリストの末尾には、先頭に省略記号を付けて(, ...name)示される残余パラメーターが現れる場合があります。残余パラメーターは、必須パラメーターと省略可能なパラメーターの後に渡されるすべての引数を、List にまとめます。そのような追加の引数がない場合、その List は空です。
アルゴリズムの手順は、順番に実行される副手順に細分化できます。副手順は字下げされ、それ自体をさらに字下げされた副手順に分割することもできます。副手順を識別するために階層的な番号付けの規約を使用し、第1階層の副手順には小文字のアルファベット、第2階層の副手順には小文字のローマ数字を付けます。3階層を超える階層が必要な場合は、この規則を繰り返し、第4階層では数字を使用します。たとえば:
- 最上位の手順
- 副手順。
- 副手順。
- 副手順の副手順。
- 副手順の副手順の副手順
- 副手順の副手順の副手順の副手順
- 副手順の副手順の副手順の副手順の副手順
手順または副手順は、その副手順の実行条件となる“もし”述語として記述される場合があります。この場合、副手順は、その述語が真である場合にのみ適用されます。手順または副手順が“そうでなければ”という語で始まる場合、それは、同じ階層の直前の“もし”述語の手順を否定した述語です。
手順は、その副手順を反復して適用することを指定するために、“それぞれについて”または“繰り返す”で始まる場合があります。
“表明:”で始まる手順は、そのアルゴリズムの不変条件を表明します。このような表明は、そうでなければ暗黙となるアルゴリズムの不変条件を明示するために使用されます。同様に、“注記:”で始まる手順は、近くの手順に関連する文脈を提供します。表明の手順と注記の手順は、厳密に参考情報であり、追加の意味論的要件を課すものではないため、実装が検査する必要はありません。
アルゴリズムの手順は、“x を someValue とする”という形式を使用して、任意の値に対する名前付きの別名を宣言できます。これらの別名は、x と someValue の両方が同じ基礎データを参照し、どちらかへの変更が両方から見えるという点で、参照に似ています。この参照のような動作を避けたいアルゴリズムの手順は、右辺のコピーを明示的に作成するべきです。“x を someValue のコピーとする”は、someValue の浅いコピーを作成します。
宣言された別名は、以降の任意の手順から参照できますが、その別名の宣言より前の手順から参照してはなりません。別名は、“x を someOtherValue に設定する”という形式を使用して変更できます。
5.2.1 評価順序
アルゴリズムの手順に複雑な式が現れる場合、それらは左から右、内側から外側の順に評価されるものとして解釈されます。たとえば、次の手順:
- A(B(), C.[[D]]) + E(F()) を返す。
は、次と同等です。
- tmp1 を B() とする。
- tmp2 を C.[[D]] とする。
- tmp3 を A(tmp1, tmp2) とする。
- tmp4 を F() とする。
- tmp5 を E(tmp4) とする。
- tmp6 を tmp3 + tmp5 とする。
- tmp6 を返す。
ここで、各 tmpN の別名は一時的なものであり、これらの手順内でのみ参照できます。
5.2.2 抽象操作
この仕様の複数の箇所で利用しやすくするため、一部のアルゴリズムには名前が付けられ、パラメーター化された関数形式で記述されており、他のアルゴリズム内から名前で参照できるようになっています。これらを抽象操作と呼びます。抽象操作は、通常、OperationName(arg1, arg2) のような関数適用形式で参照されます。一部の抽象操作は、クラスに似た仕様上の抽象化の、多態的にディスパッチされるメソッドとして扱われます。このようなメソッドに似た抽象操作は、通常、someValue.OperationName(arg1, arg2) のようなメソッド適用形式で参照されます。
5.2.3 構文指向操作
構文指向操作とは、名前付きの操作であり、その定義は、ECMAScript のいずれかの文法の一つ以上の生成規則にそれぞれ関連付けられたアルゴリズムから構成されます。複数の定義の選択肢を持つ生成規則は、通常、各選択肢に対して別個のアルゴリズムを持ちます。アルゴリズムが文法の生成規則に関連付けられている場合、その生成規則の選択肢に含まれる終端記号と非終端記号を、アルゴリズムのパラメーターであるかのように参照できます。このように使用される場合、非終端記号は、ソーステキストの解析時に実際に一致する定義の選択肢を指します。文法の生成規則、またはそこから導かれた Parse Node に一致するソーステキストとは、一致に関与した最初の終端記号の先頭から始まり、一致に関与した最後の終端記号の末尾で終わる、ソーステキストの部分です。
アルゴリズムが生成規則の選択肢に関連付けられている場合、その選択肢は、通常、“[ ]”の文法注記を一切付けずに示されます。このような注記は、その選択肢の構文上の認識にのみ影響し、選択肢に関連付けられた意味論には影響しないようにするべきです。
構文指向操作は、次のアルゴリズムの手順 1、3、および 4 の規約を使用して、解析ノードと、必要に応じてその他のパラメーターを伴って呼び出されます。
- status を SomeNonTerminal の SyntaxDirectedOperation とする。
- someParseNode を、あるソーステキストの解析結果とする。
- someParseNode の SyntaxDirectedOperation を実行する。
- 引数 "value" を使用して、someParseNode の SyntaxDirectedOperation を実行する。
明示的に別の規定がない限り、すべての連鎖生成規則は、その生成規則の左辺の非終端記号に適用され得るすべての操作について、暗黙の定義を持ちます。この暗黙の定義は、単に、同じ操作を、パラメーターがあれば同じパラメーターを使用して、連鎖生成規則の右辺の唯一の非終端記号に再適用し、その結果を返します。たとえば、あるアルゴリズムに“Block の Evaluation を返す”という形式の手順があり、次の生成規則があるとします。
Block :
{
StatementList
}
しかし、Evaluation 操作は、この生成規則にアルゴリズムを関連付けていないとします。その場合、Evaluation 操作には、次の形式の関連付けが暗黙に含まれます。
Runtime Semantics: Evaluation
Block :
{
StatementList
}
- StatementList の Evaluation を返す。
5.2.4 実行時意味論
実行時に呼び出さなければならない意味論を規定するアルゴリズムを、実行時意味論と呼びます。実行時意味論は、抽象操作または構文指向操作によって定義されます。
5.2.4.1 Completion ( completionRecord )
抽象操作 Completion。引数 completionRecord (完了レコード)。戻り値:完了レコード。 Completion Record が返されることを強調するために使用されます。 呼び出されると、次の手順を実行する。
- 表明: completionRecord は Completion Record である。
- completionRecord を返す。
5.2.4.2 スロー
アルゴリズムの手順における“スローする”という語は、ThrowCompletion を呼び出した結果を返すことの短縮表記です。たとえば:
- もし result.[[Error]] が none でなければ、result.[[Error]] をスローする。
は、次と同等です。
- もし result.[[Error]] が none でなければ、ThrowCompletion(result.[[Error]]) を返す。
特定の型の例外をスローすると記述されたアルゴリズムの手順は、スローするために、その型の例外を構築します。たとえば:
- TypeError 例外をスローする。
は、次と同等です。
- ThrowCompletion(新しく作成された TypeError オブジェクト) を返す。
5.2.4.3 Completion Record をアンラップするための短縮記法
接頭記号“?”と“!”は、Completion Record をアンラップする短縮記法として使用されます。“?”は、中断完了を呼出し元へ伝播させるため、または、そうでない場合に正常完了をアンラップするために使用されます。“!”は、Completion Record が正常であることを表明し、それをアンラップするために使用されます。形式的には、次の手順:
- result を ? record とする。
は、次と同等です。
- 表明: record は Completion Record である。
- もし record が中断完了であれば、record を返す。
- result を record.[[Value]] とする。
同様に、次の手順:
- result を ! record とする。
は、次と同等です。
- 表明: record は正常完了である。
- result を record.[[Value]] とする。
“?”または“!”がその他のコンテキストで使用される場合、まず、この規則を適用できるようになるまで、評価順序 で示される書換えを適用し、その後、この規則を適用します。たとえば、次の手順:
- AO(? Other()) を実行する。
は、次のように書き換えられます。
- tmp1 を Other() とする。
- tmp2 を ? tmp1 とする。
- AO(tmp2) を実行する。
これは、さらに次のように展開されます。
- tmp1 を Other() とする。
- 表明: tmp1 は Completion Record である。
- もし tmp1 が中断完了であれば、tmp1 を返す。
- tmp2 を tmp1.[[Value]] とする。
- AO(tmp2) を実行する。
5.2.4.4 暗黙の正常完了
Completion Record を返すと宣言された抽象操作内のアルゴリズム、およびすべての組込み関数内では、返される値をまず NormalCompletion に渡し、代わりにその結果を使用します。この規則は、Completion アルゴリズム内、または返される値がその手順内で Completion Record と明示されている場合には適用されません。該当する場合は、以下のとおりです。
このような抽象操作から、その他の手段で Completion Record が返される場合、それは編集上の誤りです。たとえば、これらの抽象操作内では:
- true を返す。
は、以下のいずれとも同じ意味です。
- NormalCompletion(true) を返す。
または:
- completion を NormalCompletion(true) とする。
- Completion(completion) を返す。
または:
- Completion Record { [[Type]]: normal, [[Value]]: true, [[Target]]: empty } を返す。
? 短縮記法の展開により、次の例は許可されることに注意してください。展開後の手順では、中断の場合には Completion を適用した結果が直接返され、正常の場合にはアンラップの後に暗黙の NormalCompletion の適用が行われるためです。
- ? completion を返す。
次の例は、Completion Record が、その手順で注記されることなく返されているため、編集上の誤りとなります。
- completion を NormalCompletion(true) とする。
- completion を返す。
5.2.5 静的意味論
文脈自由文法は、入力要素の流れが、評価可能な有効な ECMAScript の Script または Module を形成するかどうかを定義するすべての規則を表現するには、十分な表現力を持ちません。状況によっては、ECMAScript のアルゴリズム規約または文章による要件のいずれかを使用して表現される、追加の規則が必要です。このような規則は、常に文法の生成規則に関連付けられ、その生成規則の静的意味論と呼ばれます。
静的意味論の規則には名前があり、通常はアルゴリズムを使用して定義されます。名前付きの静的意味論の規則は、文法の生成規則に関連付けられます。複数の定義の選択肢を持つ生成規則は、通常、各選択肢について、適用される名前付きの静的意味論の規則ごとに、別個のアルゴリズムを持ちます。
静的意味論の規則の特別な種類として、早期エラー規則があります。早期エラー規則は、特定の文法の生成規則に関連付けられた早期エラー条件を定義します(箇条 17 を参照してください)。ほとんどの早期エラー規則の評価は、この仕様のアルゴリズム内で明示的には呼び出されません。適合実装は、Script または Module を最初に評価する前に、その Script または Module の解析に使用された生成規則のすべての早期エラー規則を検証しなければなりません。早期エラー規則のいずれかに違反する場合、その Script または Module は無効であり、評価できません。
5.2.6 数学的操作
この仕様では、次の種類の数値を参照します。
この仕様の記述では、数値の種類の違いを、下付きの接尾辞を使用して区別します。下付き文字 𝔽 は Number を指し、下付き文字 ℤ は BigInt を指します。下付きの接尾辞を持たない数値は、数学的値を指します。この仕様は、ほとんどの数値を10進数で表記します。また、0x に続いて 0-9 または A-F の数字を記述する形式の数値も、16進数の値として使用します。
一般に、この仕様が数値の種類を明示せずに、“y の長さ”や“4つの16進数字 ... で表される整数”などの語句で数値を参照する場合、その語句は数学的値を指します。Number 値または BigInt 値を参照する語句には、その旨が明示されます。たとえば、“… 内のコードポイント数に対応する Number 値”または“… に対応する BigInt 値”です。
この仕様で整数という用語を使用する場合、特に断りがない限り、整数の集合に属する数学的値を指します。この仕様で整数の Numberという用語を使用する場合、その数学的値が整数の集合に属する、有限の Number 値を指します。
+、×、=、および ≥ などの数値演算子は、オペランドの型によって決定される操作を指します。数学的値に適用される場合、それらの演算子は、通常の数学的操作を指します。拡張数学的値に適用される場合、それらの演算子は、拡張実数上の通常の数学的操作を指します。不定形は定義されておらず、この仕様内でのその使用は、編集上の誤りとみなすべきです。Number に適用される場合、それらの演算子は、IEEE 754-2019 内の対応する操作を指します。BigInt に適用される場合、それらの演算子は、BigInt の数学的値に適用される通常の数学的操作を指します。異なる型のオペランド(たとえば、Number と数学的値)に適用される数値演算子は定義されておらず、この仕様における編集上の誤りとみなすべきです。
数学値と Number または BigInt との間の変換は、この文書では常に明示的です。数学値または拡張数学値 x から Number への変換は、「x に対応する Number 値」または 𝔽(x) と表記され、6.1.6.1 で定義されます。整数 x から BigInt への変換は、「x に対応するBigInt 値」または ℤ(x) と表記されます。Number または BigInt x から数学値への変換は、「x の数学値」、または ℝ(x) と表記されます。+0𝔽 および -0𝔽 の数学値は数学値 0 です。有限でない値の数学値は定義されません。x の拡張数学値は、有限値については x の数学値であり、+∞𝔽 および -∞𝔽 についてはそれぞれ +∞ および -∞ です。NaN については定義されません。
数学関数 abs(x) は、x の絶対値を生成します。これは、x < 0 の場合は -x、そうでない場合は x 自身です。
数学関数 ln(x) は、x の自然対数を生成します。数学関数 log10(x) は、x の底10の対数を生成します。数学関数 log2(x) は、x の底2の対数を生成します。
数学関数 min(x1, x2, … , xN) は、x1 から xN のうち、数学的に最小のものを生成します。数学関数 max(x1, x2, ..., xN) は、x1 から xN のうち、数学的に最大のものを生成します。これらの数学関数の定義域と値域は、拡張数学的値です。
表記“x modulo y”(y は有限かつゼロでない必要があります)は、ある整数 q について abs(k) < abs(y) and x - k = q × y を満たし、y と同じ符号を持つ値 k(またはゼロ)を計算します。
“x を lower と upper の間に制限する結果”という語句は(ここで、x は拡張数学的値であり、lower と upper は lower ≤ upper を満たす数学的値です)、x < lower の場合は lower、x > upper の場合は upper、そうでない場合は x を生成します。
数学関数 floor(x) は、x 以下の最大の整数(+∞ に最も近い整数)を生成します。
注
floor(x) = x - (x modulo 1)。
数学関数 truncate(x) は、ゼロに向かって丸めることで x の小数部分を取り除きます。x < 0 の場合は -floor(-x)、そうでない場合は floor(x) を生成します。
数学関数 min、max、abs、floor、および truncate は、Number と BigInt に対して定義されていません。これらのメソッドを数学的値ではない引数で使用することは、この仕様における編集上の誤りとなります。
下限 a から上限 b までの区間とは、同じ数値型の数値の集合であり、無限の場合も、空の場合もあります。各境界は、包含または除外のいずれかとして記述され、両方として記述されることはありません。区間には、次の4種類があります。
- a(含む)から b(含む)までの区間は、a から b までの閉区間とも呼ばれ、a ≤ x ≤ b を満たす同じ数値型のすべての値 x を含み、それ以外の値を含みません。
- a(含む)から b(含まない)までの区間は、a ≤ x < b を満たす同じ数値型のすべての値 x を含み、それ以外の値を含みません。
- a(含まない)から b(含む)までの区間は、a < x ≤ b を満たす同じ数値型のすべての値 x を含み、それ以外の値を含みません。
- a(含まない)から b(含まない)までの区間は、a < x < b を満たす同じ数値型のすべての値 x を含み、それ以外の値を含みません。
たとえば、1(含む)から2(含まない)までの区間は、1を含み2を含まない、1と2の間のすべての数学的値から構成されます。区間を定義する目的では、-0𝔽 < +0𝔽 とします。したがって、たとえば、下限が +0𝔽 である閉区間は、+0𝔽 を含みますが、-0𝔽 は含みません。NaN が区間に含まれることはありません。
5.2.7 値の表記
この仕様では、ECMAScript 言語値を太字で表示します。例として、null、true、または "hello" があります。これらは、Function.prototype.apply や let n = 42; などの ECMAScript ソーステキストと区別されます。
5.2.8 同一性
この仕様では、仕様値と ECMAScript 言語値の両方について、等しいかどうかを比較します。等しいかどうかを比較するとき、値は2つの分類のいずれかに属します。同一性を持たない値は、整数の大きさや列の長さなど、その本来の特性がすべて同じであれば、他の同一性を持たない値と等しくなります。同一性を持たない値は、その特性を完全に記述することで、事前の参照なしに具現化できます。一方、同一性を持つ値は、それぞれ一意であり、したがって自身とのみ等しくなります。同一性を持つ値は、同一性を持たない値に似ていますが、同一性と呼ばれる、推測不可能、変更不可能、かつ普遍的に一意な特性を追加で持ちます。同一性自体は記述不可能であるため、既存の同一性を持つ値への参照を、単にその値を記述するだけで具現化することはできません。その代わり、これらの値への参照は、ある場所から別の場所へ明示的に渡されなければなりません。同一性を持つ値の一部は可変であり、その特性(同一性を除く)をその場で変更できるため、その値を保持するすべての主体が、新しい特性を観測することになります。同一性を持たない値が、同一性を持つ値と等しくなることはありません。
この仕様の観点では、“である”という語を、“もし bool が true であれば、...”のように、2つの値が等しいかどうかを比較するために使用します。また、“含む”という語を、“もし list が、r.[[Foo]] が true であるような Record r を含むならば、...”のように、等価比較を使用してリスト内の値を検索するために使用します。値の仕様上の同一性は、これらの比較の結果を決定し、この仕様では公理として扱われます。
ECMAScript 言語の観点では、言語値が等しいかどうかは、抽象操作 SameValue と、それが推移的に呼び出す抽象操作を使用して比較されます。これらの比較を行う抽象操作のアルゴリズムが、ECMAScript 言語値の言語上の同一性を決定します。
仕様値について、仕様上の同一性を持たない値の例には、数学的値と拡張数学的値、ECMAScript ソーステキスト、サロゲートペア、ディレクティブプロローグなど、UTF-16 コード単位、Unicode コードポイント、列挙値、構文指向操作やホストフックなどを含む抽象操作、および順序対が含まれますが、これらに限定されません。仕様上の同一性を持つ仕様値の例には、Property Descriptor、PrivateElement などを含むあらゆる種類の Record、Parse Node、List、Set と Relation、Abstract Closure、Data Block、Private Name、実行コンテキストと実行コンテキストスタック、エージェント識別子、および WaiterList Record が含まれますが、これらに限定されません。
仕様上の同一性は、Symbol.for によって生成される Symbol 値を除く、すべての ECMAScript 言語値について、言語上の同一性と一致します。仕様上の同一性と言語上の同一性のどちらも持たない ECMAScript 言語値は、undefined、null、Boolean、String、Number、および BigInt です。仕様上の同一性と言語上の同一性を持つ ECMAScript 言語値は、Symbol のうち Symbol.for によって生成されていないものと、Object です。Symbol.for によって生成される Symbol 値は、仕様上の同一性を持ちますが、言語上の同一性は持ちません。