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)
| 1927 | |
| 1928 | @staticmethod |
| 1929 | def _CollapseStrings(elided): |
| 1930 | """Collapses strings and chars on a line to simple "" or '' blocks. |
| 1931 | |
| 1932 | We nix strings first so we're not fooled by text like '"http://"' |
| 1933 | |
| 1934 | Args: |
| 1935 | elided: The line being processed. |
| 1936 | |
| 1937 | Returns: |
| 1938 | The line with collapsed strings. |
| 1939 | """ |
| 1940 | if _RE_PATTERN_INCLUDE.match(elided): |
| 1941 | return elided |
| 1942 | |
| 1943 | # Remove escaped characters first to make quote/single quote collapsing |
| 1944 | # basic. Things that look like escaped characters shouldn't occur |
| 1945 | # outside of strings and chars. |
| 1946 | elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) |
| 1947 | |
| 1948 | # Replace quoted strings and digit separators. Both single quotes |
| 1949 | # and double quotes are processed in the same loop, otherwise |
| 1950 | # nested quotes wouldn't work. |
| 1951 | collapsed = '' |
| 1952 | while True: |
| 1953 | # Find the first quote character |
| 1954 | match = Match(r'^([^\'"]*)([\'"])(.*)$', elided) |
| 1955 | if not match: |
| 1956 | collapsed += elided |
| 1957 | break |
| 1958 | head, quote, tail = match.groups() |
| 1959 | |
| 1960 | if quote == '"': |
| 1961 | # Collapse double quoted strings |
| 1962 | second_quote = tail.find('"') |
| 1963 | if second_quote >= 0: |
| 1964 | collapsed += head + '""' |
| 1965 | elided = tail[second_quote + 1:] |
| 1966 | else: |
| 1967 | # Unmatched double quote, don't bother processing the rest |
| 1968 | # of the line since this is probably a multiline string. |
| 1969 | collapsed += elided |
| 1970 | break |
| 1971 | else: |
| 1972 | # Found single quote, check nearby text to eliminate digit separators. |
| 1973 | # |
| 1974 | # There is no special handling for floating point here, because |
| 1975 | # the integer/fractional/exponent parts would all be parsed |
| 1976 | # correctly as long as there are digits on both sides of the |
| 1977 | # separator. So we are fine as long as we don't see something |
| 1978 | # like "0.'3" (gcc 4.9.0 will not allow this literal). |
| 1979 | if Search(r'\b(?:0[bBxX]?|[1-9])[0-9a-fA-F]*$', head): |
| 1980 | match_literal = Match(r'^((?:\'?[0-9a-zA-Z_])*)(.*)$', "'" + tail) |
| 1981 | collapsed += head + match_literal.group(1).replace("'", '') |
| 1982 | elided = match_literal.group(2) |
| 1983 | else: |
| 1984 | second_quote = tail.find('\'') |
| 1985 | if second_quote >= 0: |
| 1986 | collapsed += head + "''" |