def match_tokens(tree, tokens, args):
    """Check if stack of tokens matches the Tree structure
    
    Special matching rules that can be specified in the template::

        ':label': Label a token, the token will be returned as part of the context with key 'label'.
        '-@': Additional single letter argument determining return format of labeled token. Valid options are:
            '-r': Return token as word
            '-o': Return token as object
        '=word|word2|....|wordn': Force match raw lower case
        '$': Match end of tree

    Args:
        tree : Parsed tree structure
        tokens : Stack of tokens
    Returns:
        Boolean if they match or not
    """
    arg_type_to_func = {
        'r': get_raw_lower,
        'R': get_raw,
        'o': get_object_lower,
        'O': get_object,
    }

    if len(tokens) == 0:
        return True

    if not isinstance(tree, Tree):
        return False

    root_token = tokens[0]

    # Equality
    if root_token.find('=') >= 0:
        eq_tokens = root_token.split('=')[1].lower().split('|')
        root_token = root_token.split('=')[0]
        word = get_raw_lower(tree)
        if word not in eq_tokens:
            return False

    # Get arg
    if root_token.find(':') >= 0:
        arg_tokens = root_token.split(':')[1].split('-')
        if len(arg_tokens) == 1:
            arg_name = arg_tokens[0]
            args[arg_name] = tree
        else:
            arg_name = arg_tokens[0]
            arg_type = arg_tokens[1]
            args[arg_name] = arg_type_to_func[arg_type](tree)
        root_token = root_token.split(':')[0]

    # Does not match wild card and label does not match
    if root_token != '.' and tree.label() not in root_token.split('/'):
        return False

    # Check end symbol
    if tokens[-1] == '$':
        if len(tree) != len(tokens[:-1]) - 1:
            return False
        else:
            tokens = tokens[:-1]

    # Check # of tokens
    if len(tree) < len(tokens) - 1:
        return False

    for i in range(len(tokens) - 1):
        if not match_tokens(tree[i], tokens[i + 1], args):
            return False
    return True
def match_tokens ( tree , tokens , args ) : arg_type_to_func = { 'r' : get_raw_lower , 'R' : get_raw , 'o' : get_object_lower , 'O' : get_object , } if len ( tokens ) == 0 : return True if not isinstance ( tree , Tree ) : return False root_token = tokens [ 0 ] if root_token . find ( '=' ) >= 0 : eq_tokens = root_token . split ( '=' ) [ 1 ] . lower ( ) . split ( '|' ) root_token = root_token . split ( '=' ) [ 0 ] word = get_raw_lower ( tree ) if word not in eq_tokens : return False if root_token . find ( ':' ) >= 0 : arg_tokens = root_token . split ( ':' ) [ 1 ] . split ( '-' ) if len ( arg_tokens ) == 1 : arg_name = arg_tokens [ 0 ] args [ arg_name ] = tree else : arg_name = arg_tokens [ 0 ] arg_type = arg_tokens [ 1 ] args [ arg_name ] = arg_type_to_func [ arg_type ] ( tree ) root_token = root_token . split ( ':' ) [ 0 ] if root_token != '.' and tree . label ( ) not in root_token . split ( '/' ) : return False if tokens [ - 1 ] == '$' : if len ( tree ) != len ( tokens [ : - 1 ] ) - 1 : return False else : tokens = tokens [ : - 1 ] if len ( tree ) < len ( tokens ) - 1 : return False for i in range ( len ( tokens ) - 1 ) : if not match_tokens ( tree [ i ] , tokens [ i + 1 ] , args ) : return False return True
Check if stack of tokens matches the Tree structure
    
    Special matching rules that can be specified in the template::

        ':label': Label a token, the token will be returned as part of the context with key 'label'.
        '-@': Additional single letter argument determining return format of labeled token. Valid options are:
            '-r': Return token as word
            '-o': Return token as object
        '=word|word2|....|wordn': Force match raw lower case
        '$': Match end of tree

    Args:
        tree : Parsed tree structure
        tokens : Stack of tokens
    Returns:
        Boolean if they match or not