예제 #1
0
def parse_decls_inits(index, parse_inits=True):
    """Parse declarations and initializers into a decl_nodes.Root node.

    Ex:
       int a = 3, *b = &a;

    The decl_nodes node can be used by the caller to create a
    tree.nodes.Declaration node, and the decl_nodes node is traversed during
    the IL generation step to convert it into an appropriate ctype.

    If `parse_inits` is false, do not permit initializers. This is useful
    for parsing struct objects.

    Note that parse_declaration is simply a wrapper around this function. The
    reason this logic is not in parse_declaration directly is so that struct
    member list parsing can reuse this logic.
    """
    specs, index = parse_decl_specifiers(index)

    # If declaration specifiers are followed directly by semicolon
    if token_is(index, token_kinds.semicolon):
        return decl_nodes.Root(specs, []), index + 1

    is_typedef = any(tok.kind == token_kinds.typedef_kw for tok in specs)

    decls = []
    inits = []

    while True:
        node, index = parse_declarator(index, is_typedef)
        decls.append(node)

        if token_is(index, token_kinds.equals) and parse_inits:
            # Parse initializer expression
            from shivyc.parser.expression import parse_assignment
            expr, index = parse_assignment(index + 1)
            inits.append(expr)
        else:
            inits.append(None)

        # Expect a comma, break if there isn't one
        if token_is(index, token_kinds.comma):
            index += 1
        else:
            break

    index = match_token(index, token_kinds.semicolon, ParserError.AFTER)

    node = decl_nodes.Root(specs, decls, inits)
    return node, index
예제 #2
0
def parse_parameter_list(index):
    """Parse a function parameter list.

    Returns a list of decl_nodes arguments and the index right after the
    last argument token. This index should be the index of a closing
    parenthesis, but that check is left to the caller.

    index - index right past the opening parenthesis
    """
    # List of decl_nodes arguments
    params = []

    # No arguments
    if token_is(index, token_kinds.close_paren):
        return params, index

    while True:
        # Try parsing declaration specifiers, quit if no more exist
        specs, index = parse_decl_specifiers(index)

        end = find_decl_end(index)
        range = p.tokens[index].r + p.tokens[end - 1].r
        decl = parse_declarator(index, end)
        params.append(decl_nodes.Root(specs, [decl], None, [range]))

        index = end

        # Expect a comma, and break if there isn't one
        if token_is(index, token_kinds.comma):
            index += 1
        else:
            break

    return params, index
예제 #3
0
def parse_unary(index):
    """Parse unary expression."""

    unary_args = {
        token_kinds.incr: (parse_unary, expr_nodes.PreIncr),
        token_kinds.decr: (parse_unary, expr_nodes.PreDecr),
        token_kinds.amp: (parse_cast, expr_nodes.AddrOf),
        token_kinds.star: (parse_cast, expr_nodes.Deref),
        token_kinds.bool_not: (parse_cast, expr_nodes.BoolNot),
        token_kinds.plus: (parse_cast, expr_nodes.UnaryPlus),
        token_kinds.minus: (parse_cast, expr_nodes.UnaryMinus),
        token_kinds.compl: (parse_cast, expr_nodes.Compl)
    }

    if token_in(index, unary_args):
        parse_func, NodeClass = unary_args[p.tokens[index].kind]
        subnode, index = parse_func(index + 1)
        return NodeClass(subnode), index
    elif token_is(index, token_kinds.sizeof_kw):
        with log_error():
            node, index = parse_unary(index + 1)
            return expr_nodes.SizeofExpr(node), index

        from shivyc.parser.declaration import (parse_abstract_declarator,
                                               parse_spec_qual_list)

        match_token(index + 1, token_kinds.open_paren, ParserError.AFTER)
        specs, index = parse_spec_qual_list(index + 2)
        node, index = parse_abstract_declarator(index)
        match_token(index, token_kinds.close_paren, ParserError.AT)
        decl_node = decl_nodes.Root(specs, [node])

        return expr_nodes.SizeofType(decl_node), index + 1
    else:
        return parse_postfix(index)
예제 #4
0
def parse_decls_inits(index, parse_inits=True):
    """Parse declarations and initializers into a decl_nodes.Root node.

    The decl_nodes node is used by the caller to create a
    tree.nodes.Declaration node, and the decl_nodes node is traversed during
    the IL generation step to convert it into an appropriate ctype.

    If `parse_inits` is false, do not permit initializers. This is useful
    for parsing struct objects.
    """
    specs, index = parse_decl_specifiers(index)

    # If declaration specifiers are followed directly by semicolon
    if token_is(index, token_kinds.semicolon):
        return decl_nodes.Root(specs, [], [], []), index + 1

    decls = []
    ranges = []
    inits = []

    while True:
        end = find_decl_end(index)
        decls.append(parse_declarator(index, end))
        ranges.append(p.tokens[index].r + p.tokens[end - 1].r)

        index = end
        if token_is(index, token_kinds.equals) and parse_inits:
            # Parse initializer expression
            # Currently, only simple initializers are supported
            expr, index = parse_assignment(index + 1)
            inits.append(expr)
        else:
            inits.append(None)

        # Expect a comma, break if there isn't one
        if token_is(index, token_kinds.comma):
            index += 1
        else:
            break

    index = match_token(index, token_kinds.semicolon, ParserError.AFTER)

    node = decl_nodes.Root(specs, decls, inits, ranges)
    return node, index
예제 #5
0
def parse_func_definition(index):
    """Parse a function definition.

    This function parses all parts of the function definition, from the
    declaration specifiers to the end of the function definition body. """

    specs, index = parse_decl_specifiers(index)
    decl, index = parse_declarator(index)

    from shivyc.parser.statement import parse_compound_statement
    body, index = parse_compound_statement(index)

    root = decl_nodes.Root(specs, [decl])
    return nodes.Declaration(root, body), index
예제 #6
0
def parse_cast(index):
    """Parse cast expression."""

    from shivyc.parser.declaration import (parse_abstract_declarator,
                                           parse_spec_qual_list)

    with log_error():
        match_token(index, token_kinds.open_paren, ParserError.AT)
        specs, index = parse_spec_qual_list(index + 1)
        node, index = parse_abstract_declarator(index)
        match_token(index, token_kinds.close_paren, ParserError.AT)

        decl_node = decl_nodes.Root(specs, [node])
        expr_node, index = parse_cast(index + 1)
        return expr_nodes.Cast(decl_node, expr_node), index

    return parse_unary(index)