예제 #1
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)
예제 #2
0
def parse_compound_statement(index):
    """Parse a compound statement.

    A compound statement is a collection of several
    statements/declarations, enclosed in braces.

    """
    p.symbols.new_scope()
    index = match_token(index, token_kinds.open_brack, ParserError.GOT)

    # Read block items (statements/declarations) until there are no more.
    items = []
    while True:
        with log_error():
            item, index = parse_statement(index)
            items.append(item)
            continue

        with log_error():
            item, index = parse_declaration(index)
            items.append(item)
            continue

        break

    index = match_token(index, token_kinds.close_brack, ParserError.GOT)
    p.symbols.end_scope()

    return nodes.Compound(items), index
예제 #3
0
def _get_for_clauses(index):
    """Get the three clauses of a for-statement.

    index - Index of the beginning of the first clause.

    returns - Tuple (Node, Node, Node, index). Each Node is the corresponding
    clause, or None if that clause is empty The index is that of first token
    after the close paren terminating the for clauses.

    Raises exception on malformed input.
    """

    first, index = _get_first_for_clause(index)

    if token_is(index, token_kinds.semicolon):
        second = None
        index += 1
    else:
        second, index = parse_expression(index)
        index = match_token(index, token_kinds.semicolon, ParserError.AFTER)

    if token_is(index, token_kinds.close_paren):
        third = None
        index = index + 1
    else:
        third, index = parse_expression(index)
        index = match_token(index, token_kinds.close_paren, ParserError.AFTER)

    return first, second, third, index
예제 #4
0
def parse_compound_statement(index):
    """Parse a compound statement.

    A compound statement is a collection of several
    statements/declarations, enclosed in braces.

    """
    index = match_token(index, token_kinds.open_brack, ParserError.GOT)

    # Read block items (statements/declarations) until there are no more.
    items = []
    while True:
        try:
            item, index = parse_statement(index)
            items.append(item)
            continue
        except ParserError as e:
            log_error(e)

        try:
            item, index = parse_declaration(index)
            items.append(item)
            continue
        except ParserError as e:
            log_error(e)
            # When both of our parsing attempts fail, break out of the loop
            break

    index = match_token(index, token_kinds.close_brack, ParserError.GOT)

    return nodes.Compound(items), index
예제 #5
0
def _get_for_clauses(index):
    """Get the three clauses of a for-statement.

    index - Index of the beginning of the first clause.

    returns - Tuple (Node, Node, Node, index). Each Node is the corresponding
    clause, or None if that clause is empty The index is that of first token
    after the close paren terminating the for clauses.

    Raises exception on malformed input.
    """

    first, index = _get_first_for_clause(index)

    if token_is(index, token_kinds.semicolon):
        second = None
        index += 1
    else:
        second, index = parse_expression(index)
        index = match_token(index, token_kinds.semicolon, ParserError.AFTER)

    if token_is(index, token_kinds.close_paren):
        third = None
        index += 1
    else:
        third, index = parse_expression(index)
        index = match_token(index, token_kinds.close_paren, ParserError.AFTER)

    return first, second, third, index
예제 #6
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)
예제 #7
0
def parse_postfix(index):
    """Parse postfix expression."""
    cur, index = parse_primary(index)

    while True:
        old_range = cur.r

        if token_is(index, token_kinds.open_sq_brack):
            index += 1
            arg, index = parse_expression(index)
            cur = expr_nodes.ArraySubsc(cur, arg)
            match_token(index, token_kinds.close_sq_brack, ParserError.GOT)
            index += 1

        elif (token_is(index, token_kinds.dot) or
              token_is(index, token_kinds.arrow)):
            index += 1
            match_token(index, token_kinds.identifier, ParserError.AFTER)
            member = p.tokens[index]

            if token_is(index - 1, token_kinds.dot):
                cur = expr_nodes.ObjMember(cur, member)
            else:
                cur = expr_nodes.ObjPtrMember(cur, member)

            index += 1

        elif token_is(index, token_kinds.open_paren):
            args = []
            index += 1

            if token_is(index, token_kinds.close_paren):
                return expr_nodes.FuncCall(cur, args), index + 1

            while True:
                arg, index = parse_assignment(index)
                args.append(arg)

                if token_is(index, token_kinds.comma):
                    index += 1
                else:
                    break

            index = match_token(
                index, token_kinds.close_paren, ParserError.GOT)

            return expr_nodes.FuncCall(cur, args), index

        elif token_is(index, token_kinds.incr):
            index += 1
            cur = expr_nodes.PostIncr(cur)
        elif token_is(index, token_kinds.decr):
            index += 1
            cur = expr_nodes.PostDecr(cur)
        else:
            return cur, index

        cur.r = old_range + p.tokens[index - 1].r
