/* A.2.2 Declarations (6.7) declaration: declaration-specifiers init-declarator-list(opt) ; (6.7) declaration-specifiers: storage-class-specifier declaration-specifiers(opt) type-specifier declaration-specifiers(opt) type-qualifier declaration-specifiers(opt) function-specifier declaration-specifiers(opt) (6.7) init-declarator-list: init-declarator init-declarator-list , init-declarator (6.7) init-declarator: declarator declarator = initializer (6.7.1) storage-class-specifier: typedef extern static auto register (6.7.2) type-specifier: void char short int long float double signed unsigned _Bool _Complex struct-or-union-specifier enum-specifier typedef-name (6.7.2.1) struct-or-union-specifier: struct-or-union identifier(opt) { struct-declaration-list } struct-or-union identifier (6.7.2.1) struct-or-union: struct union (6.7.2.1) struct-declaration-list: struct-declaration struct-declaration-list struct-declaration (6.7.2.1) struct-declaration: specifier-qualifier-list struct-declarator-list ; (6.7.2.1) specifier-qualifier-list: type-specifier specifier-qualifier-list(opt) type-qualifier specifier-qualifier-list(opt) (6.7.2.1) struct-declarator-list: struct-declarator struct-declarator-list , struct-declarator (6.7.2.1) struct-declarator: declarator declarator(opt) : constant-expression (6.7.2.2) enum-specifier: enum identifier(opt) { enumerator-list } enum identifier(opt) { enumerator-list ,} enum identifier (6.7.2.2) enumerator-list: enumerator enumerator-list , enumerator (6.7.2.2) enumerator: enumeration-constant enumeration-constant = constant-expression (6.7.3) type-qualifier: const restrict volatile (6.7.4) function-specifier: inline (6.7.5) declarator: pointer(opt) direct-declarator (6.7.5) direct-declarator: identifier ( declarator ) direct-declarator [ type-qualifier-list(opt) assignment-expression(opt) ] direct-declarator [ static type-qualifier-list(opt) assignment-expression ] direct-declarator [ type-qualifier-list static assignment-expression ] direct-declarator [ type-qualifier-list(opt) *] direct-declarator ( parameter-type-list ) direct-declarator ( identifier-list(opt) ) (6.7.5) pointer: * type-qualifier-list(opt) * type-qualifier-list(opt) pointer (6.7.5) type-qualifier-list: type-qualifier type-qualifier-list type-qualifier (6.7.5) parameter-type-list: parameter-list parameter-list , ... (6.7.5) parameter-list: parameter-declaration parameter-list , parameter-declaration (6.7.5) parameter-declaration: declaration-specifiers declarator declaration-specifiers abstract-declarator(opt) (6.7.5) identifier-list: identifier identifier-list , identifier (6.7.6) type-name: specifier-qualifier-list abstract-declarator(opt) (6.7.6) abstract-declarator: pointer pointer(opt) direct-abstract-declarator (6.7.6) direct-abstract-declarator: ( abstract-declarator ) direct-abstract-declarator(opt) [ type-qualifier-list (opt) assignment-expression(opt) ] direct-abstract-declarator(opt) [static type-qualifier-list(opt) assignment-expression ] direct-abstract-declaratoropt [ type-qualifier-list static assignment-expression ] direct-abstract-declarator(opt) [ * ] direct-abstract-declarator(opt) ( parameter-type-list(opt) ) (6.7.7) typedef-name: identifier (6.7.8) initializer: assignment-expression { initializer-list } { initializer-list , } (6.7.8) initializer-list: designation(opt) initializer initializer-list , designation(opt) initializer (6.7.8) designation: designator-list = (6.7.8) designator-list: designator designator-list designator (6.7.8) designator: [ constant-expression ] . identifier A.2.4 External definitions (6.9) translation-unit: external-declaration translation-unit external-declaration (6.9) external-declaration: function-definition declaration (6.9.1) function-definition: declaration-specifiers declarator declaration-list(opt) compound-statement (6.9.1) declaration-list: declaration declaration-list declaration */ #include #include scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) { /** * ISO/IEC 9899:TC3 * 6.7 Declarations * Syntax * * declaration: * declaration-specifiers init-declarator-list(opt) ; * declaration-specifiers: * storage-class-specifier declaration-specifiers(opt) * type-specifier declaration-specifiers(opt) * type-qualifier declaration-specifiers(opt) * function-specifier declaration-specifiers(opt) * init-declarator-list: * init-declarator * init-declarator-list , init-declarator * init-declarator: * declarator * declarator = initializer */ cbool ok; scc_lexer_tok_t tok; scc_ast_type_t *type = scc_parse_type(parser); if (type == null) { return null; } ok = scc_parser_next_consume(parser, &tok); if (ok == false) { return null; } scc_ast_decl_t *decl = scc_malloc(sizeof(scc_ast_decl_t)); /* (6.7.5) declarator: pointeropt direct-declarator (6.7.5) direct-declarator: identifier ( declarator ) direct-declarator [ type-qualifier-listopt assignment-expressionopt ] direct-declarator [static type-qualifier-listopt assignment-expression ] direct-declarator [ type-qualifier-list static assignment-expression ] direct-declarator [ type-qualifier-listopt *] direct-declarator ( parameter-type-list ) direct-declarator ( identifier-listopt ) */ if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) { if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { scc_ast_decl_val_init(decl, type, scc_cstring_as_cstr(&tok.lexeme), null); goto RETURN; } else if (scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) { scc_ast_expr_t *init = scc_parse_expression(parser); scc_ast_decl_val_init(decl, type, scc_cstring_as_cstr(&tok.lexeme), init); if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) { LOG_ERROR("expect semicolon"); } goto RETURN; } // TODO return null; } // function decl decl->base.type = SCC_AST_DECL_FUNC; decl->name = scc_cstring_as_cstr(&tok.lexeme); decl->func.type = scc_malloc(sizeof(scc_ast_type_t)); decl->func.type->base.type = SCC_AST_TYPE_FUNCTION; scc_vec_init(decl->func.type->function.param_types); decl->func.type->function.return_type = type; // TODO param type scc_parser_consume_if(parser, SCC_TOK_VOID); if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) { return null; } const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser); if (tok_ptr == null) { return null; } if (tok_ptr->type != SCC_TOK_L_BRACE) { if (tok_ptr->type == SCC_TOK_SEMICOLON) { decl->func.body = null; } else { return null; } } decl->func.body = scc_parse_statement(parser); Assert(decl->func.type != null); Assert(decl->func.type->base.type == SCC_AST_TYPE_FUNCTION); Assert(decl->func.body != null); Assert(decl->func.body->base.type == SCC_AST_STMT_COMPOUND); RETURN: if (decl) { parser->sema_callbacks.on_decl(parser->sema_callbacks.context, decl->base.type, decl); } return decl; }