Permalink
Browse files

fix issue #34

  • Loading branch information...
Satoshi Ogasawara Satoshi Ogasawara
Satoshi Ogasawara authored and Satoshi Ogasawara committed Dec 30, 2018
1 parent 8aeb1a9 commit 28609eab643c42c45ff855b95d51bada516e3eb5
@@ -53,7 +53,10 @@ sealed trait Parser[+A] {

final def map2[B, C](that: Parser[B])(f: (A, B) => C): Parser[C] = (this ~ that) map f.tupled

def filter(p: A => Boolean): Parser[A] = Parser.Filter(this, p)
def filter(p: A => Boolean): Parser[A] = Parser.Filter(this, false, p)

// filter out but at least leave one element.
def filterLeaveOne(p: A => Boolean): Parser[A] = Parser.Filter(this, true, p)

// TODO come up with a better name
final def ~!~[B](that: Parser[B]): Parser[A ~ B] =
@@ -131,7 +134,7 @@ sealed trait Parser[+A] {
case Apply(target, _, _) =>
markRoots(target, tracked2)

case Filter(target, _) =>
case Filter(target, _, _) =>
markRoots(target, tracked2)

case _ => tracked
@@ -195,7 +198,7 @@ sealed trait Parser[+A] {
p.nullableMemo = inner(target, tracked)
p.nullableMemo

case p @ Filter(target, _) =>
case p @ Filter(target, _, _) =>
p.nullableMemo = inner(target, tracked)
p.nullableMemo

@@ -465,17 +468,18 @@ object Parser {
}
}

final case class Filter[A](target: Parser[A], p: A => Boolean) extends Parser[A] {
final case class Filter[A](target: Parser[A], leaveOne: Boolean, p: A => Boolean) extends Parser[A] {
nullableMemo = target.nullableMemo

override def filter(p2: A => Boolean): Parser[A] =
Filter(target, { a: A => p(a) && p2(a) })
Filter(target, leaveOne, { a: A => p(a) && p2(a) })

protected def _derive(line: Line, table: MemoTable) =
Filter(target.derive(line, table), p)
Filter(target.derive(line, table), leaveOne, p)

protected def _finish(seen: Set[ParserId[_]], table: MemoTable) =
target.finish(seen, table) pmap { _ filter p }
// if the Result is unique, no need to filter out.
target.finish(seen, table) pmap { c => if(c.length == 1 && leaveOne) c else c filter p }
}

final case class Literal(literal: String, offset: Int = 0) extends Parser[String] {
@@ -127,7 +127,7 @@ object Renderer {
case Apply(target, _, _) =>
State pure (Left(target) :: Right("") :: Right("λ") :: Nil)

case Filter(target, _) =>
case Filter(target, _, _) =>
State pure (Left(target) :: Nil)

case Literal(literal, offset) =>
@@ -148,6 +148,17 @@ object FilterSpecs extends ParsebackSpec {
expr must parseOk("1 - 2 + 3")(Add(Sub(IntLit(1), IntLit(2)), IntLit(3)))
expr must parseOk("1 + 2 * 3")(Add(IntLit(1), Mul(IntLit(2), IntLit(3))))
}

"disambiguate left-associativity with explicit parenthesis" in {
lazy val expr: Parser[Expr] = (
expr ~ "+" ~ expr ^^ { (_, e1, _, e2) => Add(e1, e2) }
| "(" ~> expr <~ ")"
| num ^^ { (_, n) => IntLit(n) }
) filterLeaveOne prec(Add)

expr must parseOk("1 + (2 + 3)")(Add(IntLit(1), Add(IntLit(2), IntLit(3))))
}

}

// %%

0 comments on commit 28609ea

Please sign in to comment.