Exemple #1
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
Exemple #2
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
Exemple #3
0
def parse_root(index):
    """Parse the given tokens into an AST."""
    items = []
    while True:
        try:
            item, index = parse_main(index)
            items.append(item)
        except ParserError as e:
            log_error(e)
        else:
            continue

        try:
            item, index = parse_declaration(index)
            items.append(item)
        except ParserError as e:
            log_error(e)
        else:
            continue

        # If neither parse attempt above worked, break
        break

    # If there are tokens that remain unparsed, complain
    if not p.tokens[index:]:
        return nodes.Root(items), index
    else:
        raise_error("unexpected token", index, ParserError.AT)
Exemple #4
0
def parse(tokens_to_parse):
    """Parse the given tokens into an AST.

    Also, as the entry point for the parser, responsible for setting the
    tokens global variable.
    """
    p.best_error = None
    p.tokens = tokens_to_parse

    try:
        return parse_root(0)[0]
    except ParserError as e:
        log_error(e)
        error_collector.add(p.best_error)
        return None
Exemple #5
0
def parse_statement(index):
    """Parse a statement.

    Try each possible type of statement, catching/logging exceptions upon
    parse failures. On the last try, raise the exception on to the caller.

    """
    for func in (parse_compound_statement, parse_return, parse_break,
                 parse_continue, parse_if_statement, parse_while_statement,
                 parse_for_statement):
        try:
            return func(index)
        except ParserError as e:
            log_error(e)

    return parse_expr_statement(index)
Exemple #6
0
def try_parse_func_decl(start, end):
    """Parse a function declarator between start and end.

    Expects that tokens[end-1] is a close parenthesis. If a function
    declarator is successfully parsed, returns the decl_node.Function
    object. Otherwise, returns None.
    """
    open_paren = find_pair_backward(end - 1)
    try:
        params, index = parse_parameter_list(open_paren + 1)
    except ParserError as e:
        log_error(e)
        return None

    if index == end - 1:
        return decl_nodes.Function(params, parse_declarator(start, open_paren))
Exemple #7
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)
Exemple #8
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)
Exemple #9
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

    try:
        return parse_declaration(index)
    except ParserError as e:
        log_error(e)

    clause, index = parse_expression(index)
    index = match_token(index, token_kinds.semicolon, ParserError.AFTER)
    return clause, index
Exemple #10
0
def parse_root(index):
    """Parse the given tokens into an AST."""
    items = []
    while True:
        with log_error():
            item, index = parse_func_definition(index)
            items.append(item)
            continue

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

        # If neither parse attempt above worked, break
        break

    # If there are tokens that remain unparsed, complain
    if not p.tokens[index:]:
        return nodes.Root(items), index
    else:
        raise_error("unexpected token", index, ParserError.AT)
Exemple #11
0
def parse(tokens_to_parse):
    """Parse the given tokens into an AST.

    Also, as the entry point for the parser, responsible for setting the
    tokens global variable.
    """
    p.best_error = None
    p.tokens = tokens_to_parse

    with log_error():
        return parse_root(0)[0]

    error_collector.add(p.best_error)
    return None
Exemple #12
0
def parse_statement(index):
    """Parse a statement.

    Try each possible type of statement, catching/logging exceptions upon
    parse failures. On the last try, raise the exception on to the caller.

    """
    for func in (parse_compound_statement, parse_return, parse_break,
                 parse_continue, parse_if_statement, parse_while_statement,
                 parse_for_statement):
        with log_error():
            return func(index)

    return parse_expr_statement(index)
Exemple #13
0
def _try_parse_func_decl(start, end, is_typedef=False):
    """Parse a function declarator between start and end.

    If a function declarator is successfully parsed, returns the
    decl_node.Function object. Otherwise, returns None.
    """
    if not token_is(end - 1, token_kinds.close_paren):
        return None

    open_paren = _find_pair_backward(end - 1)
    with log_error():
        params, index = parse_parameter_list(open_paren + 1)
        if index == end - 1:
            return decl_nodes.Function(
                params, _parse_declarator(start, open_paren, is_typedef))

    return None
Exemple #14
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)
Exemple #15
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)
Exemple #16
0
def _try_parse_func_decl(start, end, is_typedef=False):
    """Parse a function declarator between start and end.

    If a function declarator is successfully parsed, returns the
    decl_node.Function object. Otherwise, returns None.
    """
    if not token_is(end - 1, token_kinds.close_paren):
        return None

    open_paren = _find_pair_backward(end - 1)
    with log_error():
        params, index = parse_parameter_list(open_paren + 1)
        if index == end - 1:
            return decl_nodes.Function(
                params, _parse_declarator(start, open_paren, is_typedef))

    return None
Exemple #17
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