綺麗にまとめようと思っていたら、かなり時間が空いてしまったので、もう公開しちゃえ!
ECMASCript2015 Language Specificationの一人輪読会資料。
今回は5章からスタート。
サマリ
- 文脈自由文法について
- 生成規則(productions)の集合で文・言語を表現
- 生成規則は左辺が非終端記号、右辺が0個以上の非終端記号または終端記号
- 本仕様には4つの文法がある
- 字句文法(Lexical Grammar)
- ソースコード → ECMAScriptトークン
- 正規表現文法(RegExp Grammar)
- 数値文字列の文法(Numeric String Grammar)
- 構文文法(Syntactic Grammar)
- 字句文法(Lexical Grammar)
- 文法・アルゴリズムの表記法について
- 読み進めていく中でわからない記号があれば、あとで見返すくらいで良さそう。
5 Notational Conventions
- Notational Conventions・・・表記法
- 本仕様で文法やアルゴリズムをどのように表記し定義するかが書いてある。
-
ES5の5章と比較すると、おおまかには一緒だが、新しい表記法(
[paramaters]
とか)の追加や、5.3の追加など、変わっている。
5.1 Syntactic and Lexical Grammars
構文文法と字句文法
5.1.1 Context-Free Grammars
- Context-Free Grammars → 文脈自由文法
- (プログラミング言語を定義するために使われるらしい)
- 生成規則(product ion; P)の集合で言語を定義する
- 生成規則は左辺に非終端記号(nonterminal symbol; N)、右辺に0以上の終端記号(terminal symbol; Σ)か非終端記号の配列を持つ
- どの文法でも終端記号は特定のアルファベットで記述される
- 連鎖生成規則(a chain production、ES5にはなかったのでこの訳でいいか不安)は、右辺に非終端記号を含む生成規則
- 右辺の非終端記号が別の生成規則を参照しているので、生成規則→生成規則となるのが連鎖ということだと思う。
- 目標記号(the goal symbol)と呼ばれる特定の非終端記号から始まる場合、自由文脈文法は言語を示す
文脈自由文法がよくわからなかった時に見た記事
- 文脈自由文法とは
-
Wekipedia 形式文法
- そもそも「文法」とは
-
文脈自由文法の話
- 非終端記号・終端記号のイメージが分かった
5.1.2 The Lexical and RegExp Grammars
字句文法(Lexical Grammar)
- 詳細は11章
- この文法は終端記号として10.1で定義されている
SourceCharacter
のルールに従うUnicodeのコードポイントを持つ - 以下の目標記号から始まる生成規則を定義している。これらの生成規則はコードポイントの配列がどのように入力要素(Input elements)に変換されるかを定義している。
InputElementDiv
InputElementTemplateTail
InputElementRegExp
InputElementRegExpOrTemplateTail
- コメントと空白文字以外の入力要素はECMAScriptの構文文法(Syntatic Grammar)では終端文字を構成し、ECMAScriptトークン と呼ばれる
- ECMAScriptトークンは、予約語、識別子、リテラル、区切り文字(punctuators、punctuate→【動詞】句読点をつける、なので、カンマやセミコロンのことだと思われる)
- トークンと見なされない改行文字は、入力要素のストリームの一部を構成し、セミコロンの自動挿入処理(automatic semicolon insertion, 詳細は11.9)を制御する
- トークンとみなされる改行文字とは?template string内の改行とかか?
- 空白文字、行コメントは切り捨てられ、構文文法の入力要素には含まれない
- 1つ以上の改行文字を含むMultiLineComment(複数行に渡る
/* */
のコメントのことかな)は1つの改行文字に変換され、構文文法の入力要素に含まれる
正規表現文法(RegExp Grammar)
- 詳細は21.2.1
- 字句文法と一緒で終端文字はSourceCaharacterで定義されているUnicodeのコードポイント
-
Pattern
という目標記号から始まる生成規則を定義していて、Unicodeのコードポイントをどうやって正規表現パターンに変換するか定義している
字句文法・正規表現文法の記述方法
下記のように生成規則の右辺と左辺を::
(コロン2つ)で区切っている場合は、字句文法・正規表現文法の生成規則。
右辺(非終端記号)::
左辺1(非終端記号か終端記号)
左辺2
左辺3
...
字句文法と正規表現文法はいくつかの生成規則を共有する。
5.1.3 The Numeric String Grammar
数値文字列の文法
- 詳細は7.1.3.1
- この文法は数値リテラルを扱う点と終端記号としてSourceCharacterを使う点で、字句文法と似ている
- 文字列を数値に変換する文法はまた別。
- 数値文字列文法の生成規則の区切り文字は
:::
(コロン3つ)
右辺(非終端記号):::
左辺
...
5.1.4 The Syntactic Grammar
構文文法
- 詳細は11~15章
- 字句文法で定義されたECMAScriptトークンを終端記号として持つ
- 生成規則は
Script
とModule
の2つの目標記号のどちらかから始まる - 生成規則は、ECMAScriptトークンの並びがどのようにECMAScriptプログラムを構成するのかを表している。
- Unicodeのコードポイントで構成されるソースコード → <字句文法>(繰り返し適用) → ECMAScriptトークンの配列 → <構文文法>(1度だけ適用) →
Script
,Module
- トークンの並びが単体の目標記号(
Script
,Module
)にパースできていない場合はシンタックスエラーと見なされる - 構文文法の生成規則の区切り文字は
:
右辺(非終端記号):
左辺
...
5.1.5 Grammar Notation
文法の表記法。
いちおまとめたが、6章以降でわからない記号とかが出てきた時に振り返る程度いいかも。
あと、実際にはフォントや記号のサイズ・色がはっきりと区別できるようになっているので、PDFやWebで仕様書を一度目を通したほうが良いと思う。
フォントとか
- 字句文法、正規表現文法、数値文字列文法の終端記号は等幅フォントで表記される
- 非終端記号はイタリック体で表記される
- 非終端記号の選択肢が多すぎてリスト化出来ない場合はサンセリフ体で書かれた説明的な語句で表す
- 例えば、
SourceCharacter ::
any Unicode code unit
再帰
ArgumentList :
AssignmentExpression
ArgumentList , AssignmentExpression
- 右辺の中で左辺の
ArgumentList
を再帰的に参照している - 上記定義は
ArgumentList
が任意の正の数の引数をカンマで区切って持っていることを表している
"opt"
- 記号の末尾に
opt
がついている場合は、その記号がオプショナルであることを示している
VariableDeclaration :
BindingIdentifier Initializer[opt] (←実際は[opt]の文字色が赤でフォントサイズも小さい)
↓と同じ
VariableDeclaration :
BindingIdentifier
BindingIdentifier Initializer
"[parameters]" parameterized production
- 非終端記号の末尾に
[parameter]
がついている場合は、その記号に_parameter
を付けた生成規則をもう1つ定義したのと同じ
StatementList[Return] :
ReturnStatement
ExpressionStatement
↓と同じ
StatementList:
ReturnStatement
ExpressionStatement
StatementList_Return :
ReturnStatement
ExpressionStatement
-
NT[param1, param2]
みたいにパラメタをカンマで区切って複数指定できる - その場合、パラメタ数分じゃなくて組み合わせなので、パラメタが2つの場合は4通り定義される
StatementList[Return, In] :
ReturnStatement
ExpressionStatement
↓と同じ
StatementList :
ReturnStatement
ExpressionStatement
StatementList_Return :
ReturnStatement
ExpressionStatement
StatementList_In :
ReturnStatement
ExpressionStatement
StatementList_Return_In :
ReturnStatement
ExpressionStatement
-
opt
と組み合わせ可能
VariableDeclaration :
BindingIdentifier Initializer[In][opt]
↓と同じ
VariableDeclaration :
BindingIdentifier Initializer_In[opt]
[?parameter]
- 右辺にパラメタがある時にパラメタ名の先頭に
?
をつけると、左辺のパラメタが記号に付いた時にに右辺のパラメタも付くようになる
VariableDeclaration[In] :
BindingIdentifier Initializer[?In]
↓と同じ
VariableDeclaration :
BindingIdentifier Initializer
VariableDeclaration_In :
BindingIdentifier Initializer_In
[+parameter]
[~prefix]
prefix
-
[+parameter]
が先頭にある右辺の行は、左辺がそのパラメタを適用している時だけ有効になる
StatementList[Return] :
[+Return] ReturnStatement
ExpressionStatement
↓と同じ
StatementList :
ExpressionStatement
StatementList_Return :
ReturnStatement
ExpressionStatement
-
[~parameter]
は[+parameter]
の逆で、左辺がそのパラメタを適用しているときはその右辺の行が無効になる
StatementList[Return] :
[~Return] ReturnStatement
ExpressionStatement
↓と同じ
StatementList :
ReturnStatement
ExpressionStatement
StatementList_Return :
ExpressionStatement
one of
- 各文法の生成規則の区切り文字(
:
)の後にone of
がついている場合、その次の行の終端記号の一つ一つが生成規則の右辺になる
NonZeroDigit :: one of
1 2 3 4 5 6 7 8 9
↓と同じ
NonZeroDigit ::
1
2
3
4
5
6
7
8
9
[empty]
- 生成規則の右辺に
[empty]
がある場合は、その生成規則の右辺は終端記号・非終端記号を1つも持たないという意味
[lookahead ∉ set]
-
[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]
- ↑この定義は、
- 右辺1行目・・・n + 偶数1文字(1,3,5,7,9以外の数字) + 1つ以上の数字
- 右辺2行目・・・数字1文字+数字以外1文字
[no LineTerminator here]
- そのまんまだけど、その位置に改行入れた場合、その展開ルールは適用されないよという意味。
but not
- 一部の展開を許可したくない時に使う
Identifier ::
IdentifierName but not ReservedWord
- 上記例)
Identifier
はIdentiferName
( ただしReservedWord
は除く )で構成される
5.2 Algorithm Conventions
アルゴリズムの慣習
アルゴリズムの表記
- アルゴリズムのステップは番号付きリストで表現される
- わかりやすくするために。細分化されサブステップを持つ場合がある
- サブステップはインデントされて表記される
- 階層が深くなる毎に、数字→小文字英字→ローマ数字→数字...、で採番される
1. トップレベルステップ
a. サブステップ
b. サブステップ
i. サブサブステップ
1. サブサブサブステップ
2. ...
- サブステップが
if
やelse
で分岐を表現できる
アルゴリズムのパラメタライズ
- アルゴリズムはパラメタライズされる場合がある
- アルゴリズムを関数のように扱い、別のアルゴリズムから参照することで、処理の一部を抽象化すること(だと思う)
-
処理名(arg1, arg2)
のような感じで他のアルゴリズムから参照できる- いくつかはクラスのメソッドみたいに
someValue.処理名(arg1, arg2)
のように扱われるものもある
- いくつかはクラスのメソッドみたいに
- そのアルゴリズムの名前や使い方は、アルゴリズムの定義の一部として提供される
- パラメタライズされたアルゴリズムは、abstract operationという
文法の生成規則(productions)の参照
- アルゴリズムは本仕様に定義されている文法の生成規則と関連付けられる場合がある
- アルゴリズムと関連付けられる場合、文法の表記で使われていた
[]
系の注釈(5.1.5で登場した[opt]
や[パラメタ名]
みたいなやつ)はアルゴリズムの表記では用いられない
Assert
-
Assert:
で始まるステップは、そのアルゴリズムの不変条件(invariant condition)をアサートする - それらのアサーションは暗黙的になりがちなアルゴリズムの不変関係を明示的に表現するためにあり、実装でチェックする必要はない。単純にアルゴリズムをわかりやすくするために使われる
数学的な処理や関数
- ES5と同じなので、詳しくはそちらを参照ください。
- http://tsofthome.appspot.com/ecmascript/ecma-262.5_05.html
- 加算・減算・除算などの数学的な処理や、後述の章で定義する数学的な関数は、数学的な実数に基づく正確な数学的な結果を計算するものと解釈されないといけない
- 関数
-
abs(x)
はxの絶対値を返す -
floor(x)
は、xより大きくない整数のうち最も大きい整数を返す - (
modulo
はようわからん。すまん)
-
5.3 Static Semantic Rules
- 自由文脈文法は十分に強力ではない
- ECMASCriptとして正しいかどうか定義している全てのルールを表現できない
- なので、場合によって、いくつかのルールはECMAScriptのアルゴリズムの慣習や散文的な要件を必要とする場合がある
- それらのルールは常に文法の生成規則と関連付けられ、静的セマンティック(static semantic)と呼ばれる
- 静的セマンティックルールは名前を持ち、通常はアルゴリズムを使って定義される
例1)Contains
- 全ての生成規則の右辺は暗黙的に
Contains
という名前の静的セマンティックルールのための定義を持っている
1. この定義内の各終端記号・非終端記号symのために、生成規則は
a. symが同じ記号symbolの場合、trueを返す
b. symが非終端記号の場合は、
i. 右辺をsymの返り値とする
ii. 右辺がtrueの場合、trueを返す
2. それ以外の場合にはfalseを返す
例2)Early Error Rule
- 特殊な静的セマンティックルールのⅰつに早期エラールール(Early Error Rule)があげられる
- 早期エラールールは早期エラーの条件を定義している。(詳しくは16章)
- 早期エラールールの評価は明示的に実行されない