5.1 構文・字句文法
5.1.1 文脈自由文法
文脈自由文法は、複数の生成式で構成されます。各生成式は、非終端記号と呼ばれる抽象的な記号を左辺に持ち、0個以上の非終端記号と終端記号の並びを右辺に持ちます。各文法ごとに、終端記号は指定されたアルファベットから選ばれます。
連鎖生成式は、右辺にまさに1個の非終端記号と0個以上の終端記号のみを持つ生成式です。
区別される単一の非終端記号(ゴール記号)から始めて、与えられた文脈自由文法は言語、すなわち、非終端記号をその左辺となる生成式の右辺で繰り返し置き換えることで得られる終端記号の並びの(おそらく無限の)集合を定義します。
5.1.2 字句・正規表現文法
ECMAScriptの字句文法は12で示されています。この文法の終端記号は、11.1で定義されるSourceCharacterの規則に従うUnicodeコードポイントです。ゴール記号InputElementDiv、InputElementTemplateTail、InputElementRegExp、InputElementRegExpOrTemplateTail、InputElementHashbangOrRegExpから始まる生成式集合が定義され、これらのコードポイントの並びを入力要素の並びへ変換する方法を表します。
空白やコメント以外の入力要素は、ECMAScriptの構文文法の終端記号となり、ECMAScriptのトークンと呼ばれます。これらのトークンは、予約語、識別子、リテラル、句読点です。さらに、行終端文字はトークンとはみなされませんが、入力要素のストリームの一部となり自動セミコロン挿入(12.10)を導きます。単純な空白や1行コメントは破棄され、構文文法の入力要素ストリームには現れません。MultiLineComment(つまり、/*
…*/
形式のコメントで、複数行にまたがるかどうかにかかわらず)は、行終端文字を含まなければ単に破棄されますが、行終端文字が1つ以上含まれていれば、1つの行終端文字に置き換えられ、構文文法の入力要素ストリームの一部となります。
ECMAScriptの正規表現文法は22.2.1で示されています。この文法の終端記号もSourceCharacterで定義されるコードポイントです。ゴール記号Patternから始まる生成式集合が定義され、コードポイントの並びを正規表現パターンへ変換する方法を表します。
字句文法・正規表現文法の生成式は、「::」の2つのコロンで区切られていることで区別されます。字句文法と正規表現文法は一部の生成式を共有します。
5.1.3 数値文字列文法
数値文字列文法は7.1.4.1に示されています。終端記号はSourceCharacterであり、ゴール記号StringNumericLiteralから文字列を数値値へ変換するために使われます(数値リテラルの字句文法とは似ていますが異なります)。
数値文字列文法の生成式は「:::」の3つのコロンで区切られており、ソーステキストの構文解析には使用されません。
5.1.4 構文文法
ECMAScriptの構文文法は13から16までの節で示されています。この文法の終端記号は字句文法で定義されたECMAScriptトークンです(5.1.2)。ゴール記号ScriptとModuleの2つから始まる生成式集合が定義され、トークンの並びがECMAScriptプログラムの構文的に正しい独立要素を形成する方法を表します。
コードポイントのストリームをECMAScriptのScriptやModuleとして構文解析する場合、まず字句文法を繰り返し適用して入力要素のストリームに変換し、その後構文文法を1回適用して解析します。入力ストリームが、ゴール非終端記号(ScriptまたはModule)の単一インスタンスとして解析できず、トークンが余る場合は構文エラーとなります。
構文解析が成功すると、構文木という根付きの木構造が構築され、各ノードは構文ノードです。各構文ノードは文法記号のインスタンスであり、その記号から導出できるソーステキストの範囲を表します。構文木の根ノードは解析全体のゴール記号のインスタンスです。構文ノードが非終端記号のインスタンスである場合、その非終端記号を左辺に持つ生成式のインスタンスでもあります。また、右辺の各記号ごとに0個以上の子ノードを持ちます。各子は対応する記号のインスタンスである構文ノードです。
構文ノードはパーサーの呼び出しごとに新たに生成され、同じソーステキストでも解析間で使い回されることはありません。構文ノードは、同じソース範囲を表し、同じ文法記号のインスタンスであり、同じパーサー呼び出しから生成された場合のみ同じ構文ノードとみなされます。
Note 1
同じ文字列を複数回解析すると、異なる構文ノードが得られます。例えば:
let str = "1 + 1;";
eval(str);
eval(str);
それぞれのeval
呼び出しは、str
の値をECMAScriptソーステキストに変換し、独立した構文木を生成する個別の解析を行います。各木は、同じ文字列値から導出されたソーステキストであっても別物です。
Note 2構文ノードは仕様上のアーティファクトであり、実装が同様のデータ構造を使う必要はありません。
構文文法の生成式は、区切りが1つのコロン「:」であることで区別されます。
構文文法は、13から16までで示されるものだけでは、どのトークン並びが正しいECMAScriptのScriptやModuleとして受理されるかの完全な説明にはなりません。特定の追加トークン並び(たとえば行終端文字の前にセミコロンを追加した場合など)は、文法で記述されていれば受理されます。逆に、文法で記述されていても、行終端文字が「不自然」な場所に現れると受理されない場合もあります。
曖昧さ回避のため、構文文法では有効なECMAScriptのScriptやModuleにならないトークン並びも許容する一般化生成式が使われる場合があります。例えば、オブジェクトリテラルや分割代入パターンでこの手法が使われます。その場合、より制約された補助文法が提供され、受理可能なトークン並びが制限されます。通常、早期エラー規則で「"PはNをカバーしなければならない"」と記されます。Pは一般化生成式の構文ノード、Nは補助文法の非終端記号です。これは次の意味です:
- Pがもともとマッチしたトークン並びを、Nをゴール記号として再度解析します。Nが文法パラメータを持つ場合は、Pの解析時と同じ値で設定します。
- トークン並びが、余りなくNの単一インスタンスとして解析できれば:
- そのNのインスタンス(P固有の構文ノード)を「PによってカバーされたN」と呼びます。
- Nおよびその派生生成式の早期エラー規則は、PによってカバーされたNにも適用されます。
- そうでなければ(解析失敗時)、早期構文エラーとなります。
5.1.5 文法記法
5.1.5.1 終端記号
ECMAScriptの文法では、等幅
フォントで示される終端記号があります。これらはソーステキストに正確に記述されたとおりに現れなければなりません。このように指定されたすべての終端記号コードポイントは、他のUnicode範囲ではなく、基本ラテンブロックの適切なUnicodeコードポイントであると理解されます。終端記号内のコードポイントは、\
UnicodeEscapeSequenceで表現することはできません。
終端記号が個々のUnicodeコードポイントで構成される文法(字句・正規表現・数値文字列文法)では、生成式内の複数の等幅コードポイントの連続は、同じコードポイントの並びを個別の終端記号として書く省略表記です。
例えば、次の生成式:
HexIntegerLiteral ::
0x
HexDigits
は、次の省略表記です:
HexIntegerLiteral ::
0
x
HexDigits
一方、構文文法では、等幅コードポイントの連続は1つの終端記号です。
終端記号には他にも2つの形式があります:
5.1.5.2 非終端記号と生成式
非終端記号は斜体で示されます。非終端記号(「生成式」とも呼ばれる)の定義は、定義される非終端記号の名前の後に1つ以上のコロンを続けて導入されます。(コロンの数はその生成式が属する文法を示します。)非終端記号の右辺の選択肢が続く形になります。例えば、構文定義:
WhileStatement :
while
(
Expression
)
Statement
は、非終端記号WhileStatementが、while
トークン、左括弧トークン、Expression、右括弧トークン、Statementの並びを表すことを示します。ExpressionやStatementはそれ自体非終端記号です。別の例として、構文定義:
ArgumentList :
AssignmentExpression
ArgumentList
,
AssignmentExpression
は、ArgumentListが、単一のAssignmentExpressionまたは、ArgumentListの後にカンマとAssignmentExpressionが続く場合のいずれかを表すことを示します。この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
の後に1つ以上の10進数字が続き、その最初が偶数である場合、または10進数字の後にさらに数字が続かない場合にマッチします。
これらの句が構文文法で使われる場合、直後のトークン並びを一意に特定できない可能性があることに注意してください。後続トークンの決定には後続位置で使う字句ゴール記号の選択が必要となるためです。したがって、構文文法でこれらを使う場合、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
は、非終端記号IdentifierはIdentifierNameで置換できるコードポイント並びのうち、同じ並びがReservedWordでも置換できる場合を除くことを意味します。
5.1.5.10 記述的句
最後に、非終端記号のうち、すべての選択肢を列挙するのが非現実的な場合、サンセリフ体の記述的句で説明されるものがあります:
SourceCharacter ::
any Unicode code point
5.2 アルゴリズム規則
仕様書では、アルゴリズムの手順を指定するために番号付きリストをよく使用します。これらのアルゴリズムは、ECMAScript言語構成要素の必要な意味論を厳密に規定するために使われます。ただし、特定の実装技法の使用を示唆するものではありません。実際には、ある機能を実装するためにより効率的なアルゴリズムが存在する場合もあります。
アルゴリズムは、順序付きのカンマ区切りのエイリアス名の列で明示的にパラメータ化されることがあります。これらの名前は、アルゴリズムの手順内でその位置に渡された引数を参照するために使用できます。省略可能なパラメータは角括弧([ , name ])で囲まれて示され、アルゴリズム手順内では必須パラメータと違いはありません。パラメータリストの末尾には、先頭に省略記号(...name)を付けたrestパラメータを指定できます。restパラメータは、必須・省略可能パラメータの後に渡された全ての引数をListにまとめて受け取ります。追加の引数がない場合、そのListは空です。
アルゴリズムの手順は、順序付きのサブステップに分割できます。サブステップはインデントされ、さらにインデントされたサブステップに分割することもできます。アウトライン番号付け規則により、最初のサブステップは小文字アルファベット、次のレベルは小文字ローマ数字でラベル付けされます。3段階を超える場合は、4段階目で数字ラベルが使われ、以降繰り返します。例えば:
- 最上位の手順
- サブステップ
- サブステップ
- サブサブステップ
- サブサブサブステップ
- サブサブサブサブステップ
- サブサブサブサブサブステップ
手順やサブステップは、「if」条件で書かれており、サブステップは条件が真の時のみ適用されます。「else」で始まる場合は、同じ階層の直前の「if」手順の否定条件になります。
手順は、サブステップの反復適用を指定することがあります。
「Assert:」で始まる手順やサブステップは、そのアルゴリズムの不変条件を主張します。これらのアサートは、暗黙的なアルゴリズム不変性を明示するために使われます。アサートは追加の意味的要件を持たず、実装がチェックする必要はありません。アルゴリズムの明確化のためだけに使用されます。
アルゴリズム手順では、「Let x be someValue」の形式で任意の値に名前付きエイリアスを宣言できます。これらのエイリアスは参照のようなもので、xとsomeValueは同じデータを参照し、どちらかを変更すると両方に反映されます。参照的挙動を避けたい場合は、「Let x be a copy of someValue」と明示的にコピーを作成することもできます。
エイリアスは宣言後の任意の手順で参照できますが、宣言より前の手順では参照できません。エイリアスは「Set x to someOtherValue」の形式で変更できます。
5.2.1 抽象操作
この仕様の複数箇所で利用しやすくするために、あるアルゴリズム(抽象操作)は名前付き・パラメータ化された関数形式で記述され、他のアルゴリズムから名前で参照できるようになっています。抽象操作は通常、OperationName(arg1, arg2)のような関数呼び出し形式で参照されます。一部の抽象操作は、クラスライクな仕様抽象のメソッドとして多態的に呼び出されます。メソッドライク抽象操作は、someValue.OperationName(arg1, arg2)のようなメソッド呼び出し形式で参照されます。
5.2.2 構文指示操作
構文指示操作は、名前付き操作であり、その定義は複数のアルゴリズムからなり、それぞれがECMAScript文法の1つ以上の生成式に関連付けられています。生成式が複数の代替定義を持つ場合、各代替ごとに異なるアルゴリズムがあることが多いです。アルゴリズムが文法生成式に関連付けられている場合、生成式代替の終端記号や非終端記号をアルゴリズムのパラメータのように参照できます。この場合、非終端記号は、ソーステキストを構文解析したときにマッチした実際の代替定義を参照します。文法生成式やそこから導出されるParse Nodeがマッチしたソーステキストとは、最初にマッチした終端記号から最後にマッチした終端記号までのソーステキスト部分です。
アルゴリズムが生成式代替に関連付けられる場合、代替は通常「[ ]」文法注釈なしで示されます。これらの注釈は代替の構文的認識のみに影響し、代替に関連付けられた意味論には影響しません。
構文指示操作は、パースノードと(必要に応じて)他のパラメータを使って、以下のアルゴリズムの手順1、3、4で示される規則で呼び出します:
- Let status be SyntaxDirectedOperation of SomeNonTerminal.
- Let someParseNode be the parse of some source text.
- Perform SyntaxDirectedOperation of someParseNode.
- Perform SyntaxDirectedOperation of someParseNode with argument "value".
明示的な記載がない限り、すべての連鎖生成式には、その生成式の左辺非終端記号に適用される可能性のあるすべての操作の暗黙定義があります。暗黙定義は、同じ操作を同じパラメータ(あれば)で連鎖生成式の唯一の右辺非終端記号に再適用し、その結果を返すだけです。たとえば、あるアルゴリズムに「Return Evaluation of Block」という手順があり、次の生成式があるとします:
Block :
{
StatementList
}
Evaluation操作がその生成式にアルゴリズムを関連付けていない場合、Evaluation操作には次のような暗黙の関連付けが含まれます:
実行時意味論: Evaluation
Block :
{
StatementList
}
- Return Evaluation of StatementList.
5.2.3 実行時意味論
実行時に呼び出される必要がある意味論を規定するアルゴリズムは実行時意味論と呼ばれます。実行時意味論は抽象操作または構文指示操作によって定義されます。
5.2.3.1 Completion ( completionRecord )
The abstract operation Completion takes argument completionRecord (Completion Record) and returns Completion Record. It performs the following steps when called:
- Assert: completionRecordはCompletion Recordである。
- completionRecordを返す。
5.2.3.2 例外を投げる
例外を投げるように記載されたアルゴリズム手順、例えば
- TypeError例外を投げる。
は、次の意味と同じです:
- ThrowCompletion(新しく生成されたTypeErrorオブジェクト)を返す。
5.2.3.3 ReturnIfAbrupt
次のような記載やそれに相当するアルゴリズム手順:
- ReturnIfAbrupt(argument)。
は、次の意味と同じです:
- Assert: argumentはCompletion Recordである。
- argumentがabrupt completionなら、Completion(argument)を返す。
- それ以外の場合、argumentをargument.[[Value]]にセットする。
次のような記載やそれに相当するアルゴリズム手順:
- ReturnIfAbrupt(AbstractOperation())。
は、次の意味と同じです:
- Let hygienicTemp be AbstractOperation()。
- Assert: hygienicTempはCompletion Recordである。
- hygienicTempがabrupt completionなら、Completion(hygienicTemp)を返す。
- それ以外の場合、hygienicTempをhygienicTemp.[[Value]]にセットする。
ここで、hygienicTempはReturnIfAbruptに関する手順でのみ一時的に可視です。
次のような記載やそれに相当するアルゴリズム手順:
- Let result be AbstractOperation(ReturnIfAbrupt(argument))。
は、次の意味と同じです:
- Assert: argumentはCompletion Recordである。
- argumentがabrupt completionなら、Completion(argument)を返す。
- それ以外の場合、argumentをargument.[[Value]]にセットする。
- Let result be AbstractOperation(argument)。
5.2.3.4 ReturnIfAbruptの省略記法
抽象操作や構文指示操作の呼び出しの前に?
が付く場合、ReturnIfAbruptをそのCompletion Recordに適用することを示します。例えば、この手順:
- ? OperationName()。
は次の手順と同義です:
- ReturnIfAbrupt(OperationName())。
同様に、メソッド呼び出し形式の場合は:
- ? someValue.OperationName()。
は次の手順と同義です:
- ReturnIfAbrupt(someValue.OperationName())。
また、!
のプレフィックスは、後続の抽象操作や構文指示操作の呼び出しがabrupt completionを返さないことを示し、Completion Recordの[[Value]]フィールドを操作の戻り値として使うことを意味します。例えば、この手順:
- Let val be ! OperationName()。
は、次の手順と同義です:
- Let val be OperationName()。
- Assert: valはnormal completionである。
- valをval.[[Value]]にセットする。
実行時意味論の構文指示操作では、操作呼び出しの前に!
または?
を付けてこの省略記法を利用します:
- ! SyntaxDirectedOperation of NonTerminalを実行する。
5.2.3.5 暗黙のnormal completion
Completion Recordを返すことが宣言された抽象操作内や、全ての組み込み関数内のアルゴリズムでは、返される値はまずNormalCompletionに渡され、その結果が代わりに使われます。この規則はCompletionアルゴリズム内や、その手順でCompletion Recordと明示されている場合には適用されません。具体的には次のケースです:
これら以外の方法でCompletion Recordを返すことは編集上の誤りです。例として、これらの抽象操作内では、
- trueを返す。
は次のいずれかと同義です:
- NormalCompletion(true)を返す。
あるいは
- Let completion be NormalCompletion(true)。
- Completion(completion)を返す。
あるいは
- Completion Record { [[Type]]: normal, [[Value]]: true, [[Target]]: empty }を返す。
ReturnIfAbrupt展開によって、次の例は許容されます。展開後の手順内でCompletionの適用結果がabruptの場合は直接返され、normalの場合はアンラップ後に暗黙のNormalCompletion適用が行われます。
- Return ? completion。
次の例は、Completion Recordをその手順で注釈なしに返しているため編集上の誤りです。
- Let completion be NormalCompletion(true)。
- completionを返す。
5.2.4 静的意味論
文脈自由文法だけでは、入力要素のストリームが評価可能な有効なECMAScriptのScriptやModuleになるかどうかを定義する全ての規則を表現することはできません。場合によっては、ECMAScriptアルゴリズム規則や記述的要件を使って追加の規則を記述する必要があります。これらの規則は常に文法生成式に関連付けられ、生成式の静的意味論と呼ばれます。
静的意味論規則には名前があり、通常アルゴリズムで定義されます。名前付き静的意味論規則は文法生成式に関連付けられ、生成式が複数の代替定義を持つ場合、各代替ごとに適用される名前付き静的意味論規則のアルゴリズムが異なることが多いです。
静的意味論規則の中には、早期エラー規則という特別なものがあります。早期エラー規則は、特定の文法生成式に関連付けられた早期エラー条件(17参照)を定義します。ほとんどの早期エラー規則の評価は、仕様のアルゴリズム内で明示的に呼び出されません。適合実装は、ScriptやModuleを初めて評価する前に、パースに使われた生成式の全ての早期エラー規則を検証しなければなりません。早期エラー規則が違反している場合、そのScriptやModuleは無効となり、評価できません。
5.2.5 数学演算
本仕様書では、以下の種類の数値値に言及します:
仕様書の記述では、数値値は下付き添え字で種類が区別されます。添え字𝔽はNumber、添え字ℤはBigIntを指します。添え字なしは数学値です。数値の表記はほとんど10進数ですが、0xに続く数字0-9やA-Fは16進数値として使われます。
一般に、本仕様が数値値(例えば「yの長さ」や「4桁の16進数が表す整数」など)に言及する場合、数値種類を明示しない限り数学値を指します。NumberやBigInt値に言及する場合は、明示的に注釈されます(例:「…のcode point数の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です。非有限値の数学値は定義されません。拡張数学値は有限値に対しては数学値、+∞𝔽と-∞𝔽に対してはそれぞれ+∞と-∞、NaNには定義されません。
数学関数abs(x)はxの絶対値(x < 0なら- x、それ以外はx)を返します。
数学関数min(x1, x2, … , xN)はx1からxNまでの最小値、max(x1, x2, ..., xN)は最大値を返します。これらの関数の定義域と値域は拡張数学値です。
記法「x modulo y」(yは有限かつ非零)は、yと同じ符号(または0)で絶対値がy未満になる値kを計算し、abs(k) < abs(y) and x - k = q × y(qは整数)を満たします。
「xをlowerからupperの間でクランプする」という句(xは拡張数学値、lowerとupperはlower ≤ upperな数学値)は、x < lowerならlower、x > upperならupper、それ以外はxを返します。
数学関数floor(x)はx以下で最大の整数(+∞に最も近いもの)を返します。
Note
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 ≤ 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𝔽のみ含み、-0𝔽は含みません。NaNは区間に含まれません。
5.2.6 値の記法
本仕様書では、ECMAScript言語値は太字で表示されます。例: null, true, "hello"など。これらは、Function.prototype.apply
やlet n = 42;
などのECMAScriptソーステキストとは区別されます。
5.2.7 同一性
本仕様書では、仕様値とECMAScript言語値の両方の等価性を比較します。等価性を比較する場合、値は2つのカテゴリのいずれかに属します。同一性のない値は、全ての本質的特徴が同じであれば他の同一性のない値と等価です(整数の大きさや配列の長さなど)。同一性のない値は、特徴を完全に記述することで事前参照なしに現すことができます。対照的に、同一性を持つ値は一意であり自分自身とだけ等価です。同一性を持つ値は、同一性のない値の特徴に加え、推測不可・不変・普遍的な同一性という特徴を持ちます。既存の同一性を持つ値への参照は、同一性自体が記述不可能なので記述によって現せず、明示的に他所から受け渡す必要があります。同一性を持つ値の一部は可変であり、特徴(同一性以外)はその場で変更可能で、値を保持する者全員が新しい特徴を観察することになります。同一性のない値は同一性を持つ値と等価になることはありません。
本仕様書の観点では、「is」は2つの値の等価性比較に使われます(例:「bool is trueなら…」)。「contains」はリスト内の値を等価性比較で探索する場合に使われます(例:「listがRecord r(r.[[Foo]] is true)を含むなら…」)。値の仕様同一性がこれらの比較結果を決定し、本仕様では公理的に扱います。
ECMAScript言語の観点では、言語値の等価性比較はSameValue抽象操作と、それが遡及的に呼び出す抽象操作で行われます。これらの比較抽象操作のアルゴリズムがECMAScript言語値の言語同一性を定義します。
仕様値の例として、仕様同一性を持たない値には、数学値・拡張数学値、ECMAScriptソーステキスト、サロゲートペア、Directive Prologue、UTF-16コード単位、Unicodeコードポイント、enum、抽象操作(構文指示操作・ホストフック等)、順序対などが含まれます。仕様同一性を持つ値には、Record(Property Descriptor、PrivateElement等)、Parse Node、List、Set・Relation、Abstract Closure、Data Block、Private Name、実行コンテキスト・スタック、agent signifier、WaiterList Recordなどがあります。
仕様同一性は、Symbol.forで生成されたSymbol値を除き、全てのECMAScript言語値で言語同一性と一致します。仕様同一性も言語同一性も持たないECMAScript言語値は、undefined、null、Boolean、String、Number、BigIntです。仕様同一性も言語同一性も持つのはSymbol(Symbol.for生成を除く)とObjectです。Symbol.forで生成されたSymbol値は仕様同一性のみ持ち、言語同一性は持ちません。