如何让这个简单的正则表达式解析器捕捉布尔表达式?

How to get this simple regex-parser to catch a Boolean expression?

我试图用 Scala 理解解析器组合器,并编写了以下内容:

import scala.util.parsing.combinator._

class SimpleParser extends RegexParsers {

  def operand: Parser[String] = "[A-Za-z]+".r ^^ {_.toString}

  def operator: Parser[String] = "OR|AND".r ^^ {_.toString}

  def term: Parser[String] = (("(" ~> (operand ~ operator ~ operand) <~ ")")) ^^ {
    case o1 ~ operator ~ o2 => o1 + " " + operator + " " + o2
    case _ => " "
  }


  def expression: Parser[String] = (operand | term | (operand ~ operator ~ term))^^ {
    case str:String => str
    case operand ~ operator ~ term => operand + " " + operator + " " + term
  }
}

object ParserTest extends SimpleParser{
  def main(args: Array[String]): Unit = {
     println(parseAll(expression, "A").get)
     println(parseAll(expression, "(A OR C)").get)
     println(parseAll(expression, "A AND (A OR C)").get)
  }
}

前两幅作品找到,而最后一幅导致:

Exception in thread "main" java.lang.RuntimeException: No result when parsing failed at scala.sys.package$.error(package.scala:27)
at scala.util.parsing.combinator.Parsers$NoSuccess.get(Parsers.scala:181)
at scala.util.parsing.combinator.Parsers$NoSuccess.get(Parsers.scala:167)
at ParserTest$.main(ParserTest.scala:31)
at ParserTest.main(ParserTest.scala)

我认为最后一句话会匹配 "expression" 中的(操作数 ~ 运算符 ~ 术语)模式。有人可以向我解释为什么我的模式是错误的,并且可以显示 write 模式以匹配最后的 print 语句吗?

首先,您没有正确处理 parseAll 的结果。如果你是,你会看到在最后一个例子中,它返回了一个 Failure 和消息

[1.3] failure: end of input expected

A AND (B OR C)
  ^

这里的问题是你的解析器在 expression 中的顺序错误。

创建解析器的析取 (uisng |) 时,您始终必须从 "greediest" 解析器开始。换句话说,这里发生的是 operand 本身成功解析了 "A" 并且解析结束。但是parseAll看到解析成功了但是还有输入,所以returns出现上面的错误。

如果你颠倒 3 个解析器的顺序,那么它看起来像:

def expression: Parser[String] = ((operand ~ operator ~ term) | term | operand)^^

它们现在已正确排序,所有 3 个示例都有效。