Skip to content

Commit 5147f67

Browse files
authored
Merge pull request #203 from Philippus/issue/29
Make RegexParser.err handle whitespace like literal and regex
2 parents 8a84b17 + 0a3a641 commit 5147f67

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

shared/src/main/scala/scala/util/parsing/combinator/RegexParsers.scala

+16
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,22 @@ trait RegexParsers extends Parsers {
138138
}
139139
}
140140

141+
// we might want to make it public/protected in a future version
142+
private def ws[T](p: Parser[T]): Parser[T] = new Parser[T] {
143+
def apply(in: Input) = {
144+
val offset = in.offset
145+
val start = handleWhiteSpace(in.source, offset)
146+
p(in.drop (start - offset))
147+
}
148+
}
149+
150+
/**
151+
* @inheritdoc
152+
*
153+
* This parser additionally skips whitespace if `skipWhitespace` returns true.
154+
*/
155+
override def err(msg: String) = ws(super.err(msg))
156+
141157
/**
142158
* A parser generator delimiting whole phrases (i.e. programs).
143159
*

shared/src/test/scala/scala/util/parsing/combinator/RegexParsersTest.scala

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package scala.util.parsing.combinator
22

33
import org.junit.Test
4-
import org.junit.Assert.assertEquals
4+
import org.junit.Assert.{ assertEquals, assertTrue }
55

66
class RegexParsersTest {
77
@Test
@@ -100,4 +100,19 @@ class RegexParsersTest {
100100
val success = parseAll(twoWords, "first second").asInstanceOf[Success[(String, String)]]
101101
assertEquals(("second", "first"), success.get)
102102
}
103+
104+
@Test
105+
def errorConsumesWhitespace: Unit = {
106+
object parser extends RegexParsers {
107+
def num = "\\d+".r
108+
109+
def twoNums = num ~ (num | err("error!"))
110+
}
111+
import parser._
112+
113+
// this used to return a Failure (for the second num)
114+
val error = parseAll(twoNums, "458 bar")
115+
assertTrue(s"expected an Error but got: ${error.getClass.getName}", error.isInstanceOf[Error])
116+
assertEquals("error!", error.asInstanceOf[Error].msg)
117+
}
103118
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package scala.util.parsing.combinator
2+
3+
import org.junit.Test
4+
import org.junit.Assert.assertEquals
5+
6+
class gh29 {
7+
object Foo extends JavaTokenParsers {
8+
def word(x: String) = s"\\b$x\\b".r
9+
10+
lazy val expr = aSentence | something
11+
12+
lazy val aSentence = noun ~ verb ~ obj
13+
14+
lazy val noun = word("noun")
15+
lazy val verb = word("verb") | err("not a verb!")
16+
lazy val obj = word("object")
17+
18+
lazy val something = word("FOO")
19+
}
20+
21+
val expected =
22+
"""[1.6] error: not a verb!
23+
24+
noun vedsfasdf
25+
^""".stripMargin
26+
27+
@Test
28+
def test(): Unit = {
29+
val f = Foo.parseAll(Foo.expr, "noun verb object")
30+
31+
assertEquals("[1.17] parsed: ((noun~verb)~object)", f.toString)
32+
33+
val g = Foo.parseAll(Foo.expr, "noun vedsfasdf")
34+
assertEquals(expected, g.toString)
35+
}
36+
}

0 commit comments

Comments
 (0)