From: Matthias Kruk Date: Sun, 19 Jul 2020 15:20:45 +0000 (+0900) Subject: grammar: Add production rules for grammatical structures on pages 295, 296 of "The... X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=fa21643395d82a2b711210a88daa5adc0a659c2b;p=ccc grammar: Add production rules for grammatical structures on pages 295, 296 of "The C Programming Language, 2nd Edition" --- diff --git a/src/grammar.c b/src/grammar.c index 45ab477..e0eb852 100644 --- a/src/grammar.c +++ b/src/grammar.c @@ -1,10 +1,14 @@ #include #include #include +#include #include "grammar.h" #include "token.h" +#include "parser.h" +#include "lex.h" +#include "assoc_array.h" -struct rule _translation_unit_production_A[] = { +static struct rule _translation_unit_production_A[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_EXTERNAL_DECLARATION, @@ -14,7 +18,7 @@ struct rule _translation_unit_production_A[] = { } }; -struct rule _translation_unit_production_B[] = { +static struct rule _translation_unit_production_B[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_TRANSLATION_UNIT, @@ -28,13 +32,13 @@ struct rule _translation_unit_production_B[] = { } }; -struct rule **_translation_unit_productions = { +static struct rule *_translation_unit_productions[] = { _translation_unit_production_A, _translation_unit_production_B, NULL }; -struct rule _external_declaration_production_A[] = { +static struct rule _external_declaration_production_A[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_FUNCTION_DEFINITION, @@ -44,7 +48,7 @@ struct rule _external_declaration_production_A[] = { } }; -struct rule _external_declaration_production_B[] = { +static struct rule _external_declaration_production_B[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_DECLARATION, @@ -54,13 +58,13 @@ struct rule _external_declaration_production_B[] = { } }; -struct rule **_external_declaration_productions = { +static struct rule *_external_declaration_productions[] = { _external_declaration_production_A, _external_declaration_production_B, NULL }; -struct rule _function_definition_production_A[] = { +static struct rule _function_definition_production_A[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_DECLARATION_SPECIFIERS, @@ -84,12 +88,12 @@ struct rule _function_definition_production_A[] = { } }; -struct rule **_function_definition_productions = { +static struct rule *_function_definition_productions[] = { _function_definition_production_A, NULL }; -struct rule _declaration_production_A[] = { +static struct rule _declaration_production_A[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_DECLARATION_SPECIFIERS, @@ -104,12 +108,12 @@ struct rule _declaration_production_A[] = { } }; -struct rule **_declaration_productions = { - _declaration_productions_A, +static struct rule *_declaration_productions[] = { + _declaration_production_A, NULL }; -struct rule _declaration_list_production_A[] = { +static struct rule _declaration_list_production_A[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_DECLARATION, @@ -119,7 +123,7 @@ struct rule _declaration_list_production_A[] = { } }; -struct rule _declaration_list_production_B[] = { +static struct rule _declaration_list_production_B[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_DECLARATION_LIST, @@ -133,13 +137,13 @@ struct rule _declaration_list_production_B[] = { } }; -struct rule **_declaration_list_productions = { +static struct rule *_declaration_list_productions[] = { _declaration_list_production_A, _declaration_list_production_B, NULL }; -struct rule _declaration_specifiers_production_A[] = { +static struct rule _declaration_specifiers_production_A[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_STORAGE_CLASS_SPECIFIER, @@ -154,7 +158,7 @@ struct rule _declaration_specifiers_production_A[] = { } }; -struct rule _declaration_specifiers_production_B[] = { +static struct rule _declaration_specifiers_production_B[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_TYPE_SPECIFIER, @@ -169,7 +173,7 @@ struct rule _declaration_specifiers_production_B[] = { } }; -struct rule _declaration_specifiers_production_C[] = { +static struct rule _declaration_specifiers_production_C[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_TYPE_QUALIFIER, @@ -184,64 +188,64 @@ struct rule _declaration_specifiers_production_C[] = { } }; -struct rule **_declaration_specifiers_productions = { +static struct rule *_declaration_specifiers_productions[] = { _declaration_specifiers_production_A, _declaration_specifiers_production_B, _declaration_specifiers_production_C, NULL }; -struct rule _storage_class_specifier_production_A[] = { +static struct rule _storage_class_specifier_production_A[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_AUTO, - .name = "terminal" + .name = "token" }, { 0 } }; -struct rule _storage_class_specifier_production_B[] = { +static struct rule _storage_class_specifier_production_B[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_REGISTER, - .name = "terminal" + .name = "token" }, { 0 } }; -struct rule _storage_class_specifier_production_C[] = { +static struct rule _storage_class_specifier_production_C[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_STATIC, - .name = "terminal" + .name = "token" }, { 0 } }; -struct rule _storage_class_specifier_production_D[] = { +static struct rule _storage_class_specifier_production_D[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_EXTERN, - .name = "terminal" + .name = "token" }, { 0 } }; -struct rule _storage_class_specifier_production_E[] = { +static struct rule _storage_class_specifier_production_E[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_TYPEDEF, - .name = "terminal" + .name = "token" }, { 0 } }; -struct rule **_storage_class_specifier_productions = { +static struct rule *_storage_class_specifier_productions[] = { _storage_class_specifier_production_A, _storage_class_specifier_production_B, _storage_class_specifier_production_C, @@ -250,97 +254,97 @@ struct rule **_storage_class_specifier_productions = { NULL }; -struct rule _type_specifier_production_A[] = { +static struct rule _type_specifier_production_A[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_VOID, - .name = "type" + .name = "token" }, { 0 } }; -struct rule _type_specifier_production_B[] = { +static struct rule _type_specifier_production_B[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_CHAR, - .name = "type" + .name = "token" }, { 0 } }; -struct rule _type_specifier_production_C[] = { +static struct rule _type_specifier_production_C[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_SHORT, - .name = "type" + .name = "token" }, { 0 } }; -struct rule _type_specifier_production_D[] = { +static struct rule _type_specifier_production_D[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_INT, - .name = "type" + .name = "token" }, { 0 } }; -struct rule _type_specifier_production_E[] = { +static struct rule _type_specifier_production_E[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_LONG, - .name = "type" + .name = "token" }, { 0 } }; -struct rule _type_specifier_production_F[] = { +static struct rule _type_specifier_production_F[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_FLOAT, - .name = "type" + .name = "token" }, { 0 } }; -struct rule _type_specifier_production_G[] = { +static struct rule _type_specifier_production_G[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_DOUBLE, - .name = "type" + .name = "token" }, { 0 } }; -struct rule _type_specifier_production_H[] = { +static struct rule _type_specifier_production_H[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_SIGNED, - .name = "type" + .name = "token" }, { 0 } }; -struct rule _type_specifier_production_I[] = { +static struct rule _type_specifier_production_I[] = { { .type = RULE_TERMINAL, .terminal = TOKEN_UNSIGNED, - .name = "type" + .name = "token" }, { 0 } }; -struct rule _type_specifier_production_J[] = { +static struct rule _type_specifier_production_J[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_STRUCT_OR_UNION_SPECIFIER, @@ -350,7 +354,7 @@ struct rule _type_specifier_production_J[] = { } }; -struct rule _type_specifier_production_K[] = { +static struct rule _type_specifier_production_K[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_ENUM_SPECIFIER, @@ -360,7 +364,7 @@ struct rule _type_specifier_production_K[] = { } }; -struct rule _type_specifier_production_L[] = { +static struct rule _type_specifier_production_L[] = { { .type = RULE_NONTERMINAL, .nonterminal = SYNTAX_NODE_TYPEDEF_NAME, @@ -370,7 +374,7 @@ struct rule _type_specifier_production_L[] = { } }; -struct rule **_type_specifier_productions = { +static struct rule *_type_specifier_productions[] = { _type_specifier_production_A, _type_specifier_production_B, _type_specifier_production_C, @@ -386,7 +390,641 @@ struct rule **_type_specifier_productions = { NULL }; -struct syntax_node_descriptor _node_descriptors[] = { +static struct rule _type_qualifier_production_A[] = { + { + .type = RULE_TERMINAL, + .terminal = TOKEN_CONST, + .name = "token" + }, { + 0 + } +}; + +static struct rule _type_qualifier_production_B[] = { + { + .type = RULE_TERMINAL, + .terminal = TOKEN_VOLATILE, + .name = "token" + }, { + 0 + } +}; + +static struct rule *_type_qualifier_productions[] = { + _type_qualifier_production_A, + _type_qualifier_production_B, + NULL +}; + +static struct rule _struct_or_union_specifier_production_A[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_STRUCT_OR_UNION, + .name = "struct-or-union" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_IDENTIFIER, + .flags = RULE_FLAG_OPTIONAL, + .name = "identifier" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_LBRACE, + .name = "lbrace" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_STRUCT_DECLARATION_LIST, + .name = "struct-declaration-list" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_RBRACE, + .name = "rbrace" + }, { + 0 + } +}; + +static struct rule _struct_or_union_specifier_production_B[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_STRUCT_OR_UNION, + .name = "struct-or-union" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_IDENTIFIER, + .name = "identifier" + }, { + 0 + } +}; + +static struct rule *_struct_or_union_specifier_productions[] = { + _struct_or_union_specifier_production_A, + _struct_or_union_specifier_production_B, + NULL +}; + +static struct rule _struct_or_union_production_A[] = { + { + .type = RULE_TERMINAL, + .terminal = TOKEN_STRUCT, + .name = "token" + }, { + 0 + } +}; + +static struct rule _struct_or_union_production_B[] = { + { + .type = RULE_TERMINAL, + .terminal = TOKEN_UNION, + .name = "token" + }, { + 0 + } +}; + +static struct rule *_struct_or_union_productions[] = { + _struct_or_union_production_A, + _struct_or_union_production_B, + NULL +}; + +static struct rule _struct_declaration_list_production_A[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_STRUCT_DECLARATION, + .name = "struct-declaration" + }, { + 0 + } +}; + +static struct rule _struct_declaration_list_production_B[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_STRUCT_DECLARATION_LIST, + .name = "struct-declaration-list" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_STRUCT_DECLARATION, + .name = "struct-declaration" + }, { + 0 + } +}; + +static struct rule *_struct_declaration_list_productions[] = { + _struct_declaration_list_production_A, + _struct_declaration_list_production_B, + NULL +}; + +static struct rule _init_declarator_list_production_A[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_INIT_DECLARATOR, + .name = "init-declarator" + }, { + 0 + } +}; + +static struct rule _init_declarator_list_production_B[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_INIT_DECLARATOR_LIST, + .name = "init-declarator-list" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_COMMA, + .name = "comma" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_INIT_DECLARATOR, + .name = "init-declarator" + }, { + 0 + } +}; + +static struct rule *_init_declarator_list_productions[] = { + _init_declarator_list_production_A, + _init_declarator_list_production_B, + NULL +}; + +static struct rule _init_declarator_production_A[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_DECLARATOR, + .name = "declarator" + }, { + 0 + } +}; + +static struct rule _init_declarator_production_B[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_DECLARATOR, + .name = "declarator" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_EQ, + .name = "eq" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_INITIALIZER, + .name = "initializer" + }, { + 0 + } +}; + +static struct rule *_init_declarator_productions[] = { + _init_declarator_production_A, + _init_declarator_production_B, + NULL +}; + +static struct rule _struct_declaration_production_A[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_SPECIFIER_QUALIFIER_LIST, + .name = "specifier-qualifier-list" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_STRUCT_DECLARATOR_LIST, + .name = "struct-declarator-list" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_SEMICOLON, + .name = "semicolon" + }, { + 0 + } +}; + +static struct rule *_struct_declaration_productions[] = { + _struct_declaration_production_A, + NULL +}; + +static struct rule _specifier_qualifier_list_production_A[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_TYPE_SPECIFIER, + .name = "type-specifier" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_SPECIFIER_QUALIFIER_LIST, + .flags = RULE_FLAG_OPTIONAL, + .name = "specifier-qualifier-list" + }, { + 0 + } +}; + +static struct rule _specifier_qualifier_list_production_B[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_TYPE_QUALIFIER, + .name = "type-qualifier" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_SPECIFIER_QUALIFIER_LIST, + .flags = RULE_FLAG_OPTIONAL, + .name = "specifier-qualifier-list" + }, { + 0 + } +}; + +static struct rule *_specifier_qualifier_list_productions[] = { + _specifier_qualifier_list_production_A, + _specifier_qualifier_list_production_B, + NULL +}; + +static struct rule _struct_declarator_list_production_A[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_STRUCT_DECLARATOR, + .name = "struct-declarator" + }, { + 0 + } +}; + +static struct rule _struct_declarator_list_production_B[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_STRUCT_DECLARATOR_LIST, + .name = "struct-declarator-list" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_COMMA, + .name = "comma" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_STRUCT_DECLARATOR, + .name = "struct-declarator" + }, { + 0 + } +}; + +static struct rule *_struct_declarator_list_productions[] = { + _struct_declarator_list_production_A, + _struct_declarator_list_production_B, + NULL +}; + +static struct rule _struct_declarator_production_A[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_DECLARATOR, + .name = "declarator" + }, { + 0 + } +}; + +static struct rule _struct_declarator_production_B[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_DECLARATOR, + .flags = RULE_FLAG_OPTIONAL, + .name = "declarator" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_COLON, + .name = "colon" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_CONSTANT_EXPRESSION, + .name = "constant-expression" + }, { + 0 + } +}; + +static struct rule *_struct_declarator_productions[] = { + _struct_declarator_production_A, + _struct_declarator_production_B, + NULL +}; + +static struct rule _enum_specifier_production_A[] = { + { + .type = RULE_TERMINAL, + .terminal = TOKEN_ENUM, + .name = "token" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_IDENTIFIER, + .flags = RULE_FLAG_OPTIONAL, + .name = "identifier" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_LBRACE, + .name = "lbrace" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_ENUMERATOR_LIST, + .name = "enumerator-list" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_RBRACE, + .name = "rbrace" + }, { + 0 + } +}; + +static struct rule _enum_specifier_production_B[] = { + { + .type = RULE_TERMINAL, + .terminal = TOKEN_ENUM, + .name = "token" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_IDENTIFIER, + .name = "identifier" + }, { + 0 + } +}; + +static struct rule *_enum_specifier_productions[] = { + _enum_specifier_production_A, + _enum_specifier_production_B, + NULL +}; + +static struct rule _enumerator_list_production_A[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_IDENTIFIER, + .name = "identifier" + }, { + 0 + } +}; + +static struct rule _enumerator_list_production_B[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_ENUMERATOR_LIST, + .name = "enumerator-list" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_COMMA, + .name = "comma" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_ENUMERATOR, + .name = "enumerator" + }, { + 0 + } +}; + +static struct rule *_enumerator_list_productions[] = { + _enumerator_list_production_A, + _enumerator_list_production_B, + NULL +}; + +static struct rule _enumerator_production_A[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_IDENTIFIER, + .name = "identifier" + }, { + 0 + } +}; + +static struct rule _enumerator_production_B[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_IDENTIFIER, + .name = "identifier" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_EQ, + .name = "eq" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_CONSTANT_EXPRESSION + }, { + 0 + } +}; + +static struct rule *_enumerator_productions[] = { + _enumerator_production_A, + _enumerator_production_B, + NULL +}; + +static struct rule _declarator_production_A[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_POINTER, + .flags = RULE_FLAG_OPTIONAL, + .name = "pointer" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_DIRECT_DECLARATOR, + .name = "direct-declarator" + }, { + 0 + } +}; + +static struct rule *_declarator_productions[] = { + _declarator_production_A, + NULL +}; + +static struct rule _direct_declarator_production_A[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_IDENTIFIER, + .name = "identifier" + }, { + 0 + } +}; + +static struct rule _direct_declarator_production_B[] = { + { + .type = RULE_TERMINAL, + .terminal = TOKEN_LPAREN, + .name = "lparen" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_DECLARATOR, + .name = "declarator" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_RPAREN, + .name = "rparen" + }, { + 0 + } +}; + +static struct rule _direct_declarator_production_C[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_DIRECT_DECLARATOR, + .name = "direct-declarator" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_LBRACKET, + .name = "lbracket" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_CONSTANT_EXPRESSION, + .flags = RULE_FLAG_OPTIONAL, + .name = "constant-expression" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_RBRACKET, + .name = "rbracket" + }, { + 0 + } +}; + +static struct rule _direct_declarator_production_D[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_DIRECT_DECLARATOR, + .name = "direct-declarator" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_LPAREN, + .name = "lparen" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_PARAMETER_TYPE_LIST, + .name = "parameter-type-list" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_RPAREN, + .name = "rparen" + }, { + 0 + } +}; + +static struct rule _direct_declarator_production_E[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_DIRECT_DECLARATOR, + .name = "direct-declarator" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_LPAREN, + .name = "lparen" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_IDENTIFIER_LIST, + .flags = RULE_FLAG_OPTIONAL, + .name = "identifier-list" + }, { + .type = RULE_TERMINAL, + .terminal = TOKEN_RPAREN, + .name = "rparen" + }, { + 0 + } +}; + +static struct rule *_direct_declarator_productions[] = { + _direct_declarator_production_A, + _direct_declarator_production_B, + _direct_declarator_production_C, + _direct_declarator_production_D, + _direct_declarator_production_E, + NULL +}; + +static struct rule _pointer_production_A[] = { + { + .type = RULE_TERMINAL, + .terminal = TOKEN_MUL, + .name = "token" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_TYPE_QUALIFIER_LIST, + .flags = RULE_FLAG_OPTIONAL, + .name = "type-qualifier-list" + }, { + 0 + } +}; + +static struct rule _pointer_production_B[] = { + { + .type = RULE_TERMINAL, + .terminal = TOKEN_MUL, + .name = "token" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_TYPE_QUALIFIER_LIST, + .flags = RULE_FLAG_OPTIONAL, + .name = "type-qualifier-list" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_POINTER, + .name = "pointer" + }, { + 0 + } +}; + +static struct rule *_pointer_productions[] = { + _pointer_production_A, + _pointer_production_B, + NULL +}; + +static struct rule _type_qualifier_list_production_A[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_TYPE_QUALIFIER, + .name = "type-qualifier" + }, { + 0 + } +}; + +static struct rule _type_qualifier_list_production_B[] = { + { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_TYPE_QUALIFIER_LIST, + .name = "type-qualifier-list" + }, { + .type = RULE_NONTERMINAL, + .nonterminal = SYNTAX_NODE_TYPE_QUALIFIER, + .name = "type-qualifier" + }, { + 0 + } +}; + +static struct rule *_type_qualifier_list_productions[] = { + _type_qualifier_list_production_A, + _type_qualifier_list_production_B, + NULL +}; + +static struct syntax_node_descriptor _node_descriptors[] = { /* order needs to be in sync with syntax_node_type_t */ { .type = SYNTAX_NODE_INVALID, @@ -394,311 +1032,318 @@ struct syntax_node_descriptor _node_descriptors[] = { .parse = NULL }, { .type = SYNTAX_NODE_TRANSLATION_UNIT, - .productions = _translation_unit_productions, - .parse = translation_unit_parse + .productions = _translation_unit_productions }, { .type = SYNTAX_NODE_EXTERNAL_DECLARATION, - .productions = _external_declaration_productions, - .parse = external_declaration_parse + .productions = _external_declaration_productions }, { .type = SYNTAX_NODE_FUNCTION_DEFINITION, - .productions = _function_definition_productions, - .parse = function_definition_parse + .productions = _function_definition_productions }, { .type = SYNTAX_NODE_DECLARATION, - .productions = _declaration_productions, - .parse = declaration_parse + .productions = _declaration_productions }, { .type = SYNTAX_NODE_DECLARATION_LIST, - .productions = _declaration_list_productions, - .parse = declaration_list_parse + .productions = _declaration_list_productions }, { .type = SYNTAX_NODE_DECLARATION_SPECIFIERS, - .productions = _declaration_specifiers_productions, - .parse = declaration_specifiers_parse + .productions = _declaration_specifiers_productions }, { .type = SYNTAX_NODE_STORAGE_CLASS_SPECIFIER, - .productions = _storage_class_specifier_productions, - .parse = storage_class_specifier_parse + .productions = _storage_class_specifier_productions }, { .type = SYNTAX_NODE_TYPE_SPECIFIER, - .productions = _type_specifier_productions, - .parse = type_specifier_parse + .productions = _type_specifier_productions }, { .type = SYNTAX_NODE_TYPE_QUALIFIER, - .productions = _type_qualifier_productions, - .parse = type_qualifier_parse + .productions = _type_qualifier_productions }, { .type = SYNTAX_NODE_STRUCT_OR_UNION_SPECIFIER, - .productions = _struct_or_union_specifier_productions, - .parse = struct_or_union_specifier_parse + .productions = _struct_or_union_specifier_productions }, { .type = SYNTAX_NODE_STRUCT_OR_UNION, - .productions = _struct_or_union_productions, - .parse = struct_or_union_parse + .productions = _struct_or_union_productions }, { .type = SYNTAX_NODE_STRUCT_DECLARATION_LIST, - .productions = _struct_declaration_list_productions, - .parse = struct_declaration_list_parse + .productions = _struct_declaration_list_productions }, { .type = SYNTAX_NODE_INIT_DECLARATOR_LIST, - .productions = _init_declarator_list_productions, - .parse = init_declarator_list_parse + .productions = _init_declarator_list_productions }, { .type = SYNTAX_NODE_INIT_DECLARATOR, - .productions = _init_declarator_productions, - .parse = init_declarator_parse + .productions = _init_declarator_productions }, { .type = SYNTAX_NODE_STRUCT_DECLARATION, - .productions = _struct_declaration_productions, - .parse = struct_declaration_parse + .productions = _struct_declaration_productions }, { .type = SYNTAX_NODE_SPECIFIER_QUALIFIER_LIST, - .productions = _specifier_qualifier_list_productions, - .parse = specifier_qualifier_list_parse + .productions = _specifier_qualifier_list_productions }, { .type = SYNTAX_NODE_STRUCT_DECLARATOR_LIST, - .productions = _struct_declarator_list_productions, - .parse = struct_declarator_list_parse + .productions = _struct_declarator_list_productions }, { .type = SYNTAX_NODE_STRUCT_DECLARATOR, - .productions = _struct_declarator_productions, - .parse = struct_declarator_parse + .productions = _struct_declarator_productions }, { .type = SYNTAX_NODE_ENUM_SPECIFIER, - .productions = _enum_specifier_productions, - .parse = enum_specifier_parse + .productions = _enum_specifier_productions }, { .type = SYNTAX_NODE_ENUMERATOR_LIST, - .productions = _enumerator_list_productions, - .parse = enumerator_list_parse + .productions = _enumerator_list_productions }, { .type = SYNTAX_NODE_ENUMERATOR, - .productions = _enumerator_productions, - .parse = enumerator_parse + .productions = _enumerator_productions }, { .type = SYNTAX_NODE_DECLARATOR, - .productions = _declarator_productions, - .parse = declarator_parse + .productions = _declarator_productions }, { .type = SYNTAX_NODE_DIRECT_DECLARATOR, - .productions = _direct_declarator_productions, - .parse = direct_declarator_parse + .productions = _direct_declarator_productions }, { .type = SYNTAX_NODE_POINTER, - .productions = _pointer_productions, - .parse = pointer_parse + .productions = _pointer_productions }, { .type = SYNTAX_NODE_TYPE_QUALIFIER_LIST, - .productions = _type_qualifier_list_productions, - .parse = type_qualifier_list_parse + .productions = _type_qualifier_list_productions }, { .type = SYNTAX_NODE_PARAMETER_TYPE_LIST, - .productions = _parameter_type_list_productions, - .parse = parameter_type_list_parse + .productions = _parameter_type_list_productions }, { .type = SYNTAX_NODE_PARAMETER_LIST, - .productions = _parameter_list_productions, - .parse = parameter_list_parse + .productions = _parameter_list_productions }, { .type = SYNTAX_NODE_PARAMETER_DECLARATION, - .productions = _parameter_declaration_productions, - .parse = parameter_declaration_parse + .productions = _parameter_declaration_productions + }, { + .type = SYNTAX_NODE_IDENTIFIER, + .parse = identifier_parse }, { .type = SYNTAX_NODE_IDENTIFIER_LIST, - .productions = _identifier_list_productions, - .parse = identifier_list_parse + .productions = _identifier_list_productions }, { .type = SYNTAX_NODE_INITIALIZER, - .productions = _initializer_productions, - .parse = initializer_parse + .productions = _initializer_productions }, { .type = SYNTAX_NODE_INITIALIZER_LIST, - .productions = _initializer_list_productions, - .parse = initializer_list_parse + .productions = _initializer_list_productions }, { .type = SYNTAX_NODE_TYPE_NAME, - .productions = _type_name_productions, - .parse = type_name_parse + .productions = _type_name_productions }, { .type = SYNTAX_NODE_ABSTRACT_DECLARATOR, - .productions = _abstract_declarator_productions, - .parse = abstract_declarator_parse + .productions = _abstract_declarator_productions }, { .type = SYNTAX_NODE_DIRECT_ABSTRACT_DECLARATOR, - .productions = _direct_abstract_declarator_productions, - .parse = direct_abstract_declarator_parse + .productions = _direct_abstract_declarator_productions }, { .type = SYNTAX_NODE_TYPEDEF_NAME, - .productions = _typedef_name_productions, - .parse = typedef_name_parse + .productions = _typedef_name_productions }, { .type = SYNTAX_NODE_STATEMENT, - .productions = _statement_productions, - .parse = statement_parse + .productions = _statement_productions }, { .type = SYNTAX_NODE_LABELED_STATEMENT, - .productions = _labeled_statement_productions, - .parse = labeled_statement_parse + .productions = _labeled_statement_productions }, { .type = SYNTAX_NODE_EXPRESSION_STATEMENT, - .productions = _expression_statement_productions, - .parse = expression_statement_parse + .productions = _expression_statement_productions }, { .type = SYNTAX_NODE_COMPOUND_STATEMENT, - .productions = _compound_statement_productions, - .parse = compound_statement_parse + .productions = _compound_statement_productions }, { .type = SYNTAX_NODE_STATEMENT_LIST, - .productions = _statement_list_productions, - .parse = statement_list_parse + .productions = _statement_list_productions }, { .type = SYNTAX_NODE_SELECTION_STATEMENT, - .productions = _selection_statement_productions, - .parse = selection_statement_parse + .productions = _selection_statement_productions }, { .type = SYNTAX_NODE_IF_STATEMENT, - .productions = _if_statement_productions, - .parse = if_statement_parse + .productions = _if_statement_productions }, { .type = SYNTAX_NODE_IF_ELSE_STATEMENT, - .productions = _if_else_statement_productions, - .parse = if_else_statement_parse + .productions = _if_else_statement_productions }, { .type = SYNTAX_NODE_SWITCH_STATEMENT, - .productions = _switch_statement_productions, - .parse = switch_statement_parse + .productions = _switch_statement_productions }, { .type = SYNTAX_NODE_ITERATION_STATEMENT, - .productions = _iteration_statement_productions, - .parse = iteration_statement_parse + .productions = _iteration_statement_productions }, { .type = SYNTAX_NODE_WHILE_STATEMENT, - .productions = _while_statement_productions, - .parse = while_statement_parse + .productions = _while_statement_productions }, { .type = SYNTAX_NODE_DO_WHILE_STATEMENT, - .productions = _do_while_statement_productions, - .parse = do_while_statement_parse + .productions = _do_while_statement_productions }, { .type = SYNTAX_NODE_FOR_STATEMENT, - .productions = _for_statement_productions, - .parse = for_statement_parse + .productions = _for_statement_productions }, { .type = SYNTAX_NODE_JUMP_STATEMENT, - .productions = _jump_statement_productions, - .parse = jump_statement_parse + .productions = _jump_statement_productions }, { .type = SYNTAX_NODE_GOTO_STATEMENT, - .productions = _goto_statement_productions, - .parse = goto_statement_parse + .productions = _goto_statement_productions }, { .type = SYNTAX_NODE_CONTINUE_STATEMENT, - .productions = _continue_statement_productions, - .parse = continue_statement_parse + .productions = _continue_statement_productions }, { .type = SYNTAX_NODE_BREAK_STATEMENT, - .productions = _break_statement_productions, - .parse = break_statement_parse + .productions = _break_statement_productions }, { .type = SYNTAX_NODE_RETURN_STATEMENT, - .productions = _return_statement_productions, - .parse = return_statement_parse + .productions = _return_statement_productions }, { .type = SYNTAX_NODE_EXPRESSION, - .productions = _expression_productions, - .parse = expression_parse + .productions = _expression_productions }, { .type = SYNTAX_NODE_ASSIGNMENT_EXPRESSION, - .productions = _assignement_expression_productions, - .parse = assignement_expression_parse + .productions = _assignement_expression_productions }, { .type = SYNTAX_NODE_ASSIGNMENT_OPERATOR, - .productions = _assignment_operator_productions, - .parse = assignment_operator_parse + .productions = _assignment_operator_productions }, { .type = SYNTAX_NODE_CONDITIONAL_EXPRESSION, - .productions = _conditional_expression_productions, - .parse = conditional_expression_parse + .productions = _conditional_expression_productions }, { .type = SYNTAX_NODE_CONSTANT_EXPRESSION, - .productions = _constant_expression_productions, - .parse = constant_expression_parse + .productions = _constant_expression_productions }, { .type = SYNTAX_NODE_LOGICAL_OR_EXPRESSION, - .productions = _logical_or_expression_productions, - .parse = logical_or_expression_parse + .productions = _logical_or_expression_productions }, { .type = SYNTAX_NODE_LOGICAL_AND_EXPRESSION, - .productions = _logical_and_expression_productions, - .parse = logical_and_expression_parse + .productions = _logical_and_expression_productions }, { .type = SYNTAX_NODE_INCLUSIVE_OR_EXPRESSION, - .productions = _inclusive_or_expression_productions, - .parse = inclusive_or_expression_parse + .productions = _inclusive_or_expression_productions }, { .type = SYNTAX_NODE_EXCLUSIVE_OR_EXPRESSION, - .productions = _exclusive_or_expression_productions, - .parse = exclusive_or_expression_parse + .productions = _exclusive_or_expression_productions }, { .type = SYNTAX_NODE_AND_EXPRESSION, - .productions = _and_expression_productions, - .parse = and_expression_parse + .productions = _and_expression_productions }, { .type = SYNTAX_NODE_EQUALITY_EXPRESSION, - .productions = _equality_expression_productions, - .parse = equality_expression_parse + .productions = _equality_expression_productions }, { .type = SYNTAX_NODE_RELATIONAL_EXPRESSION, - .productions = _relational_expression_productions, - .parse = relational_expression_parse + .productions = _relational_expression_productions }, { .type = SYNTAX_NODE_SHIFT_EXPRESSION, - .productions = _shift_expression_productions, - .parse = shift_expression_parse + .productions = _shift_expression_productions }, { .type = SYNTAX_NODE_ADDITIVE_EXPRESSION, - .productions = _additive_expression_productions, - .parse = additive_expression_parse + .productions = _additive_expression_productions }, { .type = SYNTAX_NODE_MULTIPLICATIVE_EXRESSION, - .productions = _multiplicative_expression_productions, - .parse = multiplicative_expression_parse + .productions = _multiplicative_expression_productions }, { .type = SYNTAX_NODE_CAST_EXPRESSION, - .productions = _cast_expression_productions, - .parse = cast_expression_parse + .productions = _cast_expression_productions }, { .type = SYNTAX_NODE_UNARY_EXPRESSION, - .productions = _unary_expression_productions, - .parse = unary_expression_parse + .productions = _unary_expression_productions }, { .type = SYNTAX_NODE_UNARY_OPERATOR, - .productions = _unary_operator_productions, - .parse = unary_operator_parse + .productions = _unary_operator_productions }, { .type = SYNTAX_NODE_POSTFIX_EXPRESSION, - .productions = _postfix_expression_productions, - .parse = postfix_expression_parse + .productions = _postfix_expression_productions }, { .type = SYNTAX_NODE_PRIMARY_EXPRESSION, - .productions = _primary_expression_productions, - .parse = primary_expression_parse + .productions = _primary_expression_productions }, { .type = SYNTAX_NODE_ARGUMENT_EXPRESSION_LIST, - .productions = _argument_expression_list_productions, - .parse = argument_expression_list_parse + .productions = _argument_expression_list_productions }, { .type = SYNTAX_NODE_CONSTANT, - .productions = _constant_productions, - .parse = constant_parse + .productions = _constant_productions } }; -struct syntax_node* syntax_node_parse(syntax_node_type_t type) +struct syntax_node *syntax_node_parse_production(syntax_node_type_t type, int prod) +{ + struct syntax_node *node; + struct rule *rule; + int match; + int origin; + + node = syntax_node_new(); + + if(!node) { + return(NULL); + } + + origin = lex_getpos(); + + for(rule = _node_descriptors[type].productions[prod], match = 1; + rule && match; + rule++) { + int pos; + + pos = lex_getpos(); + + if(rule->type == RULE_TERMINAL) { + struct token *tok; + int pos; + + pos = lex_getpos(); + tok = lex_gettoken(); + + if(tok && tok->type == rule->terminal) { + syntax_node_set_property(node, rule->name, tok); + continue; + } + + match = 0; + } else { + struct syntax_node *nt; + + nt = syntax_node_parse(rule->nonterminal); + + if(nt || rule->flags & RULE_FLAG_OPTIONAL) { + /* will be NULL if optional and missing */ + syntax_node_set_child(node, rule->name, nt); + continue; + } + + match = 0; + } + } + + if(!match) { + lex_setpos(origin); + syntax_node_free(node); + node = NULL; + } + + return(node); +} + +struct syntax_node *syntax_node_parse_generic(syntax_node_type_t type) +{ + struct syntax_node *ret_val; + int prod; + + for(prod = 0; _node_descriptors[type].productions[prod]; prod++) { + ret_val = syntax_node_parse_production(type, prod); + + if(ret_val) { + break; + } + } + + return(ret_val); +} + +struct syntax_node *syntax_node_parse(syntax_node_type_t type) { if(type > 0 && type < SYNTAX_NODE_MAX) { - return(_node_descriptors[type].parse()); + if(_node_descriptors[type].parse) { + return(_node_descriptors[type].parse()); + } + + return(syntax_node_parse_generic(type)); } return(NULL); @@ -3300,3 +3945,53 @@ void jump_statement_debug(struct jump_statement *stmt) return; } + +static int _syntax_node_debug(struct syntax_node *node) +{ + return(-ENOSYS); +} + +struct syntax_node *syntax_node_new(void) +{ + struct syntax_node *node; + + node = malloc(sizeof(*node)); + + if(node) { + node->children = assoc_array_new(); + node->properties = assoc_array_new(); + + if(node->children && node->properties) { + node->debug = _syntax_node_debug; + } else { + if(node->children) { + assoc_array_free(node->children); + } + + if(node->properties) { + assoc_array_free(node->properties); + } + + free(node); + node = NULL; + } + } + + return(node); +} + +void syntax_node_free(struct syntax_node *node) +{ + if(node->children) { + /* assoc_array_foreach(node->children, syntax_node_free); */ + assoc_array_free(node->children); + } + + if(node->properties) { + assoc_array_free(node->properties); + } + + memset(node, 0, sizeof(*node)); + free(node); + return; +} diff --git a/src/grammar.h b/src/grammar.h index aa7fea9..272cedf 100644 --- a/src/grammar.h +++ b/src/grammar.h @@ -1,6 +1,7 @@ #ifndef GRAMMAR_H #define GRAMMAR_H +#include "assoc_array.h" #include "token.h" struct token; @@ -35,6 +36,7 @@ typedef enum { SYNTAX_NODE_PARAMETER_TYPE_LIST, SYNTAX_NODE_PARAMETER_LIST, SYNTAX_NODE_PARAMETER_DECLARATION, + SYNTAX_NODE_IDENTIFIER, SYNTAX_NODE_IDENTIFIER_LIST, SYNTAX_NODE_INITIALIZER, SYNTAX_NODE_INITIALIZER_LIST, @@ -94,6 +96,8 @@ struct syntax_node_descriptor { struct syntax_node { syntax_node_type_t type; + struct assoc_array *children; + struct assoc_array *properties; int (*debug)(struct syntax_node*); int (*free)(struct syntax_node*); @@ -1014,4 +1018,13 @@ void initializer_list_free(struct initializer_list*); void jump_statement_debug(struct jump_statement*); +struct syntax_node *syntax_node_new(void); +void syntax_node_free(struct syntax_node*); +int syntax_node_set_property(struct syntax_node*, const char*, void*); +int syntax_node_get_property(struct syntax_node*, const char*, void**); +int syntax_node_set_child(struct syntax_node*, const char*, struct syntax_node*); +int syntax_node_get_child(struct syntax_node*, const char*, struct syntax_node**); +syntax_node_type_t syntax_node_get_type(struct syntax_node*); +void syntax_node_set_type(struct syntax_node*, const syntax_node_type_t); + #endif /* GRAMMAR_H */ diff --git a/src/parser.h b/src/parser.h index 2a863a6..1f9f228 100644 --- a/src/parser.h +++ b/src/parser.h @@ -65,5 +65,4 @@ struct iteration_statement *parse_iteration_statement(void); struct jump_statement *parse_jump_statement(void); struct statement_list *parse_statement_list(void); - #endif /* PARSER_H */