@@ -2,6 +2,7 @@ const DEFAULT_PREFIXES = "./";
22const DEFAULT_DELIMITER = "/" ;
33const GROUPS_RE = / \( (?: \? < ( .* ?) > ) ? (? ! \? ) / g;
44const NOOP_VALUE = ( value : string ) => value ;
5+ const NAME_RE = / ^ [ \p{ L} \p{ Nl} \p{ Mn} \p{ Mc} \p{ Nd} \p{ Pc} ] $ / u;
56
67/**
78 * Encode a string into another string.
@@ -98,50 +99,40 @@ interface LexToken {
9899 * Tokenize input string.
99100 */
100101function lexer ( str : string ) {
102+ const chars = [ ...str ] ;
101103 const tokens : LexToken [ ] = [ ] ;
102104 let i = 0 ;
103105
104- while ( i < str . length ) {
105- const char = str [ i ] ;
106+ while ( i < chars . length ) {
107+ const char = chars [ i ] ;
106108
107109 if ( char === "*" || char === "+" || char === "?" ) {
108- tokens . push ( { type : "MODIFIER" , index : i , value : str [ i ++ ] } ) ;
110+ tokens . push ( { type : "MODIFIER" , index : i , value : chars [ i ++ ] } ) ;
109111 continue ;
110112 }
111113
112114 if ( char === "\\" ) {
113- tokens . push ( { type : "ESCAPED_CHAR" , index : i ++ , value : str [ i ++ ] } ) ;
115+ tokens . push ( { type : "ESCAPED_CHAR" , index : i ++ , value : chars [ i ++ ] } ) ;
114116 continue ;
115117 }
116118
117119 if ( char === "{" ) {
118- tokens . push ( { type : "OPEN" , index : i , value : str [ i ++ ] } ) ;
120+ tokens . push ( { type : "OPEN" , index : i , value : chars [ i ++ ] } ) ;
119121 continue ;
120122 }
121123
122124 if ( char === "}" ) {
123- tokens . push ( { type : "CLOSE" , index : i , value : str [ i ++ ] } ) ;
125+ tokens . push ( { type : "CLOSE" , index : i , value : chars [ i ++ ] } ) ;
124126 continue ;
125127 }
126128
127129 if ( char === ":" ) {
128130 let name = "" ;
129131 let j = i + 1 ;
130132
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 ++ ] ;
145136 continue ;
146137 }
147138
@@ -160,30 +151,30 @@ function lexer(str: string) {
160151 let pattern = "" ;
161152 let j = i + 1 ;
162153
163- if ( str [ j ] === "?" ) {
154+ if ( chars [ j ] === "?" ) {
164155 throw new TypeError ( `Pattern cannot start with "?" at ${ j } ` ) ;
165156 }
166157
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 ++ ] ;
170161 continue ;
171162 }
172163
173- if ( str [ j ] === ")" ) {
164+ if ( chars [ j ] === ")" ) {
174165 count -- ;
175166 if ( count === 0 ) {
176167 j ++ ;
177168 break ;
178169 }
179- } else if ( str [ j ] === "(" ) {
170+ } else if ( chars [ j ] === "(" ) {
180171 count ++ ;
181- if ( str [ j + 1 ] !== "?" ) {
172+ if ( chars [ j + 1 ] !== "?" ) {
182173 throw new TypeError ( `Capturing groups are not allowed at ${ j } ` ) ;
183174 }
184175 }
185176
186- pattern += str [ j ++ ] ;
177+ pattern += chars [ j ++ ] ;
187178 }
188179
189180 if ( count ) throw new TypeError ( `Unbalanced pattern at ${ i } ` ) ;
@@ -194,7 +185,7 @@ function lexer(str: string) {
194185 continue ;
195186 }
196187
197- tokens . push ( { type : "CHAR" , index : i , value : str [ i ++ ] } ) ;
188+ tokens . push ( { type : "CHAR" , index : i , value : chars [ i ++ ] } ) ;
198189 }
199190
200191 tokens . push ( { type : "END" , index : i , value : "" } ) ;
0 commit comments