Как сказал Дэниел, вам лучше позволить парсеру пропускать пропуски, чтобы минимизировать ваш код.Однако вам может потребоваться настроить значение whitespace
, чтобы вы могли явно сопоставить конец строки .Я сделал это ниже, чтобы парсер не перемещался на следующую строку, если значение для записи не определено.
Насколько это возможно, попробуйте использовать парсеры, определенные в JavaTokenParsers
, например, ident
, если выхотите сопоставить буквенные слова.
Чтобы упростить отслеживание ошибок, выполните NoSuccess
сопоставление для parseAll
, чтобы вы могли увидеть, в какой момент произошел сбой синтаксического анализатора.
import util.parsing.combinator._
val input = """0 fruit
1 id 2
1 name apple
2 type red
3 size large
3 origin Texas, US
2 var_without_value
2 date 2 aug 2011
0 fruit
1 id 3
1 name apple
2 type green
3 size small
3 origin Florida, US
2 date 3 Aug 2011"""
object TreeParser extends JavaTokenParsers {
override val whiteSpace = """[ \t]+""".r
val level = """[1-3]{1}""".r
val value = """[a-zA-Z0-9_, ]*""".r
val eol = """[\r?\n]+""".r
def recordBegin = "0" ~ ident <~ eol
def recordItem = level ~ ident ~ opt(value) <~ opt(eol) ^^ {
case l ~ n ~ v => (l.toInt, n, v.getOrElse(""))
}
def record = recordBegin ~> rep1(recordItem)
def file = rep1(record)
def parse(input: String) = parseAll(file, input) match {
case Success(result, _) => result
case NoSuccess(msg, _) => throw new RuntimeException("Parsing Failed:" + msg)
}
}
val result = TreeParser.parse(input)
result.foreach(println)