def close_scope(self, node, prefix_attr='prefix', suffix_attr='suffix', trailing_comma=False, single_paren=False): """Close a parenthesized scope on the given node, if one is open.""" # Ensures the prefix + suffix are not None if fmt.get(node, prefix_attr) is None: fmt.set(node, prefix_attr, '') if fmt.get(node, suffix_attr) is None: fmt.set(node, suffix_attr, '') if not self._parens or node not in self._scope_stack[-1]: return symbols = {')'} if trailing_comma: symbols.add(',') parsed_to_i = self._i parsed_to_loc = prev_loc = self._loc encountered_paren = False result = '' for tok in self.takewhile( lambda t: t.type in FORMATTING_TOKENS or t.src in symbols): # Consume all space up to this token result += self._space_between(prev_loc, tok) if tok.src == ')' and single_paren and encountered_paren: self.rewind() parsed_to_i = self._i parsed_to_loc = tok.start fmt.append(node, suffix_attr, result) break # Consume the token itself result += tok.src if tok.src == ')': # Close out the open scope encountered_paren = True self._scope_stack.pop() fmt.prepend(node, prefix_attr, self._parens.pop()) fmt.append(node, suffix_attr, result) result = '' parsed_to_i = self._i parsed_to_loc = tok.end if not self._parens or node not in self._scope_stack[-1]: break prev_loc = tok.end # Reset back to the last place where we parsed anything self._i = parsed_to_i self._loc = parsed_to_loc
def optional_token(self, node, attr_name, token_val, allow_whitespace_prefix=False, default=False): """Try to parse a token and attach it to the node.""" del default fmt.append(node, attr_name, '') token = (self.tokens.peek_non_whitespace() if allow_whitespace_prefix else self.tokens.peek()) if token and token.src == token_val: parsed = '' if allow_whitespace_prefix: parsed += self.ws() fmt.append(node, attr_name, parsed + self.tokens.next().src + self.ws())