3

我正在使用 Scala 中的解析器组合器解析一种语言,我想表达 CFG 规则

stmt -> if (stmt) {stmt}

自然,我希望在构造结果时丢弃“if(){}”字符串文字。我考虑过的两种方式都很丑陋。

方法 (A) 要求我们在“case”语句中复制字符串文字的位置:

lazy val stmt: PackratParser[Stmt] =
    (
      // other rules...
      | "if"~"("~stmt~")"~"{"~stmt~"}" ^^ { case _~_~s1~_~_~s2~_ ⇒ If(s1, s2) }
    )

由于 ~ 和 ~> 的优先级,方法 (B) 需要混淆括号。

lazy val stmt: PackratParser[Stmt] =
    (
      // other rules...
      | ("if"~>"("~>stmt)~(")"~>"{"~>stmt<~"}") ^^ { case s1~s2 ⇒ If(s1, s2) }
    )

理想情况下,我想丢弃 "(",")" 文字,而不需要在我的 Scala 代码中使用括号。有没有一种干净的方法可以做到这一点?

4

1 回答 1

4

在没有大量括号的情况下避免优先级问题的常用方法是定义一些助手,在我看来,这在这里工作得很好:

val cond       = "(" ~> stmt <~ ")"
val thenClause = "{" ~> stmt <~ "}"
val ifStmt = "if" ~> cond ~ thenClause ^^ { case s1 ~ s2 => If(s1, s2) }

如果由于某种原因这不是一个选项,我肯定会避免使用您的第一种方法,并且我会调整第二种方法以使优先管理括号更清晰地与语法匹配 - 即,如下所示:

"if" ~> ("(" ~> stmt <~ ")") ~ ("{" ~> stmt <~ "}") ^^ {
   case s1 ~ s2 => If(s1, s2)
}

这不是很好,但也不是绝对不可读。

于 2013-06-09T02:31:45.997 回答