可能会影响您选择的一件事是是否可以在您的有效解析器中找到 cmets。例如,假设您有类似的东西:
val p = "(" ~> "[a-z]*".r <~ ")"
它会解析 ( abc ) 之类的东西,但由于 cmets 你实际上可能会遇到类似的东西:
( ; comment goes here
abc
)
那么我会推荐使用TokenParser 或其子类之一。这是更多的工作,因为您必须提供一个词法解析器,该解析器将首先通过丢弃 cmets。但是,如果您有嵌套的 cmets,或者如果 ; 可以转义,或者如果 ; 可以在字符串文字内,它也会更加灵活,例如:
abc = "; don't ignore this" ; ignore this
另一方面,您也可以尝试覆盖 whitespace 的值,使其类似于
override protected val whiteSpace = """(\s|;.*)+""".r
或者类似的东西。
例如使用 RegexParsers scaladoc 中的示例:
import scala.util.parsing.combinator.RegexParsers
object so1 {
Calculator("""(1 + ; foo
(1 + 2))
; bar""")
}
object Calculator extends RegexParsers {
override protected val whiteSpace = """(\s|;.*)+""".r
def number: Parser[Double] = """\d+(\.\d*)?""".r ^^ { _.toDouble }
def factor: Parser[Double] = number | "(" ~> expr <~ ")"
def term: Parser[Double] = factor ~ rep("*" ~ factor | "/" ~ factor) ^^ {
case number ~ list => (number /: list) {
case (x, "*" ~ y) => x * y
case (x, "/" ~ y) => x / y
}
}
def expr: Parser[Double] = term ~ rep("+" ~ log(term)("Plus term") | "-" ~ log(term)("Minus term")) ^^ {
case number ~ list => list.foldLeft(number) { // same as before, using alternate name for /:
case (x, "+" ~ y) => x + y
case (x, "-" ~ y) => x - y
}
}
def apply(input: String): Double = parseAll(expr, input) match {
case Success(result, _) => result
case failure: NoSuccess => scala.sys.error(failure.msg)
}
}
打印出来:
Plus term --> [2.9] parsed: 2.0
Plus term --> [2.10] parsed: 3.0
res0: Double = 4.0