Collapses strings and chars on a line to simple "" or '' blocks. We nix strings first so we're not fooled by text like '"http://"' Args: elided: The line being processed. Returns: The line with collapsed strings.
(elided)
| 1455 | |
| 1456 | @staticmethod |
| 1457 | def _CollapseStrings(elided): |
| 1458 | """Collapses strings and chars on a line to simple "" or '' blocks. |
| 1459 | |
| 1460 | We nix strings first so we're not fooled by text like '"http://"' |
| 1461 | |
| 1462 | Args: |
| 1463 | elided: The line being processed. |
| 1464 | |
| 1465 | Returns: |
| 1466 | The line with collapsed strings. |
| 1467 | """ |
| 1468 | if _RE_PATTERN_INCLUDE.match(elided): |
| 1469 | return elided |
| 1470 | |
| 1471 | # Remove escaped characters first to make quote/single quote collapsing |
| 1472 | # basic. Things that look like escaped characters shouldn't occur |
| 1473 | # outside of strings and chars. |
| 1474 | elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) |
| 1475 | |
| 1476 | # Replace quoted strings and digit separators. Both single quotes |
| 1477 | # and double quotes are processed in the same loop, otherwise |
| 1478 | # nested quotes wouldn't work. |
| 1479 | collapsed = '' |
| 1480 | while True: |
| 1481 | # Find the first quote character |
| 1482 | match = Match(r'^([^\'"]*)([\'"])(.*)$', elided) |
| 1483 | if not match: |
| 1484 | collapsed += elided |
| 1485 | break |
| 1486 | head, quote, tail = match.groups() |
| 1487 | |
| 1488 | if quote == '"': |
| 1489 | # Collapse double quoted strings |
| 1490 | second_quote = tail.find('"') |
| 1491 | if second_quote >= 0: |
| 1492 | collapsed += head + '""' |
| 1493 | elided = tail[second_quote + 1:] |
| 1494 | else: |
| 1495 | # Unmatched double quote, don't bother processing the rest |
| 1496 | # of the line since this is probably a multiline string. |
| 1497 | collapsed += elided |
| 1498 | break |
| 1499 | else: |
| 1500 | # Found single quote, check nearby text to eliminate digit separators. |
| 1501 | # |
| 1502 | # There is no special handling for floating point here, because |
| 1503 | # the integer/fractional/exponent parts would all be parsed |
| 1504 | # correctly as long as there are digits on both sides of the |
| 1505 | # separator. So we are fine as long as we don't see something |
| 1506 | # like "0.'3" (gcc 4.9.0 will not allow this literal). |
| 1507 | if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head): |
| 1508 | match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail) |
| 1509 | collapsed += head + match_literal.group(1).replace("'", '') |
| 1510 | elided = match_literal.group(2) |
| 1511 | else: |
| 1512 | second_quote = tail.find('\'') |
| 1513 | if second_quote >= 0: |
| 1514 | collapsed += head + "''" |