@@ -147,26 +147,29 @@ private static function processTokens(array $tokens): array
147
147
$ nextType = $ tokens [$ offset + 1 ][0 ] ?? null ;
148
148
149
149
if ($ type === self ::T_BACKSLASH && false === $ escaped ) {
150
+ // skip the backslash and set flag to escape next token
150
151
$ escaped = true ;
151
152
152
153
continue ;
153
154
}
154
155
155
156
if ($ escaped === true ) {
157
+ // escaped flag is set, so make this a literal char and unset
158
+ // the escaped flag
156
159
$ resolved [] = [self ::T_CHAR , $ char ];
157
160
$ escaped = false ;
158
161
159
162
continue ;
160
163
}
161
164
162
- // normal globstar
165
+ // globstar must be preceded by and succeeded by a directory separator
163
166
if (
164
167
$ type === self ::T_SLASH &&
165
- ( $ tokens [ $ offset + 1 ][ 0 ] ?? null ) === self ::T_ASTERIX && ($ tokens [$ offset + 2 ][0 ] ?? null ) === self ::T_ASTERIX && ($ tokens [$ offset + 3 ][0 ] ?? null ) === self ::T_SLASH
168
+ $ nextType === self ::T_ASTERIX && ($ tokens [$ offset + 2 ][0 ] ?? null ) === self ::T_ASTERIX && ($ tokens [$ offset + 3 ][0 ] ?? null ) === self ::T_SLASH
166
169
) {
167
170
$ resolved [] = [self ::T_GLOBSTAR , '** ' ];
168
171
169
- // we eat the two `*` in addition to the slash
172
+ // we eat the two `*` and the trailing slash
170
173
$ offset += 3 ;
171
174
172
175
continue ;
@@ -208,6 +211,10 @@ private static function processTokens(array $tokens): array
208
211
continue ;
209
212
}
210
213
214
+ // https://man7.org/linux/man-pages/man7/glob.7.html
215
+ // > The string enclosed by the brackets cannot be empty; therefore
216
+ // > ']' can be allowed between the brackets, provided that it is
217
+ // > the first character.
211
218
if ($ type === self ::T_BRACKET_OPEN && $ nextType === self ::T_BRACKET_CLOSE ) {
212
219
$ bracketOpen = true ;
213
220
$ resolved [] = [self ::T_BRACKET_OPEN , '[ ' ];
@@ -218,6 +225,8 @@ private static function processTokens(array $tokens): array
218
225
continue ;
219
226
}
220
227
228
+ // if we're already in a bracket and the next two chars are [: then
229
+ // start parsing a character class...
221
230
if ($ bracketOpen && $ type === self ::T_BRACKET_OPEN && $ nextType === self ::T_COLON ) {
222
231
// this looks like a named [:character:] class
223
232
$ class = '' ;
@@ -240,14 +249,17 @@ private static function processTokens(array $tokens): array
240
249
$ resolved [] = [self ::T_CHAR , ': ' . $ class ];
241
250
}
242
251
252
+
253
+ // if bracket is already open and we have another open bracket
254
+ // interpret it as a literal
243
255
if ($ bracketOpen === true && $ type === self ::T_BRACKET_OPEN ) {
244
- // if bracket is already open, interpret everything as a
245
- // literal char
246
256
$ resolved [] = [self ::T_CHAR , $ char ];
247
257
248
258
continue ;
249
259
}
250
260
261
+ // if we are NOT in an open bracket and we have an open bracket
262
+ // then pop the bracket on the stack and enter bracket-mode.
251
263
if ($ bracketOpen === false && $ type === self ::T_BRACKET_OPEN ) {
252
264
$ bracketOpen = true ;
253
265
$ resolved [] = [$ type , $ char ];
@@ -256,7 +268,15 @@ private static function processTokens(array $tokens): array
256
268
continue ;
257
269
}
258
270
259
- if ($ type === self ::T_BRACKET_CLOSE ) {
271
+ // if are in a bracket and we get to bracket close then
272
+ // pop the last open bracket off the stack and continue
273
+ //
274
+ // TODO: $bracketOpen === true below is not tested
275
+ if ($ bracketOpen === true && $ type === self ::T_BRACKET_CLOSE ) {
276
+
277
+ // TODO: this is not tested
278
+ $ bracketOpen = false ;
279
+
260
280
array_pop ($ brackets );
261
281
$ resolved [] = [$ type , $ char ];
262
282
0 commit comments