[英]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).
( X和Y是具体类型,但这在这里并不重要)。
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.