Skip to content

Commit 1f77230

Browse files
committed
Favour 'p' to 'q' in ||| parser if they consume same #chars, fixes scala#72
1 parent 02183d8 commit 1f77230

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

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

+2-3
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,6 @@ trait Parsers {
352352
*/
353353
def | [U >: T](q: => Parser[U]): Parser[U] = append(q).named("|")
354354

355-
// TODO
356355
/** A parser combinator for alternative with longest match composition.
357356
*
358357
* `p ||| q` succeeds if `p` succeeds or `q` succeeds.
@@ -369,11 +368,11 @@ trait Parsers {
369368
val res2 = q(in)
370369

371370
(res1, res2) match {
372-
case (s1 @ Success(_, next1), s2 @ Success(_, next2)) => if (next2.pos < next1.pos) s1 else s2
371+
case (s1 @ Success(_, next1), s2 @ Success(_, next2)) => if (next2.pos < next1.pos || next2.pos == next1.pos) s1 else s2
373372
case (s1 @ Success(_, _), _) => s1
374373
case (_, s2 @ Success(_, _)) => s2
375374
case (e1 @ Error(_, _), _) => e1
376-
case (f1 @ Failure(_, next1), ns2 @ NoSuccess(_, next2)) => if (next2.pos < next1.pos) f1 else ns2
375+
case (f1 @ Failure(_, next1), ns2 @ NoSuccess(_, next2)) => if (next2.pos < next1.pos || next2.pos == next1.pos) f1 else ns2
377376
}
378377
}
379378
override def toString = "|||"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import scala.util.parsing.combinator.Parsers
2+
import scala.util.parsing.input.CharSequenceReader
3+
4+
import org.junit.Test
5+
import org.junit.Assert.assertEquals
6+
7+
class gh72 {
8+
class TestParsers extends Parsers {
9+
type Elem = Char
10+
val left: Parser[String] = 'a' ~ 'b' ~ 'c' ^^^ "left" withFailureMessage "failure on left"
11+
val right: Parser[String] = 'a' ~ 'b' ~ 'c' ^^^ "right" withFailureMessage "failure on right"
12+
def p: Parser[String] = left ||| right
13+
}
14+
15+
@Test
16+
def test(): Unit = {
17+
val tstParsers = new TestParsers
18+
val s = new CharSequenceReader("abc")
19+
assertEquals("[1.4] parsed: left", tstParsers.p(s).toString)
20+
21+
val t = new CharSequenceReader("def")
22+
val expectedFailure = """[1.1] failure: failure on left
23+
24+
def
25+
^"""
26+
assertEquals(expectedFailure, tstParsers.p(t).toString)
27+
}
28+
}

0 commit comments

Comments
 (0)