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
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
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)
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
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
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)