| 1435 | Expr.setFilters = new setFilters(); |
| 1436 | |
| 1437 | function tokenize(selector, parseOnly) { |
| 1438 | var matched, match, tokens, type, |
| 1439 | soFar, groups, preFilters, |
| 1440 | cached = tokenCache[selector + " "]; |
| 1441 | |
| 1442 | if (cached) { |
| 1443 | return parseOnly ? 0 : cached.slice(0); |
| 1444 | } |
| 1445 | |
| 1446 | soFar = selector; |
| 1447 | groups = []; |
| 1448 | preFilters = Expr.preFilter; |
| 1449 | |
| 1450 | while (soFar) { |
| 1451 | |
| 1452 | // Comma and first run |
| 1453 | if (!matched || (match = rcomma.exec(soFar))) { |
| 1454 | if (match) { |
| 1455 | // Don't consume trailing commas as valid |
| 1456 | soFar = soFar.slice(match[0].length) || soFar; |
| 1457 | } |
| 1458 | groups.push(tokens = []); |
| 1459 | } |
| 1460 | |
| 1461 | matched = false; |
| 1462 | |
| 1463 | // Combinators |
| 1464 | if ((match = rcombinators.exec(soFar))) { |
| 1465 | matched = match.shift(); |
| 1466 | tokens.push({ |
| 1467 | value: matched, |
| 1468 | // Cast descendant combinators to space |
| 1469 | type: match[0].replace(rtrim, " ") |
| 1470 | }); |
| 1471 | soFar = soFar.slice(matched.length); |
| 1472 | } |
| 1473 | |
| 1474 | // Filters |
| 1475 | for (type in Expr.filter) { |
| 1476 | if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] || |
| 1477 | (match = preFilters[type](match)))) { |
| 1478 | matched = match.shift(); |
| 1479 | tokens.push({ |
| 1480 | value: matched, |
| 1481 | type: type, |
| 1482 | matches: match |
| 1483 | }); |
| 1484 | soFar = soFar.slice(matched.length); |
| 1485 | } |
| 1486 | } |
| 1487 | |
| 1488 | if (!matched) { |
| 1489 | break; |
| 1490 | } |
| 1491 | } |
| 1492 | |
| 1493 | // Return the length of the invalid excess |
| 1494 | // if we're just parsing |