@@ -2,6 +2,7 @@ const DEFAULT_PREFIXES = "./";
2
2
const DEFAULT_DELIMITER = "/" ;
3
3
const GROUPS_RE = / \( (?: \? < ( .* ?) > ) ? (? ! \? ) / g;
4
4
const NOOP_VALUE = ( value : string ) => value ;
5
+ const NAME_RE = / ^ [ \p{ L} \p{ Nl} \p{ Mn} \p{ Mc} \p{ Nd} \p{ Pc} ] $ / u;
5
6
6
7
/**
7
8
* Encode a string into another string.
@@ -98,50 +99,40 @@ interface LexToken {
98
99
* Tokenize input string.
99
100
*/
100
101
function lexer ( str : string ) {
102
+ const chars = [ ...str ] ;
101
103
const tokens : LexToken [ ] = [ ] ;
102
104
let i = 0 ;
103
105
104
- while ( i < str . length ) {
105
- const char = str [ i ] ;
106
+ while ( i < chars . length ) {
107
+ const char = chars [ i ] ;
106
108
107
109
if ( char === "*" || char === "+" || char === "?" ) {
108
- tokens . push ( { type : "MODIFIER" , index : i , value : str [ i ++ ] } ) ;
110
+ tokens . push ( { type : "MODIFIER" , index : i , value : chars [ i ++ ] } ) ;
109
111
continue ;
110
112
}
111
113
112
114
if ( char === "\\" ) {
113
- tokens . push ( { type : "ESCAPED_CHAR" , index : i ++ , value : str [ i ++ ] } ) ;
115
+ tokens . push ( { type : "ESCAPED_CHAR" , index : i ++ , value : chars [ i ++ ] } ) ;
114
116
continue ;
115
117
}
116
118
117
119
if ( char === "{" ) {
118
- tokens . push ( { type : "OPEN" , index : i , value : str [ i ++ ] } ) ;
120
+ tokens . push ( { type : "OPEN" , index : i , value : chars [ i ++ ] } ) ;
119
121
continue ;
120
122
}
121
123
122
124
if ( char === "}" ) {
123
- tokens . push ( { type : "CLOSE" , index : i , value : str [ i ++ ] } ) ;
125
+ tokens . push ( { type : "CLOSE" , index : i , value : chars [ i ++ ] } ) ;
124
126
continue ;
125
127
}
126
128
127
129
if ( char === ":" ) {
128
130
let name = "" ;
129
131
let j = i + 1 ;
130
132
131
- while ( j < str . length ) {
132
- const code = str . charCodeAt ( j ) ;
133
-
134
- if (
135
- // `0-9`
136
- ( code >= 48 && code <= 57 ) ||
137
- // `A-Z`
138
- ( code >= 65 && code <= 90 ) ||
139
- // `a-z`
140
- ( code >= 97 && code <= 122 ) ||
141
- // `_`
142
- code === 95
143
- ) {
144
- name += str [ j ++ ] ;
133
+ while ( j < chars . length ) {
134
+ if ( NAME_RE . test ( chars [ j ] ) ) {
135
+ name += chars [ j ++ ] ;
145
136
continue ;
146
137
}
147
138
@@ -160,30 +151,30 @@ function lexer(str: string) {
160
151
let pattern = "" ;
161
152
let j = i + 1 ;
162
153
163
- if ( str [ j ] === "?" ) {
154
+ if ( chars [ j ] === "?" ) {
164
155
throw new TypeError ( `Pattern cannot start with "?" at ${ j } ` ) ;
165
156
}
166
157
167
- while ( j < str . length ) {
168
- if ( str [ j ] === "\\" ) {
169
- pattern += str [ j ++ ] + str [ j ++ ] ;
158
+ while ( j < chars . length ) {
159
+ if ( chars [ j ] === "\\" ) {
160
+ pattern += chars [ j ++ ] + chars [ j ++ ] ;
170
161
continue ;
171
162
}
172
163
173
- if ( str [ j ] === ")" ) {
164
+ if ( chars [ j ] === ")" ) {
174
165
count -- ;
175
166
if ( count === 0 ) {
176
167
j ++ ;
177
168
break ;
178
169
}
179
- } else if ( str [ j ] === "(" ) {
170
+ } else if ( chars [ j ] === "(" ) {
180
171
count ++ ;
181
- if ( str [ j + 1 ] !== "?" ) {
172
+ if ( chars [ j + 1 ] !== "?" ) {
182
173
throw new TypeError ( `Capturing groups are not allowed at ${ j } ` ) ;
183
174
}
184
175
}
185
176
186
- pattern += str [ j ++ ] ;
177
+ pattern += chars [ j ++ ] ;
187
178
}
188
179
189
180
if ( count ) throw new TypeError ( `Unbalanced pattern at ${ i } ` ) ;
@@ -194,7 +185,7 @@ function lexer(str: string) {
194
185
continue ;
195
186
}
196
187
197
- tokens . push ( { type : "CHAR" , index : i , value : str [ i ++ ] } ) ;
188
+ tokens . push ( { type : "CHAR" , index : i , value : chars [ i ++ ] } ) ;
198
189
}
199
190
200
191
tokens . push ( { type : "END" , index : i , value : "" } ) ;
0 commit comments