예제 #8
0
def parse_postfix(index):
    """Parse postfix expression."""
    cur, index = parse_primary(index)

    while True:
        old_range = cur.r

        if token_is(index, token_kinds.open_sq_brack):
            index += 1
            arg, index = parse_expression(index)
            cur = expr_nodes.ArraySubsc(cur, arg)
            match_token(index, token_kinds.close_sq_brack, ParserError.GOT)
            index += 1

        elif (token_is(index, token_kinds.dot)
              or token_is(index, token_kinds.arrow)):
            index += 1
            match_token(index, token_kinds.identifier, ParserError.AFTER)
            member = p.tokens[index]

            if token_is(index - 1, token_kinds.dot):
                cur = expr_nodes.ObjMember(cur, member)
            else:
                cur = expr_nodes.ObjPtrMember(cur, member)

            index += 1

        elif token_is(index, token_kinds.open_paren):
            args = []
            index += 1

            if token_is(index, token_kinds.close_paren):
                return expr_nodes.FuncCall(cur, args), index + 1

            while True:
                arg, index = parse_assignment(index)
                args.append(arg)

                if token_is(index, token_kinds.comma):
                    index += 1
                else:
                    break

            index = match_token(index, token_kinds.close_paren,
                                ParserError.GOT)

            return expr_nodes.FuncCall(cur, args), index

        elif token_is(index, token_kinds.incr):
            index += 1
            cur = expr_nodes.PostIncr(cur)
        elif token_is(index, token_kinds.decr):
            index += 1
            cur = expr_nodes.PostDecr(cur)
        else:
            return cur, index

        cur.r = old_range + p.tokens[index - 1].r
예제 #9
0
def parse_while_statement(index):
    """Parse a while statement."""
    index = match_token(index, token_kinds.while_kw, ParserError.GOT)
    index = match_token(index, token_kinds.open_paren, ParserError.AFTER)
    conditional, index = parse_expression(index)
    index = match_token(index, token_kinds.close_paren, ParserError.AFTER)
    statement, index = parse_statement(index)

    return nodes.WhileStatement(conditional, statement), index
예제 #10
0
def parse_for_statement(index):
    """Parse a for statement."""
    index = match_token(index, token_kinds.for_kw, ParserError.GOT)
    index = match_token(index, token_kinds.open_paren, ParserError.AFTER)

    first, second, third, index = _get_for_clauses(index)
    stat, index = parse_statement(index)

    return nodes.ForStatement(first, second, third, stat), index
예제 #11
0
def parse_for_statement(index):
    """Parse a for statement."""
    index = match_token(index, token_kinds.for_kw, ParserError.GOT)
    index = match_token(index, token_kinds.open_paren, ParserError.AFTER)

    first, second, third, index = _get_for_clauses(index)
    stat, index = parse_statement(index)

    return nodes.ForStatement(first, second, third, stat), index
예제 #12
0
def parse_while_statement(index):
    """Parse a while statement."""
    index = match_token(index, token_kinds.while_kw, ParserError.GOT)
    index = match_token(index, token_kinds.open_paren, ParserError.AFTER)
    conditional, index = parse_expression(index)
    index = match_token(index, token_kinds.close_paren, ParserError.AFTER)
    statement, index = parse_statement(index)

    return nodes.WhileStatement(conditional, statement), index
예제 #13
0
def parse_return(index):
    """Parse a return statement.

    Ex: return 5;

    """
    index = match_token(index, token_kinds.return_kw, ParserError.GOT)
    node, index = parse_expression(index)

    index = match_token(index, token_kinds.semicolon, ParserError.AFTER)
    return nodes.Return(node), index
예제 #14
0
def parse_return(index):
    """Parse a return statement.

    Ex: return 5;

    """
    index = match_token(index, token_kinds.return_kw, ParserError.GOT)
    if token_is(index, token_kinds.semicolon):
        return nodes.Return(None), index

    node, index = parse_expression(index)

    index = match_token(index, token_kinds.semicolon, ParserError.AFTER)
    return nodes.Return(node), index
예제 #15
0
파일: parser.py 프로젝트: zqxyz73/ShivyC
def parse_main(index):
    """Parse a main function containing block items.

    Ex: int main() { return 4; }

    """
    err = "expected main function starting"
    index = match_token(index, token_kinds.int_kw, ParserError.AT, err)
    index = match_token(index, token_kinds.main, ParserError.AT, err)
    index = match_token(index, token_kinds.open_paren, ParserError.AT, err)
    index = match_token(index, token_kinds.close_paren, ParserError.AT, err)

    node, index = parse_compound_statement(index)
    return nodes.Main(node), index
예제 #16
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)
예제 #17
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)
예제 #18
0
def parse_if_statement(index):
    """Parse an if statement."""

    index = match_token(index, token_kinds.if_kw, ParserError.GOT)
    index = match_token(index, token_kinds.open_paren, ParserError.AFTER)
    conditional, index = parse_expression(index)
    index = match_token(index, token_kinds.close_paren, ParserError.AFTER)
    statement, index = parse_statement(index)

    # If there is an else that follows, parse that too.
    is_else = token_is(index, token_kinds.else_kw)
    if not is_else:
        else_statement = None
    else:
        index = match_token(index, token_kinds.else_kw, ParserError.GOT)
        else_statement, index = parse_statement(index)

    return nodes.IfStatement(conditional, statement, else_statement), index
