2014-04-17

JavaScriptの自動セミコロン挿入

JavaScriptでは、多くの文は、セミコロンという終端記号を明示的に記述して、文の終わりを示す。

var i = 0 ;
++i ;
--i ;

しかし、JavaScriptでは、一部の文脈で、セミコロンの省略が許されている。あたかも、セミコロンが自動的に挿入されたかのように振る舞う。これを、自動セミコロン挿入(Automatic Semicolon Insertion)

ECMA-262 Edition 5.1 §7.9が規定する、自動セミコロン挿入の定義を、本記事では解説する。

まず、三つの基本的なルールがある。

  • プログラムを左から右にパースした時に、文法上許されないトークン(反則トークン, offending token)があった場合、以下の二つの条件のうちどちらかひとつ、もしくは両方を満たせば、セミコロンが自動的に挿入される。

    • 反則トークンと前のトークンが、ひとつ以上の行終端子で分かたれている場合

      // 例
      var x
      x
      x
      x
      

      これは、以下のようにセミコロンが自動挿入される。

      // 自動セミコロン挿入後
      var x ;
      x ;
      x ;
      x ;
      
    • 反則トークンが}である場合

      // 例
      function f(){ var x }
      
      // 自動セミコロン挿入後
      function f(){ var x ; }
      
  • プログラムを左から右にパースした時に、トークン列の最後に到達したが、正しい文法を構築できない場合、トークン列の最後にセミコロンが自動的に挿入される。

    // 例
    var x
    
    // 自動セミコロン挿入後
    var x ;
    
  • インクリメント、デクリメント、continue、break, return, throwの間で、行終端子が許されていない場所に行終端子がある場合、セミコロンが自動的に挿入される。

    LeftHandSideExpression [行終端子不許可] ++
    LeftHandSideExpression [行終端子不許可] --
    continue [行終端子不許可] Identifier ;
    break [行終端子不許可] Identifier ;
    return [行終端子不許可] Expression ;
    throw [行終端子不許可] Expression ;
    

最後のルールは、たとえば以下のようになる。

var i = 0 ;

i // 自動セミコロン挿入
++ ; // 文法エラー
i // 自動セミコロン挿入
-- ; // 文法エラー

function f()
{
    return // 自動セミコロン挿入、undefinedが返される。
    {
    // JSON的な何か
    } ;
}

ただし、自動挿入したセミコロンが空文に解釈される場合と、for文のヘッダーの中では、自動セミコロン挿入は行われない。

// 空文に解釈される場合
if( cond )
else

これは、もし自動セミコロン挿入が行われるとするならば、以下のようになる。

// 空文に解釈される場合
if( cond ) ;
else ;

このセミコロン挿入は、どちらも空文となるので、自動セミコロン挿入は行われない。

for文のヘッダーとは、for ( ... ; ... ; ... )のことだ。これにも自動セミコロン挿入は行われない。

さて、なぜ自動セミコロン挿入などという規則が存在するのか。思うに、ECMAScriptというのは、規格があって、しかる後にJavaScriptとして実装された言語でではない。JavaScriptという実装だけが先行して、あとからデファクトスタンダードとなった挙動を、ECMAScriptとして追認した形なのだ。規格の責任ではない。無秩序に進化した実装の歴史的経緯の問題である。したがって、既存の実装の挙動を、なるべく正確に規格に落としこんでいる。ECMA-262 Edition 5.1は、既存の実装の挙動を規格に落としこむという点で、非常にいい仕事をしたと思う。文面は読みやすい。JavaScriptは、C++より落とし穴が多い言語であるが、ECMA-262 Edition 5.1で、だいぶ救われている。

なお、規格では、自動セミコロン挿入には頼るべきではなく、明示的にセミコロンを書くべきだとしている。

ドワンゴ広告

この記事は、ドワンゴで最も怠惰な社員である筆者が、出社早々To Court The Kingで遊んだあとに、超チューニング祭に向けて準備をするふりをして書いた。まだバレていないようだ。

そういえば、昨日、珍しく時間の指定されて参加する必要のある社内会議があったので、予定時間の5分前に会議室に行った所、まだ誰も集まっていないどころか、会議室が別の会議で使用中であった。仕方がないので、一旦引き上げて、予定時間の2分後に会議室に行った所、前の会議の参加者は引き上げた上に、すでに全員集まって着席していた。一体、わずか7分間の間に何があったのか。

ドワンゴは本物のC++プログラマーを募集しています。

採用情報|株式会社ドワンゴ

CC BY-ND 4.0: Creative Commons — Attribution-NoDerivatives 4.0 International — CC BY-ND 4.0

9 comments:

Anonymous said...

>JSON的な何か
この場合オプジェクトではなくブロック文として解釈されるので
プロパティを2つ以上並べた時点で文法エラーになりますね。

Anonymous said...

セミコロンは反則トークンの直前に挿入されるので、「var x、改行、セミコロン、x、...」になります

Anonymous said...

ウェブサイト用に作られた言語なので、粗雑なスクリプトでも実行してしまうように強引に作った仕様でしょうね。もしC言語みたいな利用状況ならば、エラーを吐けば終い(むしろエラーを吐くべき)なわけですが。

Anonymous said...

むしろ自動セミコロン挿入はあって当然だと思う。
仕様が別に強引だとも思わない。

Anonymous said...

>自動セミコロン挿入には頼るべきではなく、明示的にセミコロンを書くべきだとしている。

規格すらこういってるのにあって当然って感覚がわからないなぁ。

Anonymous said...

個人的には、セミコロンの自動挿入は削除して欲しいです。
コード読むとき頭で2回パースしないといけないので効率悪いです。
それに、セミコロン挿入が悪い働きをするケースもあったと思うので削除して欲しいです。

Hikaru said...
This comment has been removed by the author.
Hikaru said...
This comment has been removed by the author.
tai2 said...

「なお、規格では、自動セミコロン挿入には頼るべきではなく、明示的にセミコロンを書くべきだとしている。」は、"In the circumstance that an assignment statement must begin with a left parenthesis, it is a good idea for the programmer to provide an explicit semicolon at the end of the preceding statement rather than to rely on automatic semicolon insertion." ここを指して言ってるのですかね。だとすると、そこまで強い言明はしてないのでは。