From 489581d90b1a851fc75c47cc967d6f7d990f8de3 Mon Sep 17 00:00:00 2001 From: Eike Kettner Date: Mon, 1 Mar 2021 20:26:30 +0100 Subject: [PATCH] Fix parsing nested expressions Since whitespace is used as a separator, it cannot be consumed by and/or parens. --- .../docspell/query/internal/BasicParser.scala | 6 ++--- .../query/internal/ExprParserTest.scala | 22 +++++++++++++++++++ .../query/internal/SimpleExprParserTest.scala | 4 ++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/modules/query/src/main/scala/docspell/query/internal/BasicParser.scala b/modules/query/src/main/scala/docspell/query/internal/BasicParser.scala index c4edd070..bb38fc90 100644 --- a/modules/query/src/main/scala/docspell/query/internal/BasicParser.scala +++ b/modules/query/src/main/scala/docspell/query/internal/BasicParser.scala @@ -21,13 +21,13 @@ object BasicParser { (('A' to 'Z') ++ ('a' to 'z') ++ ('0' to '9') ++ "-_.").toSet val parenAnd: P[Unit] = - P.stringIn(List("(&", "(and")).void.surroundedBy(ws0) + P.stringIn(List("(&", "(and")).void <* ws0 val parenClose: P[Unit] = - P.char(')').surroundedBy(ws0) + ws0.soft.with1 *> P.char(')') val parenOr: P[Unit] = - P.stringIn(List("(|", "(or")).void.surroundedBy(ws0) + P.stringIn(List("(|", "(or")).void <* ws0 val identParser: P[String] = P.charsWhile(identChars.contains) diff --git a/modules/query/src/test/scala/docspell/query/internal/ExprParserTest.scala b/modules/query/src/test/scala/docspell/query/internal/ExprParserTest.scala index 6f0fe07f..07e14e9b 100644 --- a/modules/query/src/test/scala/docspell/query/internal/ExprParserTest.scala +++ b/modules/query/src/test/scala/docspell/query/internal/ExprParserTest.scala @@ -67,4 +67,26 @@ class ExprParserTest extends FunSuite with ValueHelper { ) ) } + + test("nest and/ with simple expr") { + val p = ExprParser.exprParser + assertEquals( + p.parseAll("(& (& f:usd=\"4.99\" ) source:*test* )"), + Right( + Expr.and( + Expr.and(Expr.CustomFieldMatch("usd", Operator.Eq, "4.99")), + Expr.string(Operator.Like, Attr.ItemSource, "*test*") + ) + ) + ) + assertEquals( + p.parseAll("(& (& f:usd=\"4.99\" ) (| source:*test*) )"), + Right( + Expr.and( + Expr.and(Expr.CustomFieldMatch("usd", Operator.Eq, "4.99")), + Expr.or(Expr.string(Operator.Like, Attr.ItemSource, "*test*")) + ) + ) + ) + } } diff --git a/modules/query/src/test/scala/docspell/query/internal/SimpleExprParserTest.scala b/modules/query/src/test/scala/docspell/query/internal/SimpleExprParserTest.scala index 32c152a0..7a107ad7 100644 --- a/modules/query/src/test/scala/docspell/query/internal/SimpleExprParserTest.scala +++ b/modules/query/src/test/scala/docspell/query/internal/SimpleExprParserTest.scala @@ -173,6 +173,10 @@ class SimpleExprParserTest extends FunSuite with ValueHelper { p.parseAll("f:usd=26.66"), Right(Expr.CustomFieldMatch("usd", Operator.Eq, "26.66")) ) + assertEquals( + p.parseAll("f:usd=\"26.66\""), + Right(Expr.CustomFieldMatch("usd", Operator.Eq, "26.66")) + ) } }