#NEWLINE# def regroup( tokens ) : #NEWLINE# #INDENT# '\n    Match pairs of tokens: () [] {} function()\n    (Strings in "" or \'\' are taken care of by the tokenizer.)\n\n    Opening tokens are replaced by a :class:`ContainerToken`.\n    Closing tokens are removed. Unmatched closing tokens are invalid\n    but left as-is. All nested structures that are still open at\n    the end of the stylesheet are implicitly closed.\n\n    :param tokens:\n        a *flat* iterable of tokens, as returned by :func:`tokenize_flat`.\n    :return:\n        A tree of tokens.\n\n    ' #NEWLINE# pairs = { #NEWLINE# #INDENT# 'FUNCTION' : ')' , #NEWLINE# '(' : ')' , #NEWLINE# '[' : ']' , #NEWLINE# '{' : '}' , #NEWLINE# #UNINDENT# } #NEWLINE# tokens = iter ( tokens ) #NEWLINE# eof = [ False ] #NEWLINE# def _regroup_inner( stop_at = None , tokens = tokens , pairs = pairs , eof = eof , ContainerToken = token_data . ContainerToken , FunctionToken = token_data . FunctionToken ) : #NEWLINE# #INDENT# for token in tokens : #NEWLINE# #INDENT# type_ = token . type #NEWLINE# if ( type_ == stop_at ) : #NEWLINE# #INDENT# return #NEWLINE# #UNINDENT# end = pairs . get ( type_ ) #NEWLINE# if ( end is None ) : #NEWLINE# #INDENT# ( yield token ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# assert ( not isinstance ( token , ContainerToken ) ) , 'Token looks already grouped: {0}' . format ( token ) #NEWLINE# content = list ( _regroup_inner ( end ) ) #NEWLINE# if eof [ 0 ] : #NEWLINE# #INDENT# end = '' #NEWLINE# #UNINDENT# if ( type_ == 'FUNCTION' ) : #NEWLINE# #INDENT# ( yield FunctionToken ( token . type , token . as_css ( ) , end , token . value , content , token . line , token . column ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# ( yield ContainerToken ( token . type , token . as_css ( ) , end , content , token . line , token . column ) ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# eof [ 0 ] = True #NEWLINE# #UNINDENT# #UNINDENT# return _regroup_inner ( )