예제 #19
0
def parse_if_statement(index):
    """Parse an if statement."""

    index = match_token(index, token_kinds.if_kw, ParserError.GOT)
    index = match_token(index, token_kinds.open_paren, ParserError.AFTER)
    conditional, index = parse_expression(index)
    index = match_token(index, token_kinds.close_paren, ParserError.AFTER)
    statement, index = parse_statement(index)

    # If there is an else that follows, parse that too.
    is_else = token_is(index, token_kinds.else_kw)
    if not is_else:
        else_statement = None
    else:
        index = match_token(index, token_kinds.else_kw, ParserError.GOT)
        else_statement, index = parse_statement(index)

    return nodes.IfStatement(conditional, statement, else_statement), index
예제 #20
0
def parse_expr_statement(index):
    """Parse a statement that is an expression.

    Ex: a = 3 + 4

    """
    if token_is(index, token_kinds.semicolon):
        return nodes.EmptyStatement(), index + 1

    node, index = parse_expression(index)
    index = match_token(index, token_kinds.semicolon, ParserError.AFTER)
    return nodes.ExprStatement(node), index
예제 #21
0
def parse_expr_statement(index):
    """Parse a statement that is an expression.

    Ex: a = 3 + 4

    """
    if token_is(index, token_kinds.semicolon):
        return nodes.EmptyStatement(), index + 1

    node, index = parse_expression(index)
    index = match_token(index, token_kinds.semicolon, ParserError.AFTER)
    return nodes.ExprStatement(node), index
예제 #22
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
예제 #23
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
예제 #24
0
def parse_primary(index):
    """Parse primary expression."""
    if token_is(index, token_kinds.open_paren):
        node, index = parse_expression(index + 1)
        index = match_token(index, token_kinds.close_paren, ParserError.GOT)
        return expr_nodes.ParenExpr(node), index
    elif token_is(index, token_kinds.number):
        return expr_nodes.Number(p.tokens[index]), index + 1
    elif token_is(index, token_kinds.identifier):
        return expr_nodes.Identifier(p.tokens[index]), index + 1
    elif token_is(index, token_kinds.string):
        return expr_nodes.String(p.tokens[index].content), index + 1
    elif token_is(index, token_kinds.char_string):
        chars = p.tokens[index].content
        return expr_nodes.Number(chars[0]), index + 1
    else:
        raise_error("expected expression", index, ParserError.GOT)
예제 #25
0
def parse_primary(index):
    """Parse primary expression."""
    if token_is(index, token_kinds.open_paren):
        node, index = parse_expression(index + 1)
        index = match_token(index, token_kinds.close_paren, ParserError.GOT)
        return expr_nodes.ParenExpr(node), index
    elif token_is(index, token_kinds.number):
        return expr_nodes.Number(p.tokens[index]), index + 1
    elif (token_is(index, token_kinds.identifier)
          and not p.symbols.is_typedef(p.tokens[index])):
        return expr_nodes.Identifier(p.tokens[index]), index + 1
    elif token_is(index, token_kinds.string):
        return expr_nodes.String(p.tokens[index].content), index + 1
    elif token_is(index, token_kinds.char_string):
        chars = p.tokens[index].content
        return expr_nodes.Number(chars[0]), index + 1
    else:
        raise_error("expected expression", index, ParserError.GOT)
예제 #26
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
예제 #27
0
def _get_first_for_clause(index):
    """Get the first clause of a for-statement.

    index - Index of the beginning of the first clause in the for-statement.
    returns - Tuple. First element is a node if a clause is found and None if
    there is no clause (i.e. semicolon terminating the clause). Second element
    is an integer index where the next token begins.

    If malformed, raises exception.

    """
    if token_is(index, token_kinds.semicolon):
        return None, index + 1

    with log_error():
        return parse_declaration(index)

    clause, index = parse_expression(index)
    index = match_token(index, token_kinds.semicolon, ParserError.AFTER)
    return clause, index
예제 #28
0
def parse_break(index):
    """Parse a break statement."""
    index = match_token(index, token_kinds.break_kw, ParserError.GOT)
    index = match_token(index, token_kinds.semicolon, ParserError.AFTER)
    return nodes.Break(), index
예제 #29
0
def parse_continue(index):
    """Parse a continue statement."""
    index = match_token(index, token_kinds.continue_kw, ParserError.GOT)
    index = match_token(index, token_kinds.semicolon, ParserError.AFTER)
    return nodes.Continue(), index
예제 #30
0
def parse_break(index):
    """Parse a break statement."""
    index = match_token(index, token_kinds.break_kw, ParserError.GOT)
    index = match_token(index, token_kinds.semicolon, ParserError.AFTER)
    return nodes.Break(), index
예제 #31
0
def parse_continue(index):
    """Parse a continue statement."""
    index = match_token(index, token_kinds.continue_kw, ParserError.GOT)
    index = match_token(index, token_kinds.semicolon, ParserError.AFTER)
    return nodes.Continue(), index