简体   繁体   English

解析器组合器处理与可选解析器的交替

[英]Parser combinator handling alternation with an optional parser

I have a parser p of type Parser[Option[X]] and another q of type Parser[Y] .我有一个Parser[Option[X]]类型的解析器p和另一个Parser[Y]类型的q ( X and Y are concrete types but that's not important here). XY是具体类型,但这在这里并不重要)。

I'd like to combine them in such a way that the resulting parser returns a Parser[Either[X, Y]] .我想以生成的解析器返回Parser[Either[X, Y]]的方式组合它们。 This parser will succeed with Left(x) if p yields Some(x) or, failing that, it will succeed with Right(y) if q yields a y .如果p产生Some(x) ,则此解析器将通过Left(x)成功,否则,如果q产生y ,它将通过Right(y)成功。 Otherwise, it will fail.否则,它将失败。 Input will be consumed in the successful cases but not in the unsuccessful case.输入将在成功的情况下被消耗,但在不成功的情况下不会被消耗。

I'd appreciate any help with this as I can't quite figure out how to make it work.我将不胜感激,因为我不太清楚如何让它发挥作用。

A little more perseverance after taking a break and I was able to solve this.休息后再坚持一点,我就解决了这个问题。 I don't think my solution is the most elegant and would appreciate feedback:我认为我的解决方案不是最优雅的,希望得到反馈:

def compose[X, Y](p: Parser[Option[X]], q: Parser[Y]): Parser[Either[X, Y]] = Parser {
  in =>
    p(in) match {
      case s@this.Success(Some(_), _) => s map (xo => Left(xo.get))
      case _ => q(in) match {
        case s@this.Success(_, _) => s map (x => Right(x))
        case _ => this.Failure("combine: failed", in)
      }
    }
}

implicit class ParserOps[X](p: Parser[Option[X]]) {
  def ?|[Y](q: => Parser[Y]): Parser[Either[X, Y]] = compose(p, q)
}

// Example of usage
def anadicTerm: Parser[AnadicTerm] = (maybeNumber ?| anadicOperator) ^^ {
  case Left(x: Number) => debug("anadicTerm (Number)", AnadicTerm(Right(x)))
  case Right(x: String) => debug("anadicTerm (String)", AnadicTerm(Left(x)))
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM