diff --git a/components/prism-cpp.js b/components/prism-cpp.js index cf14d49b64..55a2fae60e 100644 --- a/components/prism-cpp.js +++ b/components/prism-cpp.js @@ -1,6 +1,7 @@ (function (Prism) { - var keyword = /\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/; + var keyword = /\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/; + var modName = /\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g, function () { return keyword.source; }) Prism.languages.cpp = Prism.languages.extend('c', { 'class-name': [ @@ -31,6 +32,26 @@ }); Prism.languages.insertBefore('cpp', 'string', { + 'module': { + // https://en.cppreference.com/w/cpp/language/modules + pattern: RegExp( + /(\b(?:module|import)\s+)/.source + + '(?:' + + // header-name + /"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source + + '|' + + // module name or partition or both + /(?:\s*:\s*)?|:\s*/.source.replace(//g, function () { return modName; }) + + ')' + ), + lookbehind: true, + greedy: true, + inside: { + 'string': /^[<"][\s\S]+/, + 'operator': /:/, + 'punctuation': /\./ + } + }, 'raw-string': { pattern: /R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/, alias: 'string', diff --git a/components/prism-cpp.min.js b/components/prism-cpp.min.js index 7ab1f0d4ea..16f98cc5cc 100644 --- a/components/prism-cpp.min.js +++ b/components/prism-cpp.min.js @@ -1 +1 @@ -!function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/;e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!)\\w+".replace(//g,function(){return t.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:true|false)\b/}),e.languages.insertBefore("cpp","string",{"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","operator",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism); \ No newline at end of file +!function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n="\\b(?!)\\w+(?:\\s*\\.\\s*\\w+)*\\b".replace(//g,function(){return t.source});e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!)\\w+".replace(//g,function(){return t.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:true|false)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp('(\\b(?:module|import)\\s+)(?:"(?:\\\\(?:\r\n|[^])|[^"\\\\\r\n])*"|<[^<>\r\n]*>|'+"(?:\\s*:\\s*)?|:\\s*".replace(//g,function(){return n})+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","operator",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism); \ No newline at end of file diff --git a/tests/languages/cpp/keyword_feature.test b/tests/languages/cpp/keyword_feature.test index ac72b6a31d..69c90b55df 100644 --- a/tests/languages/cpp/keyword_feature.test +++ b/tests/languages/cpp/keyword_feature.test @@ -33,20 +33,24 @@ enum; explicit export extern +final float for friend goto if +import; inline int long +module; mutable namespace new noexcept nullptr operator +override private protected public @@ -125,20 +129,24 @@ uint64_t ["keyword", "explicit"], ["keyword", "export"], ["keyword", "extern"], + ["keyword", "final"], ["keyword", "float"], ["keyword", "for"], ["keyword", "friend"], ["keyword", "goto"], ["keyword", "if"], + ["keyword", "import"], ["punctuation", ";"], ["keyword", "inline"], ["keyword", "int"], ["keyword", "long"], + ["keyword", "module"], ["punctuation", ";"], ["keyword", "mutable"], ["keyword", "namespace"], ["keyword", "new"], ["keyword", "noexcept"], ["keyword", "nullptr"], ["keyword", "operator"], + ["keyword", "override"], ["keyword", "private"], ["keyword", "protected"], ["keyword", "public"], diff --git a/tests/languages/cpp/module_feature.test b/tests/languages/cpp/module_feature.test new file mode 100644 index 0000000000..b6675c3d4e --- /dev/null +++ b/tests/languages/cpp/module_feature.test @@ -0,0 +1,116 @@ +export module speech; + +export const char* get_phrase_en() { + return "Hello, world!"; +} + +export module speech; + +export import :english; +export import :spanish; + +export module speech:english; + +import speech; +import :PrivWidget; + +import ; +import ; +import "foo.h"; +import ; + +module : private; + +---------------------------------------------------- + +[ + ["keyword", "export"], + ["keyword", "module"], + ["module", ["speech"]], + ["punctuation", ";"], + + ["keyword", "export"], + ["keyword", "const"], + ["keyword", "char"], + ["operator", "*"], + ["function", "get_phrase_en"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "{"], + + ["keyword", "return"], + ["string", "\"Hello, world!\""], + ["punctuation", ";"], + + ["punctuation", "}"], + + ["keyword", "export"], + ["keyword", "module"], + ["module", ["speech"]], + ["punctuation", ";"], + + ["keyword", "export"], + ["keyword", "import"], + ["module", [ + ["operator", ":"], + "english" + ]], + ["punctuation", ";"], + + ["keyword", "export"], + ["keyword", "import"], + ["module", [ + ["operator", ":"], + "spanish" + ]], + ["punctuation", ";"], + + ["keyword", "export"], + ["keyword", "module"], + ["module", [ + "speech", + ["operator", ":"], + "english" + ]], + ["punctuation", ";"], + + ["keyword", "import"], + ["module", ["speech"]], + ["punctuation", ";"], + + ["keyword", "import"], + ["module", [ + ["operator", ":"], + "PrivWidget" + ]], + ["punctuation", ";"], + + ["keyword", "import"], + ["module", [ + ["string", ""] + ]], + ["punctuation", ";"], + + ["keyword", "import"], + ["module", [ + ["string", ""] + ]], + ["punctuation", ";"], + + ["keyword", "import"], + ["module", [ + ["string", "\"foo.h\""] + ]], + ["punctuation", ";"], + + ["keyword", "import"], + ["module", [ + ["string", ""] + ]], + ["punctuation", ";"], + + ["keyword", "module"], + ["operator", ":"], + ["keyword", "private"], + ["punctuation", ";"] +] \ No newline at end of file