使用〜>放弃scala解析器组合器中的几个文字。 <〜

时间:2013-06-09 01:52:30

标签: scala parser-combinators

我在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代码中放弃“(”,“)”文字而不需要括号。 有干净的方法吗?

1 个答案:

答案 0 :(得分: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)
}

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