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 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
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
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_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 = utils.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 + utils.tokens[index - 1].r
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_cast(index): """ Parse cast expression """ from myparser.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)
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_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 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
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(utils.tokens[index]), index + 1 elif token_is(index, token_kinds.identifier) and not utils.symbols.is_typedef( utils.tokens[index]): return expr_nodes.Identifier(utils.tokens[index]), index + 1 elif token_is(index, token_kinds.string): return expr_nodes.String(utils.tokens[index].content), index + 1 elif token_is(index, token_kinds.char_string): chars = utils.tokens[index].content return expr_nodes.Number(chars[0]), index + 1 else: raise_error("expected expression", index, ParserError.GOT)
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 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 myparser.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
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
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