Skip to content

Commit 1d3ce9d

Browse files
committed
Merge remote-tracking branch 'scala/master'
2 parents bf431ce + d2fcadb commit 1d3ce9d

20 files changed

+295
-328
lines changed

build.sbt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ pomExtra := (
7878
</developers>
7979
)
8080

81+
libraryDependencies ++= Seq("junit" % "junit" % "4.11" % "test", "com.novocode" % "junit-interface" % "0.10" % "test")
82+
8183
// default value must be set here
8284
TestKeys.includeTestDependencies := true
8385

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package scala.util.parsing.combinator
2+
3+
import scala.util.parsing.input.CharArrayReader
4+
5+
import org.junit.Test
6+
import org.junit.Assert.assertEquals
7+
8+
class JavaTokenParsersTest {
9+
10+
@Test
11+
def parseDecimalNumber: Unit = {
12+
object TestJavaTokenParsers extends JavaTokenParsers
13+
import TestJavaTokenParsers._
14+
assertEquals("1.1", decimalNumber(new CharArrayReader("1.1".toCharArray)).get)
15+
assertEquals("1.", decimalNumber(new CharArrayReader("1.".toCharArray)).get)
16+
assertEquals(".1", decimalNumber(new CharArrayReader(".1".toCharArray)).get)
17+
// should fail to parse and we should get Failure as ParseResult
18+
val failure = decimalNumber(new CharArrayReader("!1".toCharArray)).asInstanceOf[Failure]
19+
assertEquals("""string matching regex `(\d+(\.\d*)?|\d*\.\d+)' expected but `!' found""", failure.msg)
20+
}
21+
22+
@Test
23+
def parseJavaIdent: Unit = {
24+
object javaTokenParser extends JavaTokenParsers
25+
import javaTokenParser._
26+
def parseSuccess(s: String): Unit = {
27+
val parseResult = parseAll(ident, s)
28+
parseResult match {
29+
case Success(r, _) => assertEquals(s, r)
30+
case _ => sys.error(parseResult.toString)
31+
}
32+
}
33+
def parseFailure(s: String, errorColPos: Int): Unit = {
34+
val parseResult = parseAll(ident, s)
35+
parseResult match {
36+
case Failure(_, next) =>
37+
val pos = next.pos
38+
assertEquals(1, pos.line)
39+
assertEquals(errorColPos, pos.column)
40+
case _ => sys.error(parseResult.toString)
41+
}
42+
}
43+
parseSuccess("simple")
44+
parseSuccess("with123")
45+
parseSuccess("with$")
46+
parseSuccess("with\u00f8\u00df\u00f6\u00e8\u00e6")
47+
parseSuccess("with_")
48+
parseSuccess("_with")
49+
50+
parseFailure("3start", 1)
51+
parseFailure("-start", 1)
52+
parseFailure("with-s", 5)
53+
// we♥scala
54+
parseFailure("we\u2665scala", 3)
55+
parseFailure("with space", 6)
56+
}
57+
58+
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package scala.util.parsing.combinator
2+
3+
import org.junit.Test
4+
import org.junit.Assert.assertEquals
5+
import org.junit.Assert.assertTrue
6+
7+
import scala.util.parsing.combinator.syntactical.StandardTokenParsers
8+
9+
class PackratParsersTest {
10+
11+
@Test
12+
def test1: Unit = {
13+
import grammars1._
14+
val head = phrase(term)
15+
16+
def extractResult(r : ParseResult[Int]): Int = r match {
17+
case Success(a,_) => a
18+
case NoSuccess(a,_) => sys.error(a)
19+
}
20+
def check(expected: Int, expr: String): Unit = {
21+
val parseResult = head(new lexical.Scanner(expr))
22+
val result = extractResult(parseResult)
23+
assertEquals(expected, result)
24+
}
25+
26+
check(1, "1")
27+
check(3, "1+2")
28+
check(5, "9-4")
29+
check(81, "9*9")
30+
check(4, "8/2")
31+
check(37, "4*9-0/7+9-8*1")
32+
check(9, "(1+2)*3")
33+
}
34+
35+
@Test
36+
def test2: Unit = {
37+
import grammars2._
38+
val head = phrase(exp)
39+
40+
def extractResult(r : ParseResult[Int]): Int = r match {
41+
case Success(a,_) => a
42+
case NoSuccess(a,_) => sys.error(a)
43+
}
44+
def check(expected: Int, expr: String): Unit = {
45+
val parseResult = head(new lexical.Scanner(expr))
46+
val result = extractResult(parseResult)
47+
assertEquals(expected, result)
48+
}
49+
50+
check(1, "1")
51+
check(3, "1+2")
52+
check(81, "9*9")
53+
check(43, "4*9+7")
54+
check(59, "4*9+7*2+3*3")
55+
check(188, "4*9+7*2+3*3+9*5+7*6*2")
56+
check(960, "4*(9+7)*(2+3)*3")
57+
}
58+
59+
@Test
60+
def test3: Unit = {
61+
import grammars3._
62+
val head = phrase(AnBnCn)
63+
def extractResult(r: ParseResult[AnBnCnResult]): AnBnCnResult = r match {
64+
case Success(a,_) => a
65+
case NoSuccess(a,_) => sys.error(a)
66+
}
67+
def threeLists(as: List[Symbol], bs: List[Symbol], cs: List[Symbol]): AnBnCnResult = {
68+
val as1 = as.map(_.name)
69+
val bs1 = bs.map(_.name)
70+
val cs1 = cs.map(_.name)
71+
new ~(new ~(as1, bs1), cs1)
72+
}
73+
def assertSuccess(expected1: List[Symbol], expected2: List[Symbol], expected3: List[Symbol],
74+
input: String): Unit = {
75+
val expected = threeLists(expected1, expected2, expected3)
76+
val parseResult = head(new lexical.Scanner(input))
77+
val result = extractResult(parseResult)
78+
assertEquals(expected, result)
79+
}
80+
81+
assertSuccess(List('a, 'b), List('a), List('b, 'c), "a b c")
82+
assertSuccess(List('a, 'a, 'b, 'b), List('a, 'a), List('b, 'b, 'c, 'c), "a a b b c c")
83+
assertSuccess(List('a, 'a, 'a, 'b, 'b, 'b), List('a, 'a, 'a), List('b, 'b, 'b, 'c, 'c, 'c),
84+
"a a a b b b c c c")
85+
assertSuccess(List('a, 'a, 'a, 'a, 'b, 'b, 'b, 'b), List('a, 'a, 'a, 'a), List('b, 'b, 'b, 'b, 'c, 'c, 'c, 'c),
86+
"a a a a b b b b c c c c")
87+
88+
def assertFailure(expectedFailureMsg: String, input: String): Unit = {
89+
val packratReader = new PackratReader(new lexical.Scanner(input))
90+
val parseResult = AnBnCn(packratReader)
91+
assertTrue(s"Not an instance of Failure: ${parseResult.toString()}", parseResult.isInstanceOf[Failure])
92+
val failure = parseResult.asInstanceOf[Failure]
93+
assertEquals(expectedFailureMsg, failure.msg)
94+
}
95+
assertFailure("``b'' expected but `c' found", "a a a a b b b c c c c")
96+
assertFailure("end of input", "a a a a b b b b c c c")
97+
}
98+
99+
}
100+
101+
private object grammars1 extends StandardTokenParsers with PackratParsers {
102+
103+
lexical.delimiters ++= List("+","-","*","/","(",")")
104+
lexical.reserved ++= List("Hello","World")
105+
106+
/****
107+
* term = term + fact | term - fact | fact
108+
* fact = fact * num | fact / num | num
109+
*/
110+
111+
112+
val term: PackratParser[Int] = (term~("+"~>fact) ^^ {case x~y => x+y}
113+
|term~("-"~>fact) ^^ {case x~y => x-y}
114+
|fact)
115+
116+
val fact: PackratParser[Int] = (fact~("*"~>numericLit) ^^ {case x~y => x*y.toInt}
117+
|fact~("/"~>numericLit) ^^ {case x~y => x/y.toInt}
118+
|"("~>term<~")"
119+
|numericLit ^^ {_.toInt})
120+
}
121+
122+
private object grammars2 extends StandardTokenParsers with PackratParsers {
123+
124+
lexical.delimiters ++= List("+","-","*","/","(",")")
125+
lexical.reserved ++= List("Hello","World")
126+
127+
/*
128+
* exp = sum | prod | num
129+
* sum = exp ~ "+" ~ num
130+
* prod = exp ~ "*" ~ num
131+
*/
132+
133+
val exp : PackratParser[Int] = sum | prod | numericLit ^^{_.toInt} | "("~>exp<~")"
134+
val sum : PackratParser[Int] = exp~("+"~>exp) ^^ {case x~y => x+y}
135+
val prod: PackratParser[Int] = exp~("*"~>(numericLit ^^{_.toInt} | exp)) ^^ {case x~y => x*y}
136+
137+
}
138+
139+
private object grammars3 extends StandardTokenParsers with PackratParsers {
140+
lexical.reserved ++= List("a","b", "c")
141+
val a: PackratParser[String] = memo("a")
142+
val b: PackratParser[String] = memo("b")
143+
val c: PackratParser[String] = memo("c")
144+
145+
type AnBnCnResult = List[String] ~ List[String] ~ List[String]
146+
147+
val AnBnCn: PackratParser[AnBnCnResult] =
148+
guard(repMany1(a,b) <~ not(b)) ~ rep1(a) ~ repMany1(b,c)// ^^{case x~y => x:::y}
149+
150+
151+
private def repMany[T](p: => Parser[T], q: => Parser[T]): Parser[List[T]] =
152+
( p~repMany(p,q)~q ^^ {case x~xs~y => x::xs:::(y::Nil)}
153+
| success(Nil)
154+
)
155+
156+
def repMany1[T](p: => Parser[T], q: => Parser[T]): Parser[List[T]] =
157+
p~opt(repMany(p,q))~q ^^ {case x~Some(xs)~y => x::xs:::(y::Nil)}
158+
159+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package scala.util.parsing.combinator
2+
3+
import org.junit.Test
4+
import org.junit.Assert.assertEquals
5+
6+
class RegexParsersTest {
7+
@Test
8+
def parserNoSuccessMessage: Unit = {
9+
object parser extends RegexParsers {
10+
def sign = "-"
11+
def number = "\\d+".r
12+
type ResultType = Option[String] ~ String
13+
def p: Parser[ResultType] = sign.? ~ number withErrorMessage "Number expected!"
14+
def q: Parser[ResultType] = sign.? ~! number withErrorMessage "Number expected!"
15+
}
16+
import parser._
17+
def extractResult(r: ParseResult[ResultType]): ResultType = r match {
18+
case Success(r, _) => r
19+
case r => sys.error(r.toString)
20+
}
21+
def result(num: Int): ResultType = {
22+
val minusSign = if (num < 0) Some("-") else None
23+
val absNumStr = Math.abs(num).toString
24+
new ~(minusSign, absNumStr)
25+
}
26+
27+
val failure1 = parseAll(p, "-x").asInstanceOf[Failure]
28+
assertEquals("string matching regex `\\d+' expected but `x' found", failure1.msg)
29+
val failure2 = parseAll(p, "x").asInstanceOf[Failure]
30+
assertEquals("string matching regex `\\d+' expected but `x' found", failure2.msg)
31+
assertEquals(result(-5), extractResult(parseAll(p, "-5")))
32+
assertEquals(result(5), extractResult(parseAll(p, "5")))
33+
val error1 = parseAll(q, "-x").asInstanceOf[Error]
34+
assertEquals("Number expected!", error1.msg)
35+
val error2 = parseAll(q, "x").asInstanceOf[Error]
36+
assertEquals("Number expected!", error2.msg)
37+
assertEquals(result(-5), extractResult(parseAll(q, "-5")))
38+
assertEquals(result(5), extractResult(parseAll(q, "5")))
39+
}
40+
41+
@Test
42+
def parserFilter: Unit = {
43+
object parser extends RegexParsers {
44+
val keywords = Set("if", "false")
45+
def word: Parser[String] = "\\w+".r
46+
47+
def keyword: Parser[String] = word filter (keywords.contains)
48+
def ident: Parser[String] = word filter(!keywords.contains(_))
49+
50+
def test: Parser[String ~ String] = keyword ~ ident
51+
}
52+
import parser._
53+
54+
val failure1 = parseAll(test, "if false").asInstanceOf[Failure]
55+
assertEquals("Input doesn't match filter: false", failure1.msg)
56+
val failure2 = parseAll(test, "not true").asInstanceOf[Failure]
57+
assertEquals("Input doesn't match filter: not", failure2.msg)
58+
val success = parseAll(test, "if true").asInstanceOf[Success[String ~ String]]
59+
assertEquals(new ~("if", "true"), success.get)
60+
}
61+
62+
@Test
63+
def parserForFilter: Unit = {
64+
object parser extends RegexParsers {
65+
def word: Parser[String] = "\\w+".r
66+
67+
def twoWords = for {
68+
(a ~ b) <- word ~ word
69+
} yield (b, a)
70+
}
71+
import parser._
72+
73+
val success = parseAll(twoWords, "first second").asInstanceOf[Success[(String, String)]]
74+
assertEquals(("second", "first"), success.get)
75+
}
76+
}

test/files/run/jtptest.check

Lines changed: 0 additions & 7 deletions
This file was deleted.

test/files/run/jtptest.scala

Lines changed: 0 additions & 17 deletions
This file was deleted.

test/files/run/packrat1.check

Lines changed: 0 additions & 7 deletions
This file was deleted.

test/files/run/packrat1.scala

Lines changed: 0 additions & 47 deletions
This file was deleted.

test/files/run/packrat2.check

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)