From 8270a6193805069e61666d15ffb71ecb4bc2dcca Mon Sep 17 00:00:00 2001 From: Ben Hermann Date: Sun, 5 Jan 2020 09:25:28 +0100 Subject: [PATCH 1/4] Bumping version --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index b6b6119..3e86cc3 100644 --- a/build.sbt +++ b/build.sbt @@ -29,7 +29,7 @@ ThisBuild / publishTo := { } ThisBuild / publishMavenStyle := true -ThisBuild / version := "0.9.1" +ThisBuild / version := "0.9.2-SNAPSHOT" lazy val scala212 = "2.12.10" lazy val scala213 = "2.13.1" From 54e8c4f8ff6057931ba3216d4566657d7abdc793 Mon Sep 17 00:00:00 2001 From: Ben Hermann Date: Sun, 5 Jan 2020 09:26:40 +0100 Subject: [PATCH 2/4] Extended syntax to allow field selections. Breaking to users. Closes #2 --- .../de/upb/cs/swt/delphi/core/ql/AST.scala | 2 + .../de/upb/cs/swt/delphi/core/ql/Syntax.scala | 10 +- .../upb/cs/swt/delphi/core/SyntaxTest.scala | 112 ++++++++++++++---- 3 files changed, 99 insertions(+), 25 deletions(-) diff --git a/core/src/main/scala/de/upb/cs/swt/delphi/core/ql/AST.scala b/core/src/main/scala/de/upb/cs/swt/delphi/core/ql/AST.scala index e8a7028..0c9e98b 100644 --- a/core/src/main/scala/de/upb/cs/swt/delphi/core/ql/AST.scala +++ b/core/src/main/scala/de/upb/cs/swt/delphi/core/ql/AST.scala @@ -16,6 +16,8 @@ package de.upb.cs.swt.delphi.core.ql +case class Query(expr : CombinatorialExpr, selections : Seq[FieldReference] = Seq()) + trait CombinatorialExpr case class AndExpr(left: CombinatorialExpr, right: CombinatorialExpr) extends CombinatorialExpr diff --git a/core/src/main/scala/de/upb/cs/swt/delphi/core/ql/Syntax.scala b/core/src/main/scala/de/upb/cs/swt/delphi/core/ql/Syntax.scala index dc698ce..24232b5 100644 --- a/core/src/main/scala/de/upb/cs/swt/delphi/core/ql/Syntax.scala +++ b/core/src/main/scala/de/upb/cs/swt/delphi/core/ql/Syntax.scala @@ -28,9 +28,10 @@ import org.parboiled2.{CharPredicate, Parser, ParserInput, Rule1} class Syntax(val input : ParserInput) extends Parser { def QueryRule = rule { - CombinatorialRule ~ EOI + CombinatorialRule ~ zeroOrMore(Whitespace ~ FieldSelection) ~ EOI ~> Query } + // Combinatorial rules. def CombinatorialRule : Rule1[CombinatorialExpr] = rule { OrOrElseRule | NotRule @@ -67,7 +68,8 @@ class Syntax(val input : ParserInput) extends Parser { def IsTrue = rule { FieldReferenceRule ~> IsTrueExpr } // Literals - def FieldReferenceRule = rule { "[" ~ capture(oneOrMore(CharPredicate.AlphaNum ++ '.' ++ '-' ++ ' ' ++ '_' ++ '(' ++ ':' ++')')) ~ "]" ~> FieldReference } + def FieldReferenceRule = rule { "[" ~ capture(oneOrMore(FieldAlphabet)) ~ "]" ~> FieldReference } + def FieldAlphabet = CharPredicate.AlphaNum ++ '.' ++ '-' ++ ' ' ++ '_' ++ '(' ++ ':' ++')' def IntegerLiteral = rule { capture(oneOrMore(CharPredicate.Digit)) } def StringLiteral = rule { '"' ~ capture(oneOrMore(CharPredicate.Printable -- '"' )) ~ '"'} @@ -81,6 +83,10 @@ class Syntax(val input : ParserInput) extends Parser { def OneOrMoreWhitespace = rule { oneOrMore(anyOf(" \n \r")) } + + // Field selection + def FieldSelection = rule { '#' ~ "[" ~ capture(oneOrMore(ExtendedFieldAlphabet)) ~ "]" ~> FieldReference} + def ExtendedFieldAlphabet = FieldAlphabet ++ '*' } diff --git a/core/src/test/scala/de/upb/cs/swt/delphi/core/SyntaxTest.scala b/core/src/test/scala/de/upb/cs/swt/delphi/core/SyntaxTest.scala index 98ab0f7..00aadba 100644 --- a/core/src/test/scala/de/upb/cs/swt/delphi/core/SyntaxTest.scala +++ b/core/src/test/scala/de/upb/cs/swt/delphi/core/SyntaxTest.scala @@ -26,6 +26,7 @@ import scala.util.{Failure, Success} * Tests for the DelphiQL syntax. * * @author Lisa Nguyen Quang Do + * @author Ben Hermann */ class SyntaxTest extends FlatSpec with Matchers { @@ -34,7 +35,7 @@ class SyntaxTest extends FlatSpec with Matchers { parseResult shouldBe a [Success[_]] parseResult match { case Success(ast) => { - ast.toString shouldEqual "EqualExpr(FieldReference(Filter1),abc)" + ast shouldEqual Query(EqualExpr(FieldReference("Filter1"),"abc")) } } } @@ -45,7 +46,7 @@ class SyntaxTest extends FlatSpec with Matchers { parseResult shouldBe a [Success[_]] parseResult match { case Success(ast) => { - ast.toString shouldEqual "IsTrueExpr(FieldReference(Filter1))" + ast shouldEqual Query(IsTrueExpr(FieldReference("Filter1"))) } } } @@ -67,7 +68,11 @@ class SyntaxTest extends FlatSpec with Matchers { parseResult shouldBe a [Success[_]] parseResult match { case Success(ast) => { - ast.toString shouldEqual "AndExpr(IsTrueExpr(FieldReference(Filter1)),EqualExpr(FieldReference(Filter2),3))" + ast shouldEqual + Query( + AndExpr( + IsTrueExpr(FieldReference("Filter1")), + EqualExpr(FieldReference("Filter2"),"3"))) } } } @@ -78,8 +83,13 @@ class SyntaxTest extends FlatSpec with Matchers { parseResult shouldBe a [Success[_]] parseResult match { case Success(ast) => { - ast.toString shouldEqual "OrExpr(IsTrueExpr(FieldReference(Filter1)),AndExpr(IsTrueExpr(FieldReference(Filter2))," + - "OrExpr(LessThanExpr(FieldReference(Filter3),3),GreaterThanExpr(FieldReference(Filter4),0))))" + ast shouldEqual + Query( + OrExpr( + IsTrueExpr(FieldReference("Filter1")), + AndExpr(IsTrueExpr(FieldReference("Filter2")), + OrExpr(LessThanExpr(FieldReference("Filter3"),"3"), + GreaterThanExpr(FieldReference("Filter4"),"0"))))) } } } @@ -90,8 +100,14 @@ class SyntaxTest extends FlatSpec with Matchers { parseResult shouldBe a [Success[_]] parseResult match { case Success(ast) => { - ast.toString shouldEqual "AndExpr(IsTrueExpr(FieldReference(Filter1)),XorExpr(OrExpr(LessThanExpr(FieldReference(Filter2),3)," + - "GreaterThanExpr(FieldReference(Filter2),0)),AndExpr(IsTrueExpr(FieldReference(Filter4)),IsTrueExpr(FieldReference(Filter5)))))" + ast shouldEqual + Query( + AndExpr( + IsTrueExpr(FieldReference("Filter1")), + XorExpr(OrExpr(LessThanExpr(FieldReference("Filter2"),"3"), + GreaterThanExpr(FieldReference("Filter2"),"0")), + AndExpr(IsTrueExpr(FieldReference("Filter4")), + IsTrueExpr(FieldReference("Filter5")))))) } } } @@ -112,8 +128,13 @@ class SyntaxTest extends FlatSpec with Matchers { parseResult shouldBe a [Success[_]] parseResult match { case Success(ast) => { - ast.toString shouldEqual "AndExpr(AndExpr(IsTrueExpr(FieldReference(Filter1))," + - "IsTrueExpr(FieldReference(Filter2))),IsTrueExpr(FieldReference(Filter3)))" + ast shouldEqual + Query( + AndExpr( + AndExpr( + IsTrueExpr(FieldReference("Filter1")), + IsTrueExpr(FieldReference("Filter2"))), + IsTrueExpr(FieldReference("Filter3")))) } } } @@ -123,8 +144,15 @@ class SyntaxTest extends FlatSpec with Matchers { parseResult shouldBe a [Success[_]] parseResult match { case Success(ast) => { - ast.toString shouldEqual "OrExpr(IsTrueExpr(FieldReference(Filter1)),AndExpr(XorExpr(" + - "IsTrueExpr(FieldReference(Filter2)),NotExpr(IsTrueExpr(FieldReference(Filter3)))),IsTrueExpr(FieldReference(Filter4))))" + ast shouldEqual + Query( + OrExpr( + IsTrueExpr(FieldReference("Filter1")), + AndExpr( + XorExpr( + IsTrueExpr(FieldReference("Filter2")), + NotExpr(IsTrueExpr(FieldReference("Filter3")))), + IsTrueExpr(FieldReference("Filter4"))))) } } } @@ -135,9 +163,16 @@ class SyntaxTest extends FlatSpec with Matchers { parseResult shouldBe a [Success[_]] parseResult match { case Success(ast) => { - ast.toString shouldEqual "AndExpr(OrExpr(IsTrueExpr(FieldReference(Filter1)),IsTrueExpr(FieldReference(Filter2)))," + - "XorExpr(NotExpr(IsTrueExpr(FieldReference(Filter3))),NotExpr(AndExpr(IsTrueExpr(FieldReference(Filter4))," + - "IsTrueExpr(FieldReference(Filter5))))))" + ast shouldEqual + Query( + AndExpr( + OrExpr( + IsTrueExpr(FieldReference("Filter1")), + IsTrueExpr(FieldReference("Filter2"))), + XorExpr( + NotExpr(IsTrueExpr(FieldReference("Filter3"))), + NotExpr(AndExpr(IsTrueExpr(FieldReference("Filter4")), + IsTrueExpr(FieldReference("Filter5"))))))) } } } @@ -148,8 +183,11 @@ class SyntaxTest extends FlatSpec with Matchers { parseResult shouldBe a [Success[_]] parseResult match { case Success(ast) => { - ast.toString shouldEqual "AndExpr(NotExpr(IsTrueExpr(FieldReference(Filter1)))," + - "NotExpr(IsTrueExpr(FieldReference(Filter2))))" + ast shouldEqual + Query( + AndExpr( + NotExpr(IsTrueExpr(FieldReference("Filter1"))), + NotExpr(IsTrueExpr(FieldReference("Filter2"))))) } } } @@ -159,8 +197,12 @@ class SyntaxTest extends FlatSpec with Matchers { parseResult shouldBe a [Success[_]] parseResult match { case Success(ast) => { - ast.toString shouldEqual "NotExpr(AndExpr(IsTrueExpr(FieldReference(Filter1))," + - "NotExpr(IsTrueExpr(FieldReference(Filter2)))))" + ast shouldEqual + Query( + NotExpr( + AndExpr( + IsTrueExpr(FieldReference("Filter1")), + NotExpr(IsTrueExpr(FieldReference("Filter2")))))) } } } @@ -170,9 +212,16 @@ class SyntaxTest extends FlatSpec with Matchers { parseResult shouldBe a[Success[_]] parseResult match { case Success(ast) => { - ast.toString shouldEqual "AndExpr(NotExpr(NotExpr(IsTrueExpr(FieldReference(Filter1))))," + - "NotExpr(OrExpr(LessOrEqualExpr(FieldReference(Filter2),0),NotExpr(AndExpr(IsTrueExpr(FieldReference(Filter3))," + - "NotExpr(LikeExpr(FieldReference(Filter4),abc)))))))" + ast shouldEqual + Query( + AndExpr( + NotExpr( + NotExpr(IsTrueExpr(FieldReference("Filter1")))), + NotExpr( + OrExpr( + LessOrEqualExpr(FieldReference("Filter2"),"0"), + NotExpr(AndExpr(IsTrueExpr(FieldReference("Filter3")), + NotExpr(LikeExpr(FieldReference("Filter4"),"abc")))))))) } } } @@ -183,11 +232,28 @@ class SyntaxTest extends FlatSpec with Matchers { parseResult match { case Success(ast) => { ast shouldEqual - AndExpr( + Query(AndExpr( AndExpr( GreaterThanExpr(FieldReference("metrics.classversion.9"),"0"), EqualExpr(FieldReference("metrics.classversion.8"),"0")), - EqualExpr(FieldReference("maven.groupId"),"com.github.xmlet")) + EqualExpr(FieldReference("maven.groupId"),"com.github.xmlet"))) + } + case Failure(exception : ParseError) => { + fail(parser.formatError(exception)) + } + case _ => fail() + } + } + + "Single field selection" should "be valid" in { + val parser = new Syntax("[metrics.api.unsafe.heapget]>0 #[metrics.bytecode.*]") + val parseResult = parser.QueryRule.run() + parseResult match { + case Success(ast) => { + ast shouldEqual + Query( + GreaterThanExpr(FieldReference("metrics.api.unsafe.heapget"),"0"), + Seq(FieldReference("metrics.bytecode.*"))) } case Failure(exception : ParseError) => { fail(parser.formatError(exception)) From d9ed32cfd9eba02397e699347484ffbd1e7ce173 Mon Sep 17 00:00:00 2001 From: Ben Hermann Date: Sun, 5 Jan 2020 11:24:07 +0100 Subject: [PATCH 3/4] Made syntax tollerant to whitespace at the end --- core/src/main/scala/de/upb/cs/swt/delphi/core/ql/Syntax.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/de/upb/cs/swt/delphi/core/ql/Syntax.scala b/core/src/main/scala/de/upb/cs/swt/delphi/core/ql/Syntax.scala index 24232b5..2d82f9c 100644 --- a/core/src/main/scala/de/upb/cs/swt/delphi/core/ql/Syntax.scala +++ b/core/src/main/scala/de/upb/cs/swt/delphi/core/ql/Syntax.scala @@ -22,13 +22,13 @@ import org.parboiled2.{CharPredicate, Parser, ParserInput, Rule1} * The syntax definition and parser for the Delphi QL. * * @author Lisa Nguyen Quang Do - * @author Ben Hermann + * @author Ben Hermann~ * */ class Syntax(val input : ParserInput) extends Parser { def QueryRule = rule { - CombinatorialRule ~ zeroOrMore(Whitespace ~ FieldSelection) ~ EOI ~> Query + CombinatorialRule ~ zeroOrMore(Whitespace ~ FieldSelection) ~ Whitespace ~ EOI ~> Query } From 23e48169897c8d19a1d2c3211ab33d7ff700b362 Mon Sep 17 00:00:00 2001 From: Ben Hermann Date: Sun, 5 Jan 2020 11:25:09 +0100 Subject: [PATCH 4/4] Bumped version to release --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 3e86cc3..e5f6f29 100644 --- a/build.sbt +++ b/build.sbt @@ -29,7 +29,7 @@ ThisBuild / publishTo := { } ThisBuild / publishMavenStyle := true -ThisBuild / version := "0.9.2-SNAPSHOT" +ThisBuild / version := "0.9.2" lazy val scala212 = "2.12.10" lazy val scala213 = "2.13.1"