#include /* 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 */ 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 */ if (!scc_parse_is_declaration_start(parser, 0)) { return null; } scc_ast_type_t *type = scc_parse_type(parser); if (type == null) { LOG_ERROR("Failed to parse type"); return null; } const scc_lexer_tok_t *tok = scc_lexer_stream_current(parser->lex_stream); if (!scc_lexer_tok_match(tok, SCC_TOK_IDENT)) { LOG_ERROR("Expected identifier, got %s", scc_get_tok_name(tok->type)); return null; } scc_lexer_stream_consume(parser->lex_stream); 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_parse_consume_if(parser->lex_stream, SCC_TOK_L_PAREN)) { // TODO if (scc_parse_consume_if(parser->lex_stream, SCC_TOK_SEMICOLON)) { decl->base.type = SCC_AST_DECL_VAR; decl->var.type = type; decl->var.name = tok->value.cstr.data; decl->var.init = null; return decl; } else if (scc_parse_consume_if(parser->lex_stream, SCC_TOK_ASSIGN)) { decl->base.type = SCC_AST_DECL_VAR; decl->var.type = type; decl->var.name = tok->value.cstr.data; decl->var.init = scc_parse_expression(parser); return decl; } return null; } // function decl decl->base.type = SCC_AST_DECL_FUNC; decl->func.name = tok->value.cstr.data; 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 decl->func.type->function.is_variadic = false; // TODO param type scc_parse_consume_if(parser->lex_stream, SCC_TOK_VOID); if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_R_PAREN)) { return null; } if (!scc_parse_is(parser->lex_stream, SCC_TOK_L_BRACE)) { 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 decl; }