Browse Source

feat: additional modules support

- allow module related statements to appear in preprocessor blocks
- export declarations can now appear anywhere other declarations can
master
rktdm 3 months ago
committed by jdrouhard
parent
commit
a0d1092dd7
2 changed files with 96 additions and 52 deletions
  1. +19
    -27
      grammar.js
  2. +77
    -25
      test/corpus/modules.txt

+ 19
- 27
grammar.js View File

@ -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)));
}

+ 77
- 25
test/corpus/modules.txt View File

@ -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 <vector>
export module foo;
#endif
#if USE_MODULES
import std;
#else
import <vector>;
#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))))))

Loading…
Cancel
Save