diff --git a/grammar.js b/grammar.js index 9724e2e..ffbaf0f 100644 --- a/grammar.js +++ b/grammar.js @@ -50,6 +50,10 @@ const ASSIGNMENT_OPERATORS = [ 'xor_eq', ]; +const commaSep = C.commaSep; +const commaSep1 = C.commaSep1; +const preprocIf = C.preprocIf; + module.exports = grammar(C, { name: 'cpp', @@ -133,8 +137,12 @@ module.exports = grammar(C, { alias($.operator_cast_definition, $.function_definition), alias($.operator_cast_declaration, $.declaration), ), + _block_item: ($, original) => choice( - ...original.members.filter((member) => member.content?.name != '_old_style_function_definition'), + ...original.members.filter((member) => + member.content?.name != '_old_style_function_definition' && + !member.name.startsWith('preproc_if'), + ), $.namespace_definition, $.concept_definition, $.namespace_alias_definition, @@ -144,11 +152,18 @@ module.exports = grammar(C, { $.consteval_block_declaration, $.template_declaration, $.template_instantiation, + $.export_declaration, + $.import_declaration, + alias($.preproc_if_in_block, $.preproc_if), + alias($.preproc_ifdef_in_block, $.preproc_ifdef), alias($.constructor_or_destructor_definition, $.function_definition), alias($.operator_cast_definition, $.function_definition), alias($.operator_cast_declaration, $.declaration), ), + ...preprocIf('', $ => $._top_level_item), + ...preprocIf('_in_block', $ => $._block_item), + // Types placeholder_type_specifier: $ => prec(1, seq( @@ -371,13 +386,12 @@ module.exports = grammar(C, { ';', ), - export_declaration: $ => seq( + export_declaration: $ => prec(1, seq( 'export', - choice($._block_item, seq('{', repeat($._block_item), '}')), - ), + choice($._block_item, $.declaration_list), + )), import_declaration: $ => seq( - optional('export'), 'import', choice( field('name', $.module_name), @@ -1587,25 +1601,3 @@ module.exports = grammar(C, { _namespace_identifier: $ => alias($.identifier, $.namespace_identifier), }, }); - -/** - * Creates a rule to optionally match one or more of the rules separated by a comma - * - * @param {Rule} rule - * - * @returns {ChoiceRule} - */ -function commaSep(rule) { - return optional(commaSep1(rule)); -} - -/** - * Creates a rule to match one or more of the rules separated by a comma - * - * @param {Rule} rule - * - * @returns {SeqRule} - */ -function commaSep1(rule) { - return seq(rule, repeat(seq(',', rule))); -} diff --git a/test/corpus/modules.txt b/test/corpus/modules.txt index e2e723c..7ac3ae4 100644 --- a/test/corpus/modules.txt +++ b/test/corpus/modules.txt @@ -73,9 +73,10 @@ export import mod; -------------------------------------------------------------------------------- (translation_unit - (import_declaration - name: (module_name - (identifier)))) + (export_declaration + (import_declaration + name: (module_name + (identifier))))) ================================================================================ import Declaration partition with export @@ -85,10 +86,11 @@ export import :mod; -------------------------------------------------------------------------------- (translation_unit - (import_declaration - partition: (module_partition - (module_name - (identifier))))) + (export_declaration + (import_declaration + partition: (module_partition + (module_name + (identifier)))))) ================================================================================ import Declaration headerunit with export @@ -98,8 +100,9 @@ export import ; -------------------------------------------------------------------------------- (translation_unit - (import_declaration - header: (system_lib_string))) + (export_declaration + (import_declaration + header: (system_lib_string)))) ================================================================================ global module fragment @@ -171,22 +174,23 @@ char const* french() { return "Salut!"; } (string_literal (string_content))))) (export_declaration - (function_definition - type: (primitive_type) - declarator: (function_declarator - declarator: (identifier) - parameters: (parameter_list)) - body: (compound_statement - (return_statement - (number_literal)))) - (function_definition - type: (primitive_type) - declarator: (function_declarator - declarator: (identifier) - parameters: (parameter_list)) - body: (compound_statement - (return_statement - (number_literal))))) + (declaration_list + (function_definition + type: (primitive_type) + declarator: (function_declarator + declarator: (identifier) + parameters: (parameter_list)) + body: (compound_statement + (return_statement + (number_literal)))) + (function_definition + type: (primitive_type) + declarator: (function_declarator + declarator: (identifier) + parameters: (parameter_list)) + body: (compound_statement + (return_statement + (number_literal)))))) (export_declaration (namespace_definition name: (namespace_identifier) @@ -213,3 +217,51 @@ char const* french() { return "Salut!"; } (return_statement (string_literal (string_content))))))))) + +================================================================================ +Modules in preprocessor sections +================================================================================ + +#ifdef USE_MODULES +module; +#include +export module foo; +#endif + +#if USE_MODULES +import std; +#else +import ; +#endif + +export { +#ifdef USE_MODULE +class Foo; +#endif +} + +-------- + +(translation_unit + (preproc_ifdef + (identifier) + (global_module_fragment_declaration) + (preproc_include + (system_lib_string)) + (module_declaration + (module_name + (identifier)))) + (preproc_if + (identifier) + (import_declaration + (module_name + (identifier))) + (preproc_else + (import_declaration + (system_lib_string)))) + (export_declaration + (declaration_list + (preproc_ifdef + (identifier) + (class_specifier + (type_identifier))))))