diff --git a/.github/workflows/grammar-validator.yaml b/.github/workflows/grammar-validator.yaml new file mode 100644 index 000000000..f76c5603f --- /dev/null +++ b/.github/workflows/grammar-validator.yaml @@ -0,0 +1,29 @@ +name: ANTLR Grammar validator + +# Triggers the workflow on push or pull request events +on: [push, pull_request, workflow_dispatch] + +jobs: + grammar-validator: + runs-on: ubuntu-18.04 + env: + DOTNET_NOLOGO: true + + steps: + - name: Check out our repo + uses: actions/checkout@v2 + + - name: Setup .NET 5.0 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 5.0.x + + - name: Set up JDK 15 + uses: actions/setup-java@v1 + with: + java-version: 15.0 + + - name: run validate + run: | + cd tools + ./validate-grammar.sh diff --git a/standard/grammar.md b/standard/grammar.md index 41868ff1c..1ade61301 100644 --- a/standard/grammar.md +++ b/standard/grammar.md @@ -10,6 +10,7 @@ This annex contains the grammar productions found in the specification, includin ```ANTLR +// Source: §7.3.1 General input : input_section? ; @@ -29,6 +30,7 @@ input_element | token ; +// Source: §7.3.2 Line terminators new_line : '' | '' @@ -38,6 +40,7 @@ new_line | '' ; +// Source: §7.3.3 Comments comment : single_line_comment | delimited_comment @@ -76,6 +79,7 @@ not_slash_or_asterisk : '' ; +// Source: §7.3.4 White space whitespace : '' | '' @@ -83,6 +87,7 @@ whitespace | '
' ; +// Source: §7.4.1 General token : identifier | keyword @@ -93,11 +98,13 @@ token | operator_or_punctuator ; +// Source: §7.4.2 Unicode character escape sequences unicode_escape_sequence : '\\u' hex_digit hex_digit hex_digit hex_digit | '\\U' hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit ; +// Source: §7.4.3 Identifiers identifier : available_identifier | '@' identifier_or_keyword @@ -154,6 +161,7 @@ formatting_character | '' ; +// Source: §7.4.4 Keywords keyword : 'abstract' | 'as' | 'base' | 'bool' | 'break' | 'byte' | 'case' | 'catch' | 'char' | 'checked' @@ -173,6 +181,7 @@ keyword | 'volatile' | 'while' ; +// Source: §7.4.4 Keywords contextual_keyword : 'add' 'alias' 'ascending' 'async' 'await' | 'by' 'descending' 'dynamic' 'equals' 'from' @@ -181,6 +190,7 @@ contextual_keyword | 'set' 'value' 'var' 'where' 'yield' ; +// Source: §7.4.5.1 General literal : boolean_literal | integer_literal @@ -190,11 +200,13 @@ literal | null_literal ; +// Source: §7.4.5.2 Boolean literals boolean_literal : 'true' | 'false' ; +// Source: §7.4.5.3 Integer literals integer_literal : decimal_integer_literal | hexadecimal_integer_literal @@ -221,6 +233,7 @@ hex_digit : '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f'; +// Source: §7.4.5.4 Real literals real_literal : decimal_digit+ '.' decimal_digit+ exponent_part? real_type_suffix? | '.' decimal_digit+ exponent_part? real_type_suffix? @@ -241,6 +254,7 @@ real_type_suffix : 'F' | 'f' | 'D' | 'd' | 'M' | 'm' ; +// Source: §7.4.5.5 Character literals character_literal : '\'' character '\'' ; @@ -264,6 +278,7 @@ hexadecimal_escape_sequence : '\\x' hex_digit hex_digit? hex_digit? hex_digit? ; +// Source: §7.4.5.6 String literals string_literal : regular_string_literal | verbatim_string_literal @@ -301,10 +316,12 @@ quote_escape_sequence : '""' ; +// Source: §7.4.5.7 The null literal null_literal : 'null' ; +// Source: §7.4.6 Operators and punctuators operator_or_punctuator : '{' | '}' | '[' | ']' | '(' | ')' | '.' | ',' | ':' | ';' | '+' | '-' | '*' | '/' | '%' | '&' | '|' | '^' | '!' | '~' @@ -321,6 +338,7 @@ right_shift_assignment : '>' '>=' ; +// Source: §7.5.1 General pp_directive : pp_declaration | pp_conditional @@ -330,10 +348,12 @@ pp_directive | pp_pragma ; +// Source: §7.5.2 Conditional compilation symbols conditional_symbol : '' ; +// Source: §7.5.3 Pre-processing expressions pp_expression : whitespace? pp_or_expression whitespace? ; @@ -366,6 +386,7 @@ pp_primary_expression | '(' whitespace? pp_expression whitespace? ')' ; +// Source: §7.5.4 Definition directives pp_declaration : whitespace? '#' whitespace? 'define' whitespace conditional_symbol pp_new_line | whitespace? '#' whitespace? 'undef' whitespace conditional_symbol pp_new_line @@ -375,6 +396,7 @@ pp_new_line : whitespace? single_line_comment? new_line ; +// Source: §7.5.5 Conditional compilation directives pp_conditional : pp_if_section pp_elif_section* pp_else_section? pp_endif ; @@ -413,6 +435,7 @@ not_number_sign : '' ; +// Source: §7.5.6 Diagnostic directives pp_diagnostic : whitespace? '#' whitespace? 'error' pp_message | whitespace? '#' whitespace? 'warning' pp_message @@ -423,6 +446,7 @@ pp_message | whitespace input_character* new_line ; +// Source: §7.5.7 Region directives pp_region : pp_start_region conditional_section? pp_end_region ; @@ -435,6 +459,7 @@ pp_end_region : whitespace? '#' whitespace? 'endregion' pp_message ; +// Source: §7.5.8 Line directives pp_line : whitespace? '#' whitespace? 'line' whitespace line_indicator pp_new_line ; @@ -454,6 +479,7 @@ compilation_unit_name_character : '' ; +// Source: §7.5.9 Pragma directives pp_pragma : whitespace? '#' whitespace? 'pragma' pp_pragma_text ; @@ -468,6 +494,7 @@ pp_pragma_text ```ANTLR +// Source: §8.8.1 General namespace_name : namespace_or_type_name ; @@ -482,12 +509,14 @@ namespace_or_type_name | qualified_alias_member ; +// Source: §9.1 General type : reference_type | value_type | type_parameter ; +// Source: §9.2.1 General reference_type : class_type | interface_type @@ -527,6 +556,7 @@ delegate_type : type_name ; +// Source: §9.3.1 General value_type : struct_type | enum_type @@ -578,6 +608,7 @@ enum_type : type_name ; +// Source: §9.4.2 Type arguments type_argument_list : '<' type_arguments '>' ; @@ -590,14 +621,17 @@ type_argument : type ; +// Source: §9.5 Type parameters type_parameter : identifier ; +// Source: §10.5 Variable references variable_reference : expression ; +// Source: §12.6.2.1 General argument_list : argument (',' argument)* ; @@ -616,6 +650,7 @@ argument_value | 'out' variable_reference ; +// Source: §12.7.1 General primary_expression : primary_no_array_creation_expression | array_creation_expression @@ -643,14 +678,17 @@ primary_no_array_creation_expression | anonymous_method_expression ; +// Source: §12.7.3.1 General simple_name : identifier type_argument_list? ; +// Source: §12.7.4 Parenthesized expressions parenthesized_expression : '(' expression ')' ; +// Source: §12.7.5.1 General member_access : primary_expression '.' identifier type_argument_list? | predefined_type '.' identifier type_argument_list? @@ -662,23 +700,28 @@ predefined_type | 'object' | 'sbyte' | 'short' | 'string' | 'uint' | 'ulong' | 'ushort' ; +// Source: §12.7.6.1 General invocation_expression : primary_expression '(' argument_list? ')' ; +// Source: §12.7.7.1 General element_access : primary_no_array_creation_expression '[' argument_list ']' ; +// Source: §12.7.8 This access this_access : 'this' ; +// Source: §12.7.9 Base access base_access : 'base' '.' identifier type_argument_list? | 'base' '[' argument_list ']' ; +// Source: §12.7.10 Postfix increment and decrement operators post_increment_expression : primary_expression '++' ; @@ -687,6 +730,7 @@ post_decrement_expression : primary_expression '--' ; +// Source: §12.7.11.2 Object creation expressions object_creation_expression : 'new' type '(' argument_list? ')' object_or_collection_initializer? | 'new' type object_or_collection_initializer @@ -697,6 +741,7 @@ object_or_collection_initializer | collection_initializer ; +// Source: §12.7.11.3 Object initializers object_initializer : '{' member_initializer_list? '}' | '{' member_initializer_list ',' '}' @@ -715,6 +760,7 @@ initializer_value | object_or_collection_initializer ; +// Source: §12.7.11.4 Collection initializers collection_initializer : '{' element_initializer_list '}' | '{' element_initializer_list ',' '}' @@ -734,16 +780,19 @@ expression_list | expression_list ',' expression ; +// Source: §12.7.11.5 Array creation expressions array_creation_expression : 'new' non_array_type '[' expression_list ']' rank_specifier* array_initializer? | 'new' array_type array_initializer | 'new' rank_specifier array_initializer ; +// Source: §12.7.11.6 Delegate creation expressions delegate_creation_expression : 'new' delegate_type '(' expression ')' ; +// Source: §12.7.11.7 Anonymous object creation expressions anonymous_object_creation_expression : 'new' anonymous_object_initializer ; @@ -764,6 +813,7 @@ member_declarator | identifier '=' expression ; +// Source: §12.7.12 The typeof operator typeof_expression : 'typeof' '(' type ')' | 'typeof' '(' unbound_type_name ')' @@ -785,10 +835,12 @@ comma ; +// Source: §12.7.13 The sizeof operator sizeof_expression : 'sizeof' '(' unmanaged_type ')' ; +// Source: §12.7.14 The checked and unchecked operators checked_expression : 'checked' '(' expression ')' ; @@ -797,10 +849,12 @@ unchecked_expression : 'unchecked' '(' expression ')' ; +// Source: §12.7.15 Default value expressions default_value_expression : 'default' '(' type ')' ; +// Source: §12.8.1 General unary_expression : primary_expression | '+' unary_expression @@ -813,6 +867,7 @@ unary_expression | await_expression ; +// Source: §12.8.6 Prefix increment and decrement operators pre_increment_expression : '++' unary_expression ; @@ -821,14 +876,17 @@ pre_decrement_expression : '--' unary_expression ; +// Source: §12.8.7 Cast expressions cast_expression : '(' type ')' unary_expression ; +// Source: §12.8.8.1 General await_expression : 'await' unary_expression ; +// Source: §12.9.1 General multiplicative_expression : unary_expression | multiplicative_expression '*' unary_expression @@ -842,12 +900,14 @@ additive_expression | additive_expression '-' multiplicative_expression ; +// Source: §12.10 Shift operators shift_expression : additive_expression | shift_expression '<<' additive_expression | shift_expression right_shift additive_expression ; +// Source: §12.11.1 General relational_expression : shift_expression | relational_expression '<' shift_expression @@ -864,6 +924,7 @@ equality_expression | equality_expression '!=' relational_expression ; +// Source: §12.12.1 General and_expression : equality_expression | and_expression '&' equality_expression @@ -879,6 +940,7 @@ inclusive_or_expression | inclusive_or_expression '|' exclusive_or_expression ; +// Source: §12.13.1 General conditional_and_expression : inclusive_or_expression | conditional_and_expression '&&' inclusive_or_expression @@ -889,16 +951,19 @@ conditional_or_expression | conditional_or_expression '||' conditional_and_expression ; +// Source: §12.14 The null coalescing operator null_coalescing_expression : conditional_or_expression | conditional_or_expression '??' null_coalescing_expression ; +// Source: §12.15 Conditional operator conditional_expression : null_coalescing_expression | null_coalescing_expression '?' expression ':' expression ; +// Source: §12.16.1 General lambda_expression : 'async'? anonymous_function_signature '=>' anonymous_function_body ; @@ -947,6 +1012,7 @@ anonymous_function_body | block ; +// Source: §12.17.1 General query_expression : from_clause query_body ; @@ -1023,6 +1089,7 @@ query_continuation : 'into' identifier query_body ; +// Source: §12.18.1 General assignment : unary_expression assignment_operator expression ; @@ -1032,6 +1099,7 @@ assignment_operator | right_shift_assignment ; +// Source: §12.19 Expression expression : non_assignment_expression | assignment @@ -1043,14 +1111,17 @@ non_assignment_expression | query_expression ; +// Source: §12.20 Constant expressions constant_expression : expression ; +// Source: §12.21 Boolean expressions boolean_expression : expression ; +// Source: §13.1 General statement : labeled_statement | declaration_statement @@ -1072,27 +1143,33 @@ embedded_statement | yield_statement ; +// Source: §13.3.1 General block : '{' statement_list? '}' ; +// Source: §13.3.2 Statement lists statement_list : statement+ ; +// Source: §13.4 The empty statement empty_statement : ';' ; +// Source: §13.5 Labeled statements labeled_statement : identifier ':' statement ; +// Source: §13.6.1 General declaration_statement : local_variable_declaration ';' | local_constant_declaration ';' ; +// Source: §13.6.2 Local variable declarations local_variable_declaration : local_variable_type local_variable_declarators ; @@ -1117,6 +1194,7 @@ local_variable_initializer | array_initializer ; +// Source: §13.6.3 Local constant declarations local_constant_declaration : 'const' type constant_declarators ; @@ -1129,6 +1207,7 @@ constant_declarator : identifier '=' constant_expression ; +// Source: §13.7 Expression statements expression_statement : statement_expression ';' ; @@ -1144,16 +1223,19 @@ statement_expression | await_expression ; +// Source: §13.8.1 General selection_statement : if_statement | switch_statement ; +// Source: §13.8.2 The if statement if_statement : 'if' '(' boolean_expression ')' embedded_statement | 'if' '(' boolean_expression ')' embedded_statement 'else' embedded_statement ; +// Source: §13.8.3 The switch statement switch_statement : 'switch' '(' expression ')' switch_block ; @@ -1171,6 +1253,7 @@ switch_label | 'default' ':' ; +// Source: §13.9.1 General iteration_statement : while_statement | do_statement @@ -1178,14 +1261,17 @@ iteration_statement | foreach_statement ; +// Source: §13.9.2 The while statement while_statement : 'while' '(' boolean_expression ')' embedded_statement ; +// Source: §13.9.3 The do statement do_statement : 'do' embedded_statement 'while' '(' boolean_expression ')' ';' ; +// Source: §13.9.4 The for statement for_statement : 'for' '(' for_initializer? ';' for_condition? ';' for_iterator? ')' embedded_statement ; @@ -1207,10 +1293,12 @@ statement_expression_list : statement_expression (',' statement_expression)* ; +// Source: §13.9.5 The foreach statement foreach_statement : 'foreach' '(' local_variable_type identifier 'in' expression ')' embedded_statement ; +// Source: §13.10.1 General jump_statement : break_statement | continue_statement @@ -1219,55 +1307,49 @@ jump_statement | throw_statement ; +// Source: §13.10.2 The break statement break_statement : 'break' ';' ; +// Source: §13.10.3 The continue statement continue_statement : 'continue' ';' ; +// Source: §13.10.4 The goto statement goto_statement : 'goto' identifier ';' | 'goto' 'case' constant_expression ';' | 'goto' 'default' ';' ; +// Source: §13.10.5 The return statement return_statement : 'return' expression? ';' ; +// Source: §13.10.6 The throw statement throw_statement : 'throw' expression? ';' ; +// Source: §13.11 The try statement try_statement - : 'try' block catch_clauses - | 'try' block catch_clauses? finally_clause + : 'try' block catch_clause+ + | 'try' block finally_clause + | 'try' block catch_clause+ finally_clause ; catch_clauses - : specific_catch_clauses - | specific_catch_clauses? general_catch_clause + : 'catch' exception_specifier? block ; -specific_catch_clauses - : specific_catch_clause - | specific_catch_clauses specific_catch_clause - ; - -specific_catch_clause - : 'catch' '(' type identifier? ')' block - ; - -general_catch_clause - : 'catch' block - ; - -finally_clause - : 'finally' block +exception_specifier + : '(' type identifier? ')' ; +// Source: §13.12 The checked and unchecked statements checked_statement : 'checked' block ; @@ -1276,10 +1358,12 @@ unchecked_statement : 'unchecked' block ; +// Source: §13.13 The lock statement lock_statement : 'lock' '(' expression ')' embedded_statement ; +// Source: §13.14 The using statement using_statement : 'using' '(' resource_acquisition ')' embedded_statement ; @@ -1289,15 +1373,18 @@ resource_acquisition | expression ; +// Source: §13.15 The yield statement yield_statement : 'yield' 'return' expression ';' | 'yield' 'break' ';' ; +// Source: §14.2 Compilation units compilation_unit : extern_alias_directive* using_directive* global_attributes? namespace_member_declaration* ; +// Source: §14.3 Namespace declarations namespace_declaration : 'namespace' qualified_identifier namespace_body ';'? ; @@ -1310,28 +1397,34 @@ namespace_body : '{' extern_alias_directive* using_directive* namespace_member_declaration* '}' ; +// Source: §14.4 Extern alias directives extern_alias_directive : 'extern' 'alias' identifier ';' ; +// Source: §14.5.1 General using_directive : using_alias-directive | using_namespace-directive ; +// Source: §14.5.2 Using alias directives using_alias_directive : 'using' identifier '=' namespace_or_type_name ';' ; +// Source: §14.5.3 Using namespace directives using_namespace_directive : 'using' namespace_name ';' ; +// Source: §14.6 Namespace member declarations namespace_member_declaration : namespace_declaration | type_declaration ; +// Source: §14.7 Type declarations type_declaration : class_declaration | struct_declaration @@ -1340,15 +1433,18 @@ type_declaration | delegate_declaration ; +// Source: §14.8.1 General qualified_alias_member : identifier '::' identifier type_argument_list? ; +// Source: §15.2.1 General class_declaration : attributes? class_modifier* 'partial'? 'class' identifier type_parameter_list? class_base? type_parameter_constraints_clause* class_body ';'? ; +// Source: §15.2.2.1 General class_modifier : 'new' | 'public' @@ -1360,6 +1456,7 @@ class_modifier | 'static' ; +// Source: §15.2.3 Type parameters type_parameter_list : '<' type_parameters '>' ; @@ -1369,6 +1466,7 @@ type_parameters | type_parameters ',' attributes? type_parameter ; +// Source: §15.2.4.1 General class_base : ':' class_type | ':' interface_type_list @@ -1379,6 +1477,7 @@ interface_type_list : interface_type (',' interface_type)* ; +// Source: §15.2.5 Type parameter constraints type_parameter_constraints_clauses : type_parameter_constraints_clause | type_parameter_constraints_clauses type_parameter_constraints_clause @@ -1415,10 +1514,12 @@ constructor_constraint : 'new' '(' ')' ; +// Source: §15.2.6 Class body class_body : '{' class_member_declaration* '}' ; +// Source: §15.3.1 General class_member_declaration : constant_declaration | field_declaration @@ -1433,6 +1534,7 @@ class_member_declaration | type_declaration ; +// Source: §15.4 Constants constant_declaration : attributes? constant_modifier* 'const' type constant_declarators ';' ; @@ -1445,6 +1547,7 @@ constant_modifier | 'private' ; +// Source: §15.5.1 General field_declaration : attributes? field_modifier* type variable_declarators ';' ; @@ -1468,6 +1571,7 @@ variable_declarator : identifier ('=' variable_initializer)? ; +// Source: §15.6.1 General method_declaration : method_header method_body ; @@ -1505,6 +1609,7 @@ method_body : block ; +// Source: §15.6.2.1 General formal_parameter_list : fixed_parameters | fixed_parameters ',' parameter_array @@ -1537,6 +1642,7 @@ parameter_array : attributes? 'params' array_type identifier ; +// Source: §15.7.1 General property_declaration : attributes? property_modifiers? type member_name '{' accessor_declarations '}' ; @@ -1560,6 +1666,7 @@ property_modifier | 'extern' ; +// Source: §15.7.3 Accessors accessor_declarations : get_accessor_declaration set_accessor_declaration? | set_accessor_declaration get_accessor_declaration? @@ -1586,6 +1693,7 @@ accessor_body | ';' ; +// Source: §15.8.1 General event_declaration : attributes? event_modifier* 'event' type variable_declarators ';' | attributes? event_modifier* 'event' type member_name '{' event_accessor_declarations '}' @@ -1618,6 +1726,7 @@ remove_accessor_declaration : attributes? 'remove' block ; +// Source: §15.9 Indexers indexer_declaration : attributes? indexer_modifiers? indexer_declarator '{' accessor_declarations '}' ; @@ -1645,6 +1754,7 @@ indexer_declarator | type interface_type '.' 'this' '[' formal_parameter_list ']' ; +// Source: §15.10.1 General operator_declaration : attributes? operator_modifier+ operator_declarator operator_body ; @@ -1688,6 +1798,7 @@ operator_body | ';' ; +// Source: §15.11.1 General constructor_declaration : attributes? constructor_modifier* constructor_declarator constructor_body ; @@ -1714,6 +1825,7 @@ constructor_body | ';' ; +// Source: §15.12 Static constructors static_constructor_declaration : attributes? static_constructor_modifiers identifier '(' ')' static_constructor_body ; @@ -1728,6 +1840,7 @@ static_constructor_body | ';' ; +// Source: §15.13 Finalizers finalizer_declaration : attributes? 'extern'? '~' identifier '(' ')' finalizer_body ; @@ -1737,11 +1850,13 @@ finalizer_body | ';' ; +// Source: §16.2.1 General struct_declaration : attributes? struct_modifier* 'partial'? 'struct' identifier type_parameter_list? struct_interfaces? type_parameter_constraints_clause* struct_body ';'? ; +// Source: §16.2.2 Struct modifiers struct_modifier : 'new' | 'public' @@ -1750,14 +1865,17 @@ struct_modifier | 'private' ; +// Source: §16.2.4 Struct interfaces struct_interfaces : ':' interface_type_list ; +// Source: §16.2.5 Struct body struct_body : '{' struct_member_declaration* '}' ; +// Source: §16.3 Struct members struct_member_declaration : constant_declaration | field_declaration @@ -1771,6 +1889,7 @@ struct_member_declaration | type_declaration ; +// Source: §17.7 Array initializers array_initializer : '{' variable_initializer_list? '}' | '{' variable_initializer_list ',' '}' @@ -1785,10 +1904,12 @@ variable_initializer | array_initializer ; +// Source: §18.2.1 General interface_declaration : attributes? interface_modifier* 'partial'? 'interface' identifier variant_type_parameter_list? interface_base? type_parameter_constraints_clause* interface_body ';'? ; +// Source: §18.2.2 Interface modifiers interface_modifier : 'new' | 'public' @@ -1797,28 +1918,34 @@ interface_modifier | 'private' ; +// Source: §18.2.3.1 General variant_type_parameter_list : '<' variant_type_parameters '>' ; +// Source: §18.2.3.1 General variant_type_parameters : attributes? variance_annotation? type_parameter | variant_type_parameters ',' attributes? variance_annotation? type_parameter ; +// Source: §18.2.3.1 General variance_annotation : 'in' | 'out' ; +// Source: §18.2.4 Base interfaces interface_base : ':' interface_type_list ; +// Source: §18.3 Interface body interface_body : '{' interface_member_declaration* '}' ; +// Source: §18.4.1 General interface_member_declaration : interface_method_declaration | interface_property_declaration @@ -1826,14 +1953,17 @@ interface_member_declaration | interface_indexer_declaration ; +// Source: §18.4.2 Interface methods interface_method_declaration : attributes? 'new'? return_type identifier type_parameter_list? '(' formal_parameter_list? ')' type_parameter_constraints_clause* ';' ; +// Source: §18.4.3 Interface properties interface_property_declaration : attributes? 'new'? type identifier '{' interface_accessors '}' ; +// Source: §18.4.3 Interface properties interface_accessors : attributes? 'get' ';' | attributes? 'set' ';' @@ -1841,14 +1971,17 @@ interface_accessors | attributes? 'set' ';' attributes? 'get' ';' ; +// Source: §18.4.4 Interface events interface_event_declaration : attributes? 'new'? 'event' type identifier ';' ; +// Source: §18.4.5 Interface indexers interface_indexer_declaration: attributes? 'new'? type 'this' '[' formal_parameter_list ']' '{' interface_accessors '}' ; +// Source: §19.2 Enum declarations enum_declaration : attributes? enum_modifier* 'enum' identifier enum_base? enum_body ';'? ; @@ -1862,6 +1995,7 @@ enum_body | '{' enum_member_declarations ',' '}' ; +// Source: §19.3 Enum modifiers enum_modifier : 'new' | 'public' @@ -1870,14 +2004,17 @@ enum_modifier | 'private' ; +// Source: §19.4 Enum members enum_member_declarations : enum_member_declaration (',' enum_member_declaration)* ; +// Source: §19.4 Enum members enum_member_declaration : attributes? identifier ('=' constant_expression)? ; +// Source: §20.2 Delegate declarations delegate_declaration : attributes? delegate_modifier* 'delegate' return_type identifier variant_type_parameter_list? '(' formal_parameter_list? ')' type_parameter_constraints_clause* ';' ; @@ -1890,6 +2027,7 @@ delegate_modifier | 'private' ; +// Source: §22.3 Attribute specification global_attributes : global_attribute_section+ ; @@ -1968,6 +2106,7 @@ attribute_argument_expression ```ANTLR +// Source: §23.2 Unsafe contexts class_modifier : ... | 'unsafe' @@ -2046,6 +2185,7 @@ unsafe_statement : 'unsafe' block ; +// Source: §23.3 Pointer types type : ... | pointer_type @@ -2056,6 +2196,7 @@ non_array_type | pointer_type ; +// Source: §23.3 Pointer types pointer_type : unmanaged_type '*' | 'void' '*' @@ -2065,6 +2206,7 @@ unmanaged_type : type ; +// Source: §23.6.1 General primary_no_array_creation_expression : ... | pointer_member_access @@ -2077,22 +2219,27 @@ unary_expression | addressof_expression ; +// Source: §23.6.2 Pointer indirection pointer_indirection_expression : '*' unary_expression ; +// Source: §23.6.3 Pointer member access pointer_member_access : primary_expression '->' identifier type_argument_list? ; +// Source: §23.6.4 Pointer element access pointer_element_access : primary_no_array_creation_expression '[' expression ']' ; +// Source: §23.6.5 The address-of operator addressof_expression : '&' unary_expression ; +// Source: §23.7 The fixed statement fixed_statement : 'fixed' '(' pointer_type fixed_pointer_declarators ')' embedded_statement ; @@ -2110,6 +2257,7 @@ fixed_pointer_initializer | expression ; +// Source: §23.8.2 Fixed-size buffer declarations struct_member_declaration : ... | fixed_size_buffer_declaration @@ -2136,6 +2284,7 @@ fixed_size_buffer_declarator : identifier '[' constant_expression ']' ; +// Source: §23.9 Stack allocation local_variable_initializer : ... | stackalloc_initializer diff --git a/tools/GetGrammar/GetGrammar.bat b/tools/GetGrammar/GetGrammar.bat deleted file mode 100644 index b678fbdbb..000000000 --- a/tools/GetGrammar/GetGrammar.bat +++ /dev/null @@ -1,33 +0,0 @@ -echo off -dotnet build -dotnet publish - -del ..\..\standard\grammar.md -echo Insert General/Lexical Headers -type grammar-general-lexical-insert.md >..\..\standard\grammar.md -echo Extract Lexical Grammar -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\lexical-structure.md >>..\..\standard\grammar.md -echo Insert Syntactic Header -type grammar-syntactic-insert.md >>..\..\standard\grammar.md -echo Extract Syntactic Grammar -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\basic-concepts.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\types.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\variables.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\conversions.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\expressions.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\statements.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\namespaces.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\classes.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\structs.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\arrays.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\interfaces.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\enums.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\delegates.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\exceptions.md >>..\..\standard\grammar.md -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\attributes.md >>..\..\standard\grammar.md -echo Insert Unsafe Header -type grammar-unsafe-extensions-insert.md >>..\..\standard\grammar.md -echo Extract Unsafe Grammar -bin\Debug\netcoreapp3.1\publish\GetGrammar <..\..\standard\unsafe-code.md >>..\..\standard\grammar.md -echo Insert EOF Stuff -type grammar-eof-insert.md >>..\..\standard\grammar.md diff --git a/tools/GetGrammar/GetGrammar.csproj b/tools/GetGrammar/GetGrammar.csproj index c73e0d169..d75be9161 100644 --- a/tools/GetGrammar/GetGrammar.csproj +++ b/tools/GetGrammar/GetGrammar.csproj @@ -2,7 +2,8 @@ Exe - netcoreapp3.1 + net5.0 + enable diff --git a/tools/GetGrammar/Program.cs b/tools/GetGrammar/Program.cs index cd5e77447..d99ecd534 100644 --- a/tools/GetGrammar/Program.cs +++ b/tools/GetGrammar/Program.cs @@ -24,53 +24,61 @@ using System; using System.IO; +using System.Threading.Tasks; namespace ExtractGrammar { class Program { - public static void Main() - { - string inputLine; + public static async Task Main(string[] args) + { + if (args.Length != 1) + { + Console.WriteLine("Usage: GetGrammar "); + Environment.Exit(1); + } + using var inputFile = new StreamReader(args[0]); + string section = ""; - while ((inputLine = Console.ReadLine()) != null) - { - if (inputLine.Length < 8) // Is it long enough to contain an opening fence? + while (await inputFile.ReadLineAsync() is string inputLine) + { + if (inputLine.StartsWith("#")) { - continue; + section = inputLine.Trim('#', ' '); + continue; } - string leader = inputLine.Substring(0, 8); // grab what might be an opening fence -// Console.WriteLine(">" + leader + "<"); - if (leader != "```ANTLR" && leader != "```antlr") - { - continue; + if (!inputLine.StartsWith("```ANTLR", StringComparison.InvariantCultureIgnoreCase)) + { + continue; } -// Console.WriteLine("------ Start of a production"); - Console.WriteLine(); // write out blank line before each new production + // Console.WriteLine("------ Start of a production"); + Console.WriteLine(); // write out blank line before each new production + Console.WriteLine($"// Source: §{section}"); - while (true) - { - inputLine = Console.ReadLine(); - if (inputLine == null) - { - Console.WriteLine("Unexpected EOF; no closing grammar fence"); - Environment.Exit(1); - } - if (inputLine.Length < 3) // Is it long enough to contain a closing fence? - { - Console.WriteLine(inputLine); - } - else if (inputLine.Substring(0, 3) == "```") // If line starts with ``` - { -// Console.WriteLine("------ End of a production"); - break; - } - else + // This loop might be a candidate for a bit of refactoring. + while (true) + { + string? nextLine = await inputFile.ReadLineAsync(); + if (nextLine == null) + { + Console.WriteLine("Unexpected EOF; no closing grammar fence"); + Environment.Exit(1); + } + if (nextLine.Length < 3) // Is it long enough to contain a closing fence? { - Console.WriteLine(inputLine); - } - } - } - } + Console.WriteLine(nextLine); + } + else if (nextLine.Substring(0, 3) == "```") // If line starts with ``` + { + // Console.WriteLine("------ End of a production"); + break; + } + else + { + Console.WriteLine(nextLine); + } + } + } + } } } diff --git a/tools/update-grammar-annex.sh b/tools/update-grammar-annex.sh new file mode 100755 index 000000000..e17b56ed9 --- /dev/null +++ b/tools/update-grammar-annex.sh @@ -0,0 +1,50 @@ +#!/bin/bash +set -eu -o pipefail + +declare -r GRAMMAR_PROJECT=GetGrammar +declare -r SPEC_DIRECTORY=../standard +declare -r OUTPUT_FILE=../standard/grammar.md + +# Note that lexical structure and unsafe code are not in the array +# There are headers inserted before them. +declare -a SPEC_FILES=( + "basic-concepts.md" + "types.md" + "variables.md" + "conversions.md" + "expressions.md" + "statements.md" + "namespaces.md" + "classes.md" + "structs.md" + "arrays.md" + "interfaces.md" + "enums.md" + "delegates.md" + "exceptions.md" + "attributes.md" + ) + +dotnet build $GRAMMAR_PROJECT -c Release +dotnet publish $GRAMMAR_PROJECT -c Release -o $GRAMMAR_PROJECT/publish + +rm $OUTPUT_FILE + +echo Insert General/Lexical Headers +cat $GRAMMAR_PROJECT/grammar-general-lexical-insert.md >$OUTPUT_FILE +dotnet $GRAMMAR_PROJECT/publish/$GRAMMAR_PROJECT.dll $SPEC_DIRECTORY/lexical-structure.md >>$OUTPUT_FILE + +echo Insert Syntactic Header +cat $GRAMMAR_PROJECT/grammar-syntactic-insert.md >>$OUTPUT_FILE + +for file in "${SPEC_FILES[@]}" +do + echo "$file" + dotnet $GRAMMAR_PROJECT/publish/$GRAMMAR_PROJECT.dll $SPEC_DIRECTORY/$file >>$OUTPUT_FILE +done + +echo Insert Unsafe Header +cat $GRAMMAR_PROJECT/grammar-unsafe-extensions-insert.md >>$OUTPUT_FILE +dotnet $GRAMMAR_PROJECT/publish/$GRAMMAR_PROJECT.dll $SPEC_DIRECTORY/unsafe-code.md >>$OUTPUT_FILE +echo Insert EOF Stuff +cat $GRAMMAR_PROJECT/grammar-eof-insert.md >>$OUTPUT_FILE diff --git a/tools/validate-grammar.sh b/tools/validate-grammar.sh new file mode 100755 index 000000000..d462f541e --- /dev/null +++ b/tools/validate-grammar.sh @@ -0,0 +1,43 @@ +#!/bin/bash +set -eu -o pipefail + +declare -r GRAMMAR_PROJECT=GetGrammar +declare -r SPEC_DIRECTORY=../standard +declare -r OUTPUT_FILE=csharp-grammar.g4 + +declare -a SPEC_FILES=( + "lexical-structure.md" + "basic-concepts.md" + "types.md" + "variables.md" + "conversions.md" + "expressions.md" + "statements.md" + "namespaces.md" + "classes.md" + "structs.md" + "arrays.md" + "interfaces.md" + "enums.md" + "delegates.md" + "exceptions.md" + "attributes.md" + "unsafe-code.md" + ) + +dotnet build $GRAMMAR_PROJECT -c Release +dotnet publish $GRAMMAR_PROJECT -c Release -o $GRAMMAR_PROJECT/publish + +rm $OUTPUT_FILE + +echo "grammar CSGrammar;" > $OUTPUT_FILE + +for file in "${SPEC_FILES[@]}" +do + echo "$file" + dotnet $GRAMMAR_PROJECT/publish/$GRAMMAR_PROJECT.dll $SPEC_DIRECTORY/$file >>$OUTPUT_FILE +done + +# Now, validate it: +curl -H "Accept: application/zip" https://www.antlr.org/download/antlr-4.9.1-complete.jar -o antlr-4.9.1-complete.jar +java -jar antlr-4.9.1-complete.jar -Dlanguage=CSharp $OUTPUT_FILE \ No newline at end of file