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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
package java.util.regex
import scala.annotation.switch
import scala.scalajs.js
final class Pattern private (pattern0: String, flags0: Int)
extends Serializable {
import Pattern._
def pattern(): String = pattern0
def flags(): Int = flags1
private[regex] val (jspattern, flags1) = {
if ((flags0 & LITERAL) != 0) (quote(pattern0), flags0)
else {
trySplitHack(pattern0, flags0) orElse
tryFlagHack(pattern0, flags0) getOrElse
(pattern0, flags0)
}
}
private[regex] val jsflags = {
var f = "g"
if ((flags & CASE_INSENSITIVE) != 0)
f += "i"
if ((flags & MULTILINE) != 0)
f += "m"
f
}
override def toString(): String = pattern0
def matcher(input: CharSequence): Matcher =
new Matcher(this, input, 0, input.length)
def split(input: CharSequence): Array[String] =
split(input, 0)
def split(input: CharSequence, limit: Int): Array[String] = {
val lim = if (limit > 0) limit else Int.MaxValue
val result = js.Array[String]()
val inputStr = input.toString
val matcher = this.matcher(inputStr)
var prevEnd = 0
// Actually split original string
while ((result.length < lim-1) && matcher.find()) {
result.push(inputStr.substring(prevEnd, matcher.start))
prevEnd = matcher.end
}
result.push(inputStr.substring(prevEnd))
// Remove a leading empty element iff the first match was zero-length
// and there is no other place the regex matches
if (prevEnd == 0 && result.length == 2 && (lim > 2 || !matcher.find())) {
Array(inputStr)
} else {
var len = result.length
if (limit == 0) {
while (len > 1 && result(len-1).isEmpty)
len -= 1
}
val actualResult = new Array[String](len)
result.copyToArray(actualResult)
actualResult
}
}
}
object Pattern {
final val UNIX_LINES = 0x01
final val CASE_INSENSITIVE = 0x02
final val COMMENTS = 0x04
final val MULTILINE = 0x08
final val LITERAL = 0x10
final val DOTALL = 0x20
final val UNICODE_CASE = 0x40
final val CANON_EQ = 0x80
final val UNICODE_CHARACTER_CLASS = 0x100
def compile(regex: String, flags: Int): Pattern =
new Pattern(regex, flags)
def compile(regex: String): Pattern =
new Pattern(regex, 0)
def matches(regex: String, input: CharSequence): Boolean =
compile(regex).matcher(input).matches()
def quote(s: String): String = {
var result = ""
var i = 0
while (i < s.length) {
val c = s.charAt(i)
result += ((c: @switch) match {
case '\\' | '.' | '(' | ')' | '[' | ']' | '{' | '}' | '|'
| '?' | '*' | '+' | '^' | '$' => "\\"+c
case _ => c
})
i += 1
}
result
}
/** This is a hack to support StringLike.split().
* It replaces occurrences of \Q<char>\E by quoted(<char>)
*/
@inline
private def trySplitHack(pat: String, flags: Int) = {
val m = splitHackPat.exec(pat)
if (m != null)
Some((quote(m(1).get), flags))
else
None
}
@inline
private def tryFlagHack(pat: String, flags0: Int) = {
val m = flagHackPat.exec(pat)
if (m != null) {
val newPat = pat.substring(m(0).get.length) // cut off the flag specifiers
val flags1 = m(1).fold(flags0) { chars =>
chars.foldLeft(flags0) { (f, c) => f | charToFlag(c) }
}
val flags2 = m(2).fold(flags1) { chars =>
chars.foldLeft(flags1) { (f, c) => f & ~charToFlag(c) }
}
Some((newPat, flags2))
} else
None
}
private def charToFlag(c: Char) = (c: @switch) match {
case 'i' => CASE_INSENSITIVE
case 'd' => UNIX_LINES
case 'm' => MULTILINE
case 's' => DOTALL
case 'u' => UNICODE_CASE
case 'x' => COMMENTS
case 'U' => UNICODE_CHARACTER_CLASS
case _ => sys.error("bad in-pattern flag")
}
/** matches \Q<char>\E to support StringLike.split */
private val splitHackPat = new js.RegExp("^\\\\Q(.|\\n|\\r)\\\\E$")
/** regex to match flag specifiers in regex. E.g. (?u), (?-i), (?U-i) */
private val flagHackPat =
new js.RegExp("^\\(\\?([idmsuxU]*)(?:-([idmsuxU]*))?\\)")
}
|