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
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
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
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
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
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
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
def _parse_declarator_raw(start, end, is_typedef): """Like _parse_declarator, but doesn't add `.r` range attribute.""" if start == end: return decl_nodes.Identifier(None) elif (start + 1 == end and p.tokens[start].kind == token_kinds.identifier): p.symbols.add_symbol(p.tokens[start], is_typedef) return decl_nodes.Identifier(p.tokens[start]) elif p.tokens[start].kind == token_kinds.star: const, index = _find_const(start + 1) return decl_nodes.Pointer(_parse_declarator(index, end, is_typedef), const) func_decl = _try_parse_func_decl(start, end, is_typedef) if func_decl: return func_decl # First and last elements make a parenthesis pair elif (p.tokens[start].kind == token_kinds.open_paren and _find_pair_forward(start) == end - 1): return _parse_declarator(start + 1, end - 1, is_typedef) # Last element indicates an array type elif p.tokens[end - 1].kind == token_kinds.close_sq_brack: open_sq = _find_pair_backward( end - 1, token_kinds.open_sq_brack, token_kinds.close_sq_brack, "mismatched square brackets in declaration") if open_sq == end - 2: num_el = None else: num_el, index = parse_expression(open_sq + 1) if index != end - 1: err = "unexpected token in array size" raise_error(err, index, ParserError.AFTER) return decl_nodes.Array(num_el, _parse_declarator(start, open_sq, is_typedef)) raise_error("faulty declaration syntax", start, ParserError.AT)
def _parse_declarator_raw(start, end, is_typedef): """Like _parse_declarator, but doesn't add `.r` range attribute.""" if start == end: return decl_nodes.Identifier(None) elif (start + 1 == end and p.tokens[start].kind == token_kinds.identifier): p.symbols.add_symbol(p.tokens[start], is_typedef) return decl_nodes.Identifier(p.tokens[start]) elif p.tokens[start].kind == token_kinds.star: const, index = _find_const(start + 1) return decl_nodes.Pointer( _parse_declarator(index, end, is_typedef), const) func_decl = _try_parse_func_decl(start, end, is_typedef) if func_decl: return func_decl # First and last elements make a parenthesis pair elif (p.tokens[start].kind == token_kinds.open_paren and _find_pair_forward(start) == end - 1): return _parse_declarator(start + 1, end - 1, is_typedef) # Last element indicates an array type elif p.tokens[end - 1].kind == token_kinds.close_sq_brack: open_sq = _find_pair_backward( end - 1, token_kinds.open_sq_brack, token_kinds.close_sq_brack, "mismatched square brackets in declaration") if open_sq == end - 2: num_el = None else: num_el, index = parse_expression(open_sq + 1) if index != end - 1: err = "unexpected token in array size" raise_error(err, index, ParserError.AFTER) return decl_nodes.Array( num_el, _parse_declarator(start, open_sq, is_typedef)) raise_error("faulty declaration syntax", start, ParserError.AT)
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