テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

(scala report) parser combinator: パースした入力に依存してパーサを切り替える

SGFフォーマットにおけるPropertyは, MessagePackなどと同様によくある形をしており, PropIdentというIDによってその後をどうやってパースするかが決まる. ただしその形は, "PropIdent PropValue+"と決まっていて, PropValueはざっくりいうと"[xxxx]"の形なので, 一度その部分を文字列としてパースしてしまって(PropIdent ~ List[String]を得る)から, 後に変換することも出来るのだが, 本来やりたいことは, 「まずPropIdentを読み込んでからそれに応じてParserを切り替えて, 残った要素をパースするパーサを作る」ということなので, これは, >>=演算子が必要になる. つまり, Applicative Functorの力では足りない.

二日酔いで頭が痛いなりにAPIを調べてみると, ScalaのパーサコンビネータにはflatMap[U](f: (T) => Parser[U]): Parser[U]が実装されている. 同じ型のものでintoというのも提供されているが, きっと同じものだろうと思う.

早い段階で, 超基本的なSGFファイルについてはパース出来るようにしたい. しかし毎回のことだが思っていたよりは骨で, やや苦戦気味といえる.

実験

以下のようなパーサを作る. 頭がIの場合はさらにintを読む. Sならば無条件で成功する. Fならば無条件で失敗する.

  def p = char into {
    case 'I' => int
    case 'S' => success(100)
    case 'F' => failure("F")
  }

これを使って以下のようにパースする.

    println(parseAll(p, "I10"))
    println(parseAll(p, "S"))
    println(parseAll(p, "F"))

結果を見るとうまく行くことが分かる.

[1.4] parsed: 10
[1.2] parsed: 100
[1.2] failure: F