如何使scala解析器失败

Kev*_*vin 8 scala

所以我有这样的事情:

class MyParser extends JavaTokenParsers {
    var m = new HashMap[String,String]
    def store = ("var" ~> ident "=") ~ ident ^^ {
        case k ~ v => m += k -> v
    }
    def stored_val = ident ^^ {
        case k => m(k)
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是我真正想做的是让解析器stored_val失败,以便其他解析器有机会匹配输入.但现在发生的是当地图无法找到值时会抛出.

我尝试像这样实现stored_val:

def stored_val = ident => {
    case k => if (m.contains(k)) m(k) else failure("identifier not found")
}
Run Code Online (Sandbox Code Playgroud)

但问题是失败返回Parser [Nothing],它与String不同.

小智 8

您可以使用^?接受部分函数的组合子(Scaladoc):

def stored_val: Parser[String] = ident ^? {
    case k if m.contains(k) => m(k)
}
Run Code Online (Sandbox Code Playgroud)

我把一个完整的例子测试到Github上.


Eug*_*ota 3

如果您想检查正则表达式之外的字符内容,您可能需要查看StandardTokenParser. 尤其,

\n\n
def elem (kind: String, p: (Elem) \xe2\x87\x92 Boolean) : Parser[Elem]\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

如果输入以true元素开头,则匹配满足给定谓词的输入元素的解析器\n 会elem(kind, p)成功。e\'p(e)

\n
\n\n

编辑:\n有关标准令牌解析器的示例,请查看 Jim McBeath 关于Scala 解析器组合器的文章。我对第一个示例进行了快速修改以进行演示elem。这是一个简单的解析器,只需要奇数的和:

\n\n
import scala.util.parsing.combinator.syntactical._\nimport scala.util.parsing.combinator._\n\ntrait Expression\ncase class EConstant(value: Int) extends Expression\ncase class EAdd(lhs: Expression, rhs: Expression) extends Expression\n\nobject ExpressionParser extends StandardTokenParsers {\n  lexical.delimiters ++= List("+")\n\n  def oddValue = elem("odd", { x => x.toString.toInt % 2 == 1 }) ^^ {\n    x => EConstant(x.toString.toInt) }\n  def value = numericLit ^^ { x => EConstant(x.toInt) }\n\n  def sum = oddValue ~ "+" ~ oddValue ^^ { case left ~ "+" ~ right =>\n          EAdd(left, right) }\n\n  def expr = ( sum | value )\n\n  def parse(s:String) = {\n    val tokens = new lexical.Scanner(s)\n    phrase(expr)(tokens)\n  }\n\n  def apply(s:String): Expression = parse(s) match {\n    case Success(tree, _) => tree\n    case e: NoSuccess =>\n      throw new IllegalArgumentException("Bad syntax: "+s)\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

将以上内容保存为ExpressionParser.scala并加载到 REPL 中,如下所示:

\n\n
scala> :l ExpressionParser.scala     \nLoading ExpressionParser.scala...\nimport scala.util.parsing.combinator.syntactical._\nimport scala.util.parsing.combinator._\ndefined trait Expression\ndefined class EConstant\ndefined class EAdd\ndefined module ExpressionParser\n\nscala> ExpressionParser("2 + 2")\njava.lang.IllegalArgumentException: Bad syntax: 2 + 2\n    at ExpressionParser$.apply(<console>:42)\n    at .<init>(<console>:24)\n    at .<clinit>(<console>)\n    at RequestResult$.<init>(<console>:9)\n    at RequestResult$.<clinit>(<console>)\n    at RequestResult$scala_repl_result(<console>)\n    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n    at java.lang.reflect.Method.invoke(Method.java:597)\n    at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)\n    at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)\n    at scala.util.con...\nscala> ExpressionParser("1 + 1")\nres3: Expression = EAdd(EConstant(1),EConstant(1))\n
Run Code Online (Sandbox Code Playgroud)\n