Scalaのソースコードを読んでみる　その５


[前回](http://qiita.com/JunSuzukiJapan@github/items/14b504ac304d420abaf2)からの続きです。

# トップレベルの解析

トップレベルの構文解析は、メソッドtopStatSeq()で行われているようです。
見てみましょう。


```scala:Parsers.scala
    /** {{{
     *  TopStatSeq ::= TopStat {semi TopStat}
     *  TopStat ::= Annotations Modifiers TmplDef
     *            | Packaging
     *            | package object objectDef
     *            | Import
     *            |
     *  }}}
     */
    def topStatSeq(): List[Tree] = {
      val stats = new ListBuffer[Tree]
      while (!isStatSeqEnd) {
        stats ++= (in.token match {
          case PACKAGE  =>
            packageOrPackageObject(in.skipToken()) :: Nil
          case IMPORT =>
            in.flushDoc
            importClause()
          case x if x == AT || isTemplateIntro || isModifier =>
            joinComment(topLevelTmplDef :: Nil)
          case _ =>
            if (isStatSep) Nil
            else syntaxErrorOrIncompleteAnd("expected class or object definition", skipIt = true)(Nil)
        })
        acceptStatSepOpt()
      }
      stats.toList
    }
```

前回は書き忘れていましたが、すべての生成規則（を表すメソッド）には、
コメントがついていて、そこで拡張BNF（？）で対応する構文が示されています。

```text
TopStatSeq ::= TopStat {semi TopStat}
TopStat ::= Annotations Modifiers TmplDef
          | Packaging
          | package object objectDef
          | Import
          |
```

の部分ですね。
これを見ると、TopStatSeqは、１個以上のTopStatが連続したものになります。
そして、TopStatは、
　Annotations Modifiers TmplDef
の並びか、
　Packaging
か
　package object objedtDef
の並びか
　Import
か
　空文
ですね。

実際に、メソッドtopStatSeq()では、最初のトークンによって上記の場合分けをしているようです。
さて、ここでtopStatSeq()のなかの

```scala
          case x if x == AT || isTemplateIntro || isModifier =>
            joinComment(topLevelTmplDef :: Nil)
```

という部分に注目してみます。
x == AT は、おそらく’＠’かどうかでしょうし、
isModifier は、public, abstract などのモディファイアの判定だろうと想像はつきますが、
isTemplateIntroとは何を表しているのでしょうか。
実際に定義を見てみましょう。
検索すると、６２４行目あたりにありました。

```scala
    def isTemplateIntro: Boolean = in.token match {
      case OBJECT | CASEOBJECT | CLASS | CASECLASS | TRAIT  => true
      case _                                                => false
    }
```

これをみると、現在のトークンが
 OBJECT, CASEOBJECT, CLASS, TRAIT
の場合にのみ真になるようです。

**もしも、クラスやトレイトなどと同じレベル（？）の構文を追加したい場合には、このisTemplateIntroに変更を加える必要がありそうです。**

# コメントによる区分

ちょっと話は、ずれますが、ここまでParsers.scalaを眺めてきて気になったのが、
上記isTemplateIntroよりもちょっと上、５９９行目あたりにある

```scala
/* -------------- TOKEN CLASSES ------------------------------------------- */
```

というコメントです。

これだけなら、普通にコメントだな、と読み流すんですが、
これ以外にも、似たようなタイプのコメントがあちこちに散りばめられています。
この手のコメント（"/\*" と "\*/"に囲まれた１行だけのもの）だけ抽出してみます。

```scala
/* --------------- PLACEHOLDERS ------------------------------------------- */
/* ------------- ERROR HANDLING ------------------------------------------- */
/* -------------- TOKEN CLASSES ------------------------------------------- */
/* --------- COMMENT AND ATTRIBUTE COLLECTION ----------------------------- */
/* ---------- TREE CONSTRUCTION ------------------------------------------- */
/* --------- OPERAND/OPERATOR STACK --------------------------------------- */
/* -------- IDENTIFIERS AND LITERALS ------------------------------------------- */
/* ------------- NEW LINES ------------------------------------------------- */
/* ------------- TYPES ---------------------------------------------------- */
/* ----------- EXPRESSIONS ------------------------------------------------ */
/* -------- PATTERNS ------------------------------------------- */
/* -------- MODIFIERS and ANNOTATIONS ------------------------------------------- */
/* -------- PARAMETERS ------------------------------------------- */
/* -------- DEFS ------------------------------------------- */
/* -------- TEMPLATES ------------------------------------------- */
/* -------- STATSEQS ------------------------------------------- */
```

こうやって並べてみると、生成規則の種類（エラーハンドリングなどの役割）ごとに整理されているようです。
これがわかれば、探したい規則がどの辺にあるかわかりますね。


（つづく）