如何使 Scala 解析器失败 [英] how to make scala parser fail

查看:32
本文介绍了如何使 Scala 解析器失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有这样的事情:

class MyParser 扩展 JavaTokenParsers {var m = new HashMap[String,String]def store = ("var" ~> ident "=") ~ ident ^^ {情况k~v=>m += k ->v}定义存储值 = 标识 ^^ {情况k=>米(k)}}

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

我尝试像这样实现stored_val:

def stored_val = ident =>{情况k=>if (m.contains(k)) m(k) else 失败(未找到标识符")}

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

解决方案

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

def elem (kind: String, p: (Elem) ⇒ Boolean) : Parser[Elem]

<块引用>

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

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

import scala.util.parsing.combinator.syntactical._导入 scala.util.parsing.combinator._特质表达case class EConstant(value: Int) extends Expressioncase class EAdd(lhs: Expression, rhs: Expression) extends Expression对象 ExpressionParser 扩展了 StandardTokenParsers {lexical.delimiters ++= List("+")defoddValue = elem("odd", { x => x.toString.toInt % 2 == 1 }) ^^ {x =>EConstant(x.toString.toInt) }def 值 = numericLit ^^ { x =>EConstant(x.toInt) }def sum =oddValue ~ "+" ~oddValue ^^ { case left ~ "+" ~ right =>EAdd(左,右)}def expr = ( sum | value )def解析(s:字符串)= {val 标记 = 新 lexical.Scanner(s)短语(expr)(令牌)}def apply(s:String): Expression = parse(s) match {案例成功(树,_)=>树情况e:NoSuccess =>throw new IllegalArgumentException("语法错误:"+s)}}

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

scala>:l ExpressionParser.scala正在加载 ExpressionParser.scala...导入 scala.util.parsing.combinator.syntactical._导入 scala.util.parsing.combinator._定义的特征表达定义类 EConstant定义类 EAdd定义模块 ExpressionParser标度>ExpressionParser("2 + 2")java.lang.IllegalArgumentException:语法错误:2 + 2在 ExpressionParser$.apply(:42)在 .<init>(<console>:24)在 .<clinit>(<控制台>)在 RequestResult$.(:9)在 RequestResult$.()在 RequestResult$scala_repl_result()在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)在 java.lang.reflect.Method.invoke(Method.java:597)在 scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)在 scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)在 scala.util.con...标度>表达式解析器("1 + 1")res3:表达式 = EAdd(EConstant(1),EConstant(1))

so I have something like this:

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)
    }
}

And my problem is that what I really want to do is have the parser stored_val fail so that other parsers have the chance to match the input. But what happens now is that the map throws when it can't find the value.

I tried implementing stored_val like this:

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

But the problem with that is failure returns Parser[Nothing] which is a different type than String.

解决方案

If you want to check the content of the characters beyond regex, you might want to check out StandardTokenParser. In particular,

def elem (kind: String, p: (Elem) ⇒ Boolean) : Parser[Elem]

A parser matching input elements that satisfy a given predicate elem(kind, p) succeeds if the input starts with an element e' for which p(e) is true.

Edit: For examples of Standard Token Parser, check out Jim McBeath's article on Scala Parser Combinators. I made a quick modification to the first example to demonstrate elem. It's a simple parser that only takes sum of odd numbers:

import scala.util.parsing.combinator.syntactical._
import scala.util.parsing.combinator._

trait Expression
case class EConstant(value: Int) extends Expression
case class EAdd(lhs: Expression, rhs: Expression) extends Expression

object ExpressionParser extends StandardTokenParsers {
  lexical.delimiters ++= List("+")

  def oddValue = elem("odd", { x => x.toString.toInt % 2 == 1 }) ^^ {
    x => EConstant(x.toString.toInt) }
  def value = numericLit ^^ { x => EConstant(x.toInt) }

  def sum = oddValue ~ "+" ~ oddValue ^^ { case left ~ "+" ~ right =>
          EAdd(left, right) }

  def expr = ( sum | value )

  def parse(s:String) = {
    val tokens = new lexical.Scanner(s)
    phrase(expr)(tokens)
  }

  def apply(s:String): Expression = parse(s) match {
    case Success(tree, _) => tree
    case e: NoSuccess =>
      throw new IllegalArgumentException("Bad syntax: "+s)
  }
}

Save the above as ExpressionParser.scala and load it into REPL as follows:

scala> :l ExpressionParser.scala     
Loading ExpressionParser.scala...
import scala.util.parsing.combinator.syntactical._
import scala.util.parsing.combinator._
defined trait Expression
defined class EConstant
defined class EAdd
defined module ExpressionParser

scala> ExpressionParser("2 + 2")
java.lang.IllegalArgumentException: Bad syntax: 2 + 2
    at ExpressionParser$.apply(<console>:42)
    at .<init>(<console>:24)
    at .<clinit>(<console>)
    at RequestResult$.<init>(<console>:9)
    at RequestResult$.<clinit>(<console>)
    at RequestResult$scala_repl_result(<console>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)
    at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)
    at scala.util.con...
scala> ExpressionParser("1 + 1")
res3: Expression = EAdd(EConstant(1),EConstant(1))

这篇关于如何使 Scala 解析器失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