Skip to content

Commit 895a882

Browse files
committed
Merge pull request #65 from liskin/pagedseqreader-packrat
Fix packrat caching with PagedSeqReader
2 parents aacfcf8 + 0345e49 commit 895a882

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

src/main/scala/scala/util/parsing/input/PagedSeqReader.scala

+8-4
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ object PagedSeqReader {
3030
* @author Martin Odersky
3131
*/
3232
class PagedSeqReader(seq: PagedSeq[Char],
33-
override val offset: Int) extends Reader[Char] {
33+
override val offset: Int) extends Reader[Char] { outer =>
3434
import PagedSeqReader._
3535

36-
override lazy val source: java.lang.CharSequence = seq
36+
override val source: java.lang.CharSequence = seq
3737

3838
/** Construct a `PagedSeqReader` with its first element at
3939
* `source(0)` and position `(1,1)`.
@@ -51,7 +51,9 @@ class PagedSeqReader(seq: PagedSeq[Char],
5151
* otherwise, it's a `PagedSeqReader` containing the rest of input.
5252
*/
5353
def rest: PagedSeqReader =
54-
if (seq.isDefinedAt(offset)) new PagedSeqReader(seq, offset + 1)
54+
if (seq.isDefinedAt(offset)) new PagedSeqReader(seq, offset + 1) {
55+
override val source: java.lang.CharSequence = outer.source
56+
}
5557
else this
5658

5759
/** The position of the first element in the reader.
@@ -67,5 +69,7 @@ class PagedSeqReader(seq: PagedSeq[Char],
6769
* `n` elements.
6870
*/
6971
override def drop(n: Int): PagedSeqReader =
70-
new PagedSeqReader(seq, offset + n)
72+
new PagedSeqReader(seq, offset + n) {
73+
override val source: java.lang.CharSequence = outer.source
74+
}
7175
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package scala.util.parsing.combinator
2+
3+
import scala.util.parsing.input._
4+
import scala.collection.immutable.PagedSeq
5+
6+
import org.junit.Test
7+
import org.junit.Assert.assertTrue
8+
9+
import scala.util.parsing.combinator.syntactical.StandardTokenParsers
10+
11+
class gh45 {
12+
13+
@Test
14+
def test4: Unit = {
15+
def check(rd: Reader[Char]): Unit = {
16+
val g = new grammar
17+
val p = g.phrase(g.script)
18+
val parseResult = p(new g.lexical.Scanner(rd))
19+
assertTrue(parseResult.isInstanceOf[g.Success[_]])
20+
}
21+
22+
val str = "x once y"
23+
check(new CharSequenceReader(str))
24+
/* Note that this only tests PagedSeq.rest since neither
25+
* PackratReader nor lexical.Scanner override/use the drop method.
26+
*/
27+
check(new PagedSeqReader(PagedSeq.fromStrings(List(str))))
28+
}
29+
30+
}
31+
32+
private final class grammar extends StandardTokenParsers with PackratParsers {
33+
lexical.reserved ++= List("x", "y", "z", "once")
34+
35+
var onceCnt: Int = 0
36+
lazy val once: PackratParser[String] = memo("once") ^? {
37+
case s if onceCnt == 0 =>
38+
onceCnt += 1
39+
s
40+
}
41+
42+
lazy val script: PackratParser[Any] =
43+
( "x" ~ once ~ "z"
44+
| "x" ~ once ~ "y"
45+
)
46+
}

0 commit comments

Comments
 (0)