blob: 5cd93e84e87bb2283b60445d2171b7541f5d5c74 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.plugin.osgi
import scala.util.parsing.combinator.JavaTokenParsers
import ExportPackages.{Parameter, Export}
import com.yahoo.container.plugin.util.Extractors.ListOf
import scala.util.parsing.input.CharSequenceReader
import scala.annotation.tailrec
/**
* @author tonytv
*/
object ExportPackageParser extends JavaTokenParsers {
val ListOfParameter = new ListOf(classOf[Parameter])
def exportPackage = rep1sep(export, ",")
//TODO: remove when fix is in current scala library
//Fix for https://github.com/scala/scala-parser-combinators/pull/4
def stringLiteral_fixed: Parser[String] = ("\""+"""([^"\p{Cntrl}\\]|\\[\\'"bfnrt]|\\u[a-fA-F0-9]{4})*+"""+"\"").r
@SuppressWarnings(Array("unchecked"))
def export : Parser[Export] = packageName ~ opt(";" ~> (parameters | export)) ^^ {
case (packageName : String) ~ optional => {
optional match {
case None => Export(List(packageName.asInstanceOf[String]), List())
case Some(e: Export) => e.copy(packageNames = packageName +: e.packageNames)
case Some(ListOfParameter(parameters)) => Export(List(packageName), parameters)
}
}
}
def parameters = rep1sep(parameter, ";")
def parameter = (directive | attribute) ^^ {
case k ~ v => Parameter(k.toString, v.toString)
}
def directive = (extended_ <~ ":=") ~ argument
def attribute = (extended_ <~ "=") ~ argument
def packageName = rep1sep(ident_, ".") ^^ {
x => x.mkString(".")
}
def extended = rep1("""\p{Alnum}""".r | "_" | "-" | ".") ^^ {
_.mkString
}
def argument = (extended_ | stringLiteral_ | failure("argument expected")) ^^ {
val quote = '"'.toString
_.toString.stripPrefix(quote).stripSuffix(quote)
}
def parseAll(in: CharSequence): ParseResult[List[Export]] = {
try {
parseAll(exportPackage, in)
} catch {
case e: StackOverflowError =>
throw new RuntimeException("Failed parsing Export-Package: '''\n" + in + "\n'''", e)
}
}
//*** For debugging StackOverflow error **/
def ident_ = printStackOverflow(ident)("ident")
def stringLiteral_ = printStackOverflow(stringLiteral_fixed)("stringLiteral_fixed")
def extended_ = printStackOverflow(extended)("extended")
def printStackOverflow[T](p: => Parser[T])(name: String): Parser[T] = Parser{ in =>
try {
p(in)
} catch {
case e: StackOverflowError =>
val input = in match {
case reader: CharSequenceReader => readerToString(reader)
case other => other.toString
}
println(s"***StackOverflow for $name with input '''$input'''")
throw e
}
}
@tailrec
def readerToString(reader: CharSequenceReader, current: String = ""): String = {
if (reader.atEnd) current
else readerToString(reader.rest, current + reader.first)
}
}
|