как заставить парсер scala провалиться - PullRequest
8 голосов
/ 09 февраля 2011

, поэтому у меня есть что-то вроде этого:

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

И моя проблема в том, что я действительно хочу, чтобы произошел сбой синтаксического анализатора сохраненный_вальчик, чтобы другие парсеры имели возможность сопоставить входные данные.Но теперь происходит то, что карта выдает, когда не может найти значение.

Я пытался реализовать сохраненный_вал следующим образом:

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

Но проблема с этим - ошибка, возвращает Parser [Ничего], который отличается от типа String.

Ответы [ 2 ]

8 голосов
/ 20 февраля 2013

Вы можете использовать комбинатор ^?, который принимает частичную функцию ( Scaladoc ):

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

Я отправил полный пример с тестами на Github.

3 голосов
/ 09 февраля 2011

Если вы хотите проверить содержимое символов за пределами регулярного выражения, вы можете проверить StandardTokenParser. В частности,

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

Парсер, сопоставляющий входные элементы, которые удовлетворяют данному предикату elem(kind, p) завершается успешно, если ввод начинается с элемента e', для которого p(e) имеет значение true.

Редактировать : Примеры стандартного анализатора токенов можно найти в статье Джима Макбита о Scala Parser Combinators . Я сделал быструю модификацию первого примера, чтобы продемонстрировать elem. Это простой парсер, который принимает только сумму нечетных чисел:

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

Сохраните вышеуказанное как ExpressionParser.scala и загрузите его в REPL следующим образом:

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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...