Skip to content

Commit

Permalink
fix issue djspiewak#34
Browse files Browse the repository at this point in the history
  • Loading branch information
Satoshi Ogasawara authored and Satoshi Ogasawara committed Jan 12, 2019
1 parent 8aeb1a9 commit 28609ea
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 8 deletions.
18 changes: 11 additions & 7 deletions core/src/main/scala/parseback/parsers.scala
Expand Up @@ -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] =
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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] {
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/parseback/render/Renderer.scala
Expand Up @@ -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) =>
Expand Down
11 changes: 11 additions & 0 deletions core/src/test/scala/parseback/ast/FilterSpecs.scala
Expand Up @@ -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))))
}

}

// %%
Expand Down

0 comments on commit 28609ea

Please sign in to comment.