From 6c7804bb3d255334f4be0e856d5d9257e3860f70 Mon Sep 17 00:00:00 2001 From: Philippus Date: Wed, 27 Jun 2018 22:30:47 +0200 Subject: [PATCH 1/2] Implement ~> and <~ for OnceParser, fixes scala/bug#6464 --- .../util/parsing/combinator/Parsers.scala | 8 +++- .../scala/util/parsing/combinator/t6464.scala | 39 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 shared/src/test/scala/scala/util/parsing/combinator/t6464.scala diff --git a/shared/src/main/scala/scala/util/parsing/combinator/Parsers.scala b/shared/src/main/scala/scala/util/parsing/combinator/Parsers.scala index 4783afea..dd1bcc24 100644 --- a/shared/src/main/scala/scala/util/parsing/combinator/Parsers.scala +++ b/shared/src/main/scala/scala/util/parsing/combinator/Parsers.scala @@ -948,6 +948,12 @@ trait Parsers { */ trait OnceParser[+T] extends Parser[T] { override def ~ [U](p: => Parser[U]): Parser[~[T, U]] - = OnceParser{ (for(a <- this; b <- commit(p)) yield new ~(a,b)).named("~") } + = OnceParser{ (for(a <- this; b <- commit(p)) yield new ~(a,b)).named("~") } + + override def ~> [U](p: => Parser[U]): Parser[U] + = OnceParser{ (for(a <- this; b <- commit(p)) yield b).named("~>") } + + override def <~ [U](p: => Parser[U]): Parser[T] + = OnceParser{ (for(a <- this; b <- commit(p)) yield a).named("<~") } } } diff --git a/shared/src/test/scala/scala/util/parsing/combinator/t6464.scala b/shared/src/test/scala/scala/util/parsing/combinator/t6464.scala new file mode 100644 index 00000000..b6db28d5 --- /dev/null +++ b/shared/src/test/scala/scala/util/parsing/combinator/t6464.scala @@ -0,0 +1,39 @@ +import scala.util.parsing.input.CharSequenceReader +import scala.util.parsing.combinator.RegexParsers + +import org.junit.Test +import org.junit.Assert.assertEquals + +class t6464 { + object SspParser extends RegexParsers { + val ok: Parser[Any] = + ("<%" ~! rep(' ') ~ "\\w+".r ~ rep(' ') ~ "%>" + | "<%" ~! err("should not fail here, because of ~!")) + + val buggy: Parser[Any] = + ("<%" ~! rep(' ') ~> "\\w+".r <~ rep(' ') ~ "%>" + | "<%" ~! err("should not fail here, because of ~!")) + + } + @Test + def test: Unit = { + assertEquals( + "[1.9] parsed: ((((<%~List( ))~hi)~List( ))~%>)", + SspParser.phrase(SspParser.ok)(new CharSequenceReader("<% hi %>")).toString) + val expected = """[1.7] error: string matching regex '\w+' expected but '%' found + +<% %> + ^""" + assertEquals( + expected, + SspParser.phrase(SspParser.ok)(new CharSequenceReader("<% %>")).toString) + + assertEquals( + "[1.9] parsed: hi", + SspParser.phrase(SspParser.buggy)(new CharSequenceReader("<% hi %>")).toString) + + assertEquals( + expected, + SspParser.phrase(SspParser.buggy)(new CharSequenceReader("<% %>")).toString) + } +} From f4f00bb6572982435542067b2cc309816caff9ba Mon Sep 17 00:00:00 2001 From: Philippus Date: Tue, 10 Jul 2018 22:21:05 +0200 Subject: [PATCH 2/2] Fix indentation --- .../util/parsing/combinator/Parsers.scala | 6 ++-- .../scala/util/parsing/combinator/t6464.scala | 33 ++++++++++--------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/shared/src/main/scala/scala/util/parsing/combinator/Parsers.scala b/shared/src/main/scala/scala/util/parsing/combinator/Parsers.scala index dd1bcc24..f6029423 100644 --- a/shared/src/main/scala/scala/util/parsing/combinator/Parsers.scala +++ b/shared/src/main/scala/scala/util/parsing/combinator/Parsers.scala @@ -948,12 +948,12 @@ trait Parsers { */ trait OnceParser[+T] extends Parser[T] { override def ~ [U](p: => Parser[U]): Parser[~[T, U]] - = OnceParser{ (for(a <- this; b <- commit(p)) yield new ~(a,b)).named("~") } + = OnceParser{ (for(a <- this; b <- commit(p)) yield new ~(a,b)).named("~") } override def ~> [U](p: => Parser[U]): Parser[U] - = OnceParser{ (for(a <- this; b <- commit(p)) yield b).named("~>") } + = OnceParser{ (for(a <- this; b <- commit(p)) yield b).named("~>") } override def <~ [U](p: => Parser[U]): Parser[T] - = OnceParser{ (for(a <- this; b <- commit(p)) yield a).named("<~") } + = OnceParser{ (for(a <- this; b <- commit(p)) yield a).named("<~") } } } diff --git a/shared/src/test/scala/scala/util/parsing/combinator/t6464.scala b/shared/src/test/scala/scala/util/parsing/combinator/t6464.scala index b6db28d5..f1f1e264 100644 --- a/shared/src/test/scala/scala/util/parsing/combinator/t6464.scala +++ b/shared/src/test/scala/scala/util/parsing/combinator/t6464.scala @@ -15,25 +15,28 @@ class t6464 { | "<%" ~! err("should not fail here, because of ~!")) } - @Test - def test: Unit = { - assertEquals( - "[1.9] parsed: ((((<%~List( ))~hi)~List( ))~%>)", - SspParser.phrase(SspParser.ok)(new CharSequenceReader("<% hi %>")).toString) - val expected = """[1.7] error: string matching regex '\w+' expected but '%' found + + @Test + def test: Unit = { + assertEquals( + "[1.9] parsed: ((((<%~List( ))~hi)~List( ))~%>)", + SspParser.phrase(SspParser.ok)(new CharSequenceReader("<% hi %>")).toString) + + val expected = """[1.7] error: string matching regex '\w+' expected but '%' found <% %> ^""" - assertEquals( - expected, - SspParser.phrase(SspParser.ok)(new CharSequenceReader("<% %>")).toString) - assertEquals( - "[1.9] parsed: hi", - SspParser.phrase(SspParser.buggy)(new CharSequenceReader("<% hi %>")).toString) + assertEquals( + expected, + SspParser.phrase(SspParser.ok)(new CharSequenceReader("<% %>")).toString) + + assertEquals( + "[1.9] parsed: hi", + SspParser.phrase(SspParser.buggy)(new CharSequenceReader("<% hi %>")).toString) - assertEquals( - expected, - SspParser.phrase(SspParser.buggy)(new CharSequenceReader("<% %>")).toString) + assertEquals( + expected, + SspParser.phrase(SspParser.buggy)(new CharSequenceReader("<% %>")).toString) } }