Scalaでパーサコンビネータ

Scala 2.6.0-RC1 でscala.util.parsing.combinatorが標準パッケージになりました。というわけでリファレンスとちょっとしたサンプルくらしかなかったのだけど、とりあえず書いてみた。

どう書く?orgに投稿した、ExcelライクCSVのパーサ。

scala code
  1. import scala.util.parsing.combinator.{Parsers, ImplicitConversions, ~, mkTilde}
  2. import scala.util.parsing.input.CharArrayReader
  3. import Character.isISOControl
  4.  
  5. object CSVParser {
  6.  trait Base
  7.  case class Field(s:String) extends Base {
  8.    override def toString = s
  9.  }
  10.  case class Record(fields: List[Field]) extends Base
  11.  case class File(records :List[Record]) extends Base
  12.  
  13.  def mkString(cs :List[Any]) = cs.mkString("")
  14.  class CSVParser extends Parsers {
  15.    type Elem = Char
  16.    def notMeta(c:Elem) = c!=',' && c!='\n' && c!='"' && !isISOControl(c)
  17.  
  18.    lazy val file = record.*('\n') ^^ File
  19.    lazy val record = (field|quotedField|nullableField).*(',') ^^ Record
  20.    lazy val field = chars.+ ^^ {cs => Field(mkString(cs))}
  21.    lazy val nullableField = chars.* ^^ {cs => Field("")}
  22.    lazy val quotedField = '"' ~ (charsInQuote|quoteInQuote).* ~ '"' ^^ {cs => Field(mkString(cs))}
  23.    lazy val charsInQuote = elem("chars in field", _!='"')
  24.    lazy val quoteInQuote = repN(2, quote) ^^ {cs => '"'}
  25.    lazy val quote = '"' ^^ success
  26.    lazy val chars = elem("chars", notMeta)
  27.  }
  28. }
  29.  
  30. val data = """
  31. "aaa","b
  32. bb","ccc",zzz,"y""Y""y",xxx
  33. """.trim
  34.  
  35. (new CSVParser.CSVParser).file(new
  36. CharArrayReader(data.toCharArray)).map(file => {
  37.  file.records.map({record =>
  38.    val fields = record.fields
  39.    (1 to fields.length).foreach(i => println(i +" => " + fields(i-1)))
  40.  })
  41. })
  42.  

とりあえずこんな感じ。これはダイレクトにParsersクラスを直接継承してるけど、StdTokenParsersってかんじのParserもあるし、StdLexicalってかんじなLexerもあってこれはなかなか。

時間が出来たらもうちょっといじってみよう。よさげな解説してるサイトがあったら是非教えてください。

Related posts:

07.27.08/12am

No comments yet

trackback uri
  • ajax-loading
  • ajax-loading
  • ajax-loading

Leave a Comment

You can use these tags: <code>, <i>, <em>, <strong>, <a>

About

Author:yuin(http://inforno.net/)

文学部文化学科卒という生粋の文系趣味プログラマ。

主にRuby、Javascript、PHP、JAVA,Python,C,Scala,Schemeなどを使っています。今はPythonな感じかもしれない。今後作曲活動なども復活するかもしれない。

Pages