| 2396 | Expr.setFilters = new setFilters(); |
| 2397 | |
| 2398 | function tokenize( selector, parseOnly ) { |
| 2399 | var matched, match, tokens, type, |
| 2400 | soFar, groups, preFilters, |
| 2401 | cached = tokenCache[ selector + " " ]; |
| 2402 | |
| 2403 | if ( cached ) { |
| 2404 | return parseOnly ? 0 : cached.slice( 0 ); |
| 2405 | } |
| 2406 | |
| 2407 | soFar = selector; |
| 2408 | groups = []; |
| 2409 | preFilters = Expr.preFilter; |
| 2410 | |
| 2411 | while ( soFar ) { |
| 2412 | |
| 2413 | // Comma and first run |
| 2414 | if ( !matched || (match = rcomma.exec( soFar )) ) { |
| 2415 | if ( match ) { |
| 2416 | // Don't consume trailing commas as valid |
| 2417 | soFar = soFar.slice( match[0].length ) || soFar; |
| 2418 | } |
| 2419 | groups.push( tokens = [] ); |
| 2420 | } |
| 2421 | |
| 2422 | matched = false; |
| 2423 | |
| 2424 | // Combinators |
| 2425 | if ( (match = rcombinators.exec( soFar )) ) { |
| 2426 | matched = match.shift(); |
| 2427 | tokens.push({ |
| 2428 | value: matched, |
| 2429 | // Cast descendant combinators to space |
| 2430 | type: match[0].replace( rtrim, " " ) |
| 2431 | }); |
| 2432 | soFar = soFar.slice( matched.length ); |
| 2433 | } |
| 2434 | |
| 2435 | // Filters |
| 2436 | for ( type in Expr.filter ) { |
| 2437 | if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || |
| 2438 | (match = preFilters[ type ]( match ))) ) { |
| 2439 | matched = match.shift(); |
| 2440 | tokens.push({ |
| 2441 | value: matched, |
| 2442 | type: type, |
| 2443 | matches: match |
| 2444 | }); |
| 2445 | soFar = soFar.slice( matched.length ); |
| 2446 | } |
| 2447 | } |
| 2448 | |
| 2449 | if ( !matched ) { |
| 2450 | break; |
| 2451 | } |
| 2452 | } |
| 2453 | |
| 2454 | // Return the length of the invalid excess |
| 2455 | // if we're just parsing |