r"""Retrieves all the text between matching open and close parentheses. Given a string of lines and a regular expression string, retrieve all the text following the expression and between opening punctuation symbols like (, [, or {, and the matching close-punctuation symbol. This properly nes
(text, start_pattern)
| 3754 | |
| 3755 | |
| 3756 | def _GetTextInside(text, start_pattern): |
| 3757 | r"""Retrieves all the text between matching open and close parentheses. |
| 3758 | |
| 3759 | Given a string of lines and a regular expression string, retrieve all the text |
| 3760 | following the expression and between opening punctuation symbols like |
| 3761 | (, [, or {, and the matching close-punctuation symbol. This properly nested |
| 3762 | occurrences of the punctuations, so for the text like |
| 3763 | printf(a(), b(c())); |
| 3764 | a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. |
| 3765 | start_pattern must match string having an open punctuation symbol at the end. |
| 3766 | |
| 3767 | Args: |
| 3768 | text: The lines to extract text. Its comments and strings must be elided. |
| 3769 | It can be single line and can span multiple lines. |
| 3770 | start_pattern: The regexp string indicating where to start extracting |
| 3771 | the text. |
| 3772 | Returns: |
| 3773 | The extracted text. |
| 3774 | None if either the opening string or ending punctuation could not be found. |
| 3775 | """ |
| 3776 | # TODO(sugawarayu): Audit cpplint.py to see what places could be profitably |
| 3777 | # rewritten to use _GetTextInside (and use inferior regexp matching today). |
| 3778 | |
| 3779 | # Give opening punctuations to get the matching close-punctuations. |
| 3780 | matching_punctuation = {'(': ')', '{': '}', '[': ']'} |
| 3781 | closing_punctuation = set(itervalues(matching_punctuation)) |
| 3782 | |
| 3783 | # Find the position to start extracting text. |
| 3784 | match = re.search(start_pattern, text, re.M) |
| 3785 | if not match: # start_pattern not found in text. |
| 3786 | return None |
| 3787 | start_position = match.end(0) |
| 3788 | |
| 3789 | assert start_position > 0, ( |
| 3790 | 'start_pattern must ends with an opening punctuation.') |
| 3791 | assert text[start_position - 1] in matching_punctuation, ( |
| 3792 | 'start_pattern must ends with an opening punctuation.') |
| 3793 | # Stack of closing punctuations we expect to have in text after position. |
| 3794 | punctuation_stack = [matching_punctuation[text[start_position - 1]]] |
| 3795 | position = start_position |
| 3796 | while punctuation_stack and position < len(text): |
| 3797 | if text[position] == punctuation_stack[-1]: |
| 3798 | punctuation_stack.pop() |
| 3799 | elif text[position] in closing_punctuation: |
| 3800 | # A closing punctuation without matching opening punctuations. |
| 3801 | return None |
| 3802 | elif text[position] in matching_punctuation: |
| 3803 | punctuation_stack.append(matching_punctuation[text[position]]) |
| 3804 | position += 1 |
| 3805 | if punctuation_stack: |
| 3806 | # Opening punctuations left without matching close-punctuations. |
| 3807 | return None |
| 3808 | # punctuations match. |
| 3809 | return text[start_position:position - 1] |
| 3810 | |
| 3811 | |
| 3812 | # Patterns for matching call-by-reference parameters. |
no test coverage detected