Scala JavaTokenParsers 动态解析

Scala JavaTokenParsers dynamic parsing

我正在尝试使用 JavaTokenParser 来解析字符串的多次重复,这些字符串从前一个标记中读取大小, 即

list-name:5
ABCDE

second-list-name:2
AB  //<--the length of the string determines by the value at the token before

因此 repN 将由列表名称后的标记 I 确定

def body = (listname <~ ":") ~ (numOfRepeat <~ LF) ~ repN(?, char)
def char = """[A-Z]""".r

有什么技巧可以将 just-passed-token (numOfRepeat) 作为 Int 值传递给下一个解析器 (repN)?

谢谢!

是的!—这正是单子解析允许您做的:让后续解析依赖于先前的结果。例如:

import scala.util.parsing.combinator._

object parser extends JavaTokenParsers {
  override val skipWhitespace = false

  val lengthAndBody: Parser[String] = for {
    _ <- ident
    _ <- literal(":")
    n <- decimalNumber
    _ <- literal("\n")
    body <- repN(n.toInt, "[A-Z]".r)
  } yield body.mkString

  def apply(in: String) = parseAll(lengthAndBody, in)
}

然后:

scala> parser("""listName:5\nABCDE""")
res5: parser.ParseResult[String] = [1.18] parsed: ABCDE

但是:

scala> parser("""listName:5\nABCD""")
res6: parser.ParseResult[String] =
[1.17] failure: string matching regex `[A-Z]' expected but end of source found

listName:5\nABCD
                ^

并且:

scala> parser("""listName:5\nABCDEF""")
res7: parser.ParseResult[String] =
[1.18] failure: string matching regex `\z' expected but `F' found

listName:5\nABCDEF
                 ^

您还可以将 ~>^^ 等运算符与 >> 一起使用,后者是 flatMap 的别名,但我个人认为 for-在这种情况下理解更清楚了。