diff --git a/components/prism-cpp.js b/components/prism-cpp.js index 55a2fae60e..b771da11ca 100644 --- a/components/prism-cpp.js +++ b/components/prism-cpp.js @@ -27,7 +27,7 @@ pattern: /(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i, greedy: true }, - 'operator': />>=?|<<=?|->|([-+&|:])\1|[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/, + 'operator': />>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/, 'boolean': /\b(?:true|false)\b/ }); @@ -59,6 +59,27 @@ } }); + Prism.languages.insertBefore('cpp', 'keyword', { + 'generic-function': { + pattern: /\b[a-z_]\w*\s*<(?:[^<>]|<(?:[^<>])*>)*>(?=\s*\()/i, + inside: { + 'function': /^\w+/, + 'generic': { + pattern: /<[\s\S]+/, + alias: 'class-name', + inside: Prism.languages.cpp + } + } + } + }); + + Prism.languages.insertBefore('cpp', 'operator', { + 'double-colon': { + pattern: /::/, + alias: 'punctuation' + } + }); + Prism.languages.insertBefore('cpp', 'class-name', { // the base clause is an optional list of parent classes // https://en.cppreference.com/w/cpp/language/class @@ -69,7 +90,8 @@ inside: Prism.languages.extend('cpp', {}) } }); - Prism.languages.insertBefore('inside', 'operator', { + + Prism.languages.insertBefore('inside', 'double-colon', { // All untokenized words that are not namespaces should be class names 'class-name': /\b[a-z_]\w*\b(?!\s*::)/i }, Prism.languages.cpp['base-clause']); diff --git a/components/prism-cpp.min.js b/components/prism-cpp.min.js index 16f98cc5cc..9c21ed3a9b 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|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 +!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:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\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","keyword",{"generic-function":{pattern:/\b[a-z_]\w*\s*<(?:[^<>]|<(?:[^<>])*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),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","double-colon",{"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/base-clause_feature.test b/tests/languages/cpp/base-clause_feature.test index 4d9247bbc4..260a7099e3 100644 --- a/tests/languages/cpp/base-clause_feature.test +++ b/tests/languages/cpp/base-clause_feature.test @@ -18,6 +18,7 @@ class service : private Transport // comment ["punctuation", "{"], ["punctuation", "}"], ["punctuation", ";"], + ["keyword", "struct"], ["class-name", "Derived"], ["operator", ":"], @@ -27,6 +28,7 @@ class service : private Transport // comment ["punctuation", "{"], ["punctuation", "}"], ["punctuation", ";"], + ["keyword", "struct"], ["class-name", "Derived"], ["operator", ":"], @@ -35,6 +37,7 @@ class service : private Transport // comment ["class-name", "Base"] ]], ["punctuation", ";"], + ["keyword", "class"], ["class-name", "X"], ["operator", ":"], @@ -46,6 +49,7 @@ class service : private Transport // comment ["punctuation", "{"], ["punctuation", "}"], ["punctuation", ";"], + ["keyword", "class"], ["class-name", "Y"], ["operator", ":"], @@ -57,18 +61,20 @@ class service : private Transport // comment ["punctuation", "{"], ["punctuation", "}"], ["punctuation", ";"], + ["keyword", "class"], ["class-name", "Y"], ["operator", ":"], ["base-clause", [ ["keyword", "virtual"], " baz", - ["operator", "::"], + ["double-colon", "::"], ["class-name", "B"] ]], ["punctuation", "{"], ["punctuation", "}"], ["punctuation", ";"], + ["keyword", "class"], ["class-name", "Z"], ["operator", ":"], @@ -77,11 +83,12 @@ class service : private Transport // comment ["class-name", "B"], ["operator", "<"], "foo", - ["operator", "::"], + ["double-colon", "::"], ["class-name", "T"], ["operator", ">"] ]], ["punctuation", ";"], + ["keyword", "struct"], ["class-name", "AA"], ["operator", ":"], @@ -91,14 +98,15 @@ class service : private Transport // comment ["class-name", "Y"], ["punctuation", ","], " foo", - ["operator", "::"], + ["double-colon", "::"], "bar", - ["operator", "::"], + ["double-colon", "::"], ["class-name", "Z"] ]], ["punctuation", "{"], ["punctuation", "}"], ["punctuation", ";"], + ["keyword", "class"], ["class-name", "service"], ["operator", ":"], @@ -107,6 +115,7 @@ class service : private Transport // comment ["class-name", "Transport"], ["comment", "// comment"] ]], + ["punctuation", "{"], ["punctuation", "}"], ["punctuation", ";"] diff --git a/tests/languages/cpp/class-name_feature.test b/tests/languages/cpp/class-name_feature.test index 3e5a42fc48..086f6af2af 100644 --- a/tests/languages/cpp/class-name_feature.test +++ b/tests/languages/cpp/class-name_feature.test @@ -4,6 +4,7 @@ concept Foo_bar struct foo enum bar enum class FooBar + template void Foo::bar() {} @@ -19,12 +20,16 @@ void Foo::bar() {} ["keyword", "struct"], ["class-name", "foo"], ["keyword", "enum"], ["class-name", "bar"], ["keyword", "enum"], ["keyword", "class"], ["class-name", "FooBar"], - ["keyword", "template"], ["operator", "<"], ["keyword", "typename"], ["class-name", "FooBar"], ["operator", ">"], + ["keyword", "template"], + ["operator", "<"], + ["keyword", "typename"], + ["class-name", "FooBar"], + ["operator", ">"], ["keyword", "void"], ["class-name", "Foo"], - ["operator", "::"], + ["double-colon", "::"], ["function", "bar"], ["punctuation", "("], ["punctuation", ")"], @@ -32,7 +37,7 @@ void Foo::bar() {} ["punctuation", "}"], ["class-name", "Foo"], - ["operator", "::"], + ["double-colon", "::"], ["operator", "~"], ["function", "Foo"], ["punctuation", "("], @@ -45,7 +50,7 @@ void Foo::bar() {} ["operator", "<"], ["keyword", "int"], ["operator", ">"], - ["operator", "::"], + ["double-colon", "::"], ["function", "bar"], ["punctuation", "("], ["punctuation", ")"], diff --git a/tests/languages/cpp/function_feature.test b/tests/languages/cpp/function_feature.test new file mode 100644 index 0000000000..2968199382 --- /dev/null +++ b/tests/languages/cpp/function_feature.test @@ -0,0 +1,93 @@ +foo(); +line.substr(0, separator_index); +boost::trim(key); +bpo::value() +bpo::value>()->multitoken() +std::make_unique(std::move(entries)); + +---------------------------------------------------- + +[ + ["function", "foo"], + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", ";"], + + "\r\nline", + ["punctuation", "."], + ["function", "substr"], + ["punctuation", "("], + ["number", "0"], + ["punctuation", ","], + " separator_index", + ["punctuation", ")"], + ["punctuation", ";"], + + "\r\nboost", + ["double-colon", "::"], + ["function", "trim"], + ["punctuation", "("], + "key", + ["punctuation", ")"], + ["punctuation", ";"], + + "\r\nbpo", + ["double-colon", "::"], + ["generic-function", [ + ["function", "value"], + ["generic", [ + ["operator", "<"], + "std", + ["double-colon", "::"], + "string", + ["operator", ">"] + ]] + ]], + ["punctuation", "("], + ["punctuation", ")"], + + "\r\nbpo", + ["double-colon", "::"], + ["generic-function", [ + ["function", "value"], + ["generic", [ + ["operator", "<"], + "std", + ["double-colon", "::"], + "vector", + ["operator", "<"], + "std", + ["double-colon", "::"], + "string", + ["operator", ">>"] + ]] + ]], + ["punctuation", "("], + ["punctuation", ")"], + ["operator", "->"], + ["function", "multitoken"], + ["punctuation", "("], + ["punctuation", ")"], + + "\r\nstd", + ["double-colon", "::"], + ["generic-function", [ + ["function", "make_unique"], + ["generic", [ + ["operator", "<"], + "service", + ["double-colon", "::"], + "UniqueMap", + ["operator", ">"] + ]] + ]], + ["punctuation", "("], + "std", + ["double-colon", "::"], + ["function", "move"], + ["punctuation", "("], + "entries", + ["punctuation", ")"], + ["punctuation", ")"], + ["punctuation", ";"] +] \ No newline at end of file diff --git a/tests/languages/cpp/issue2347.test b/tests/languages/cpp/issue2347.test index 9f302201b6..d6bf174ffc 100644 --- a/tests/languages/cpp/issue2347.test +++ b/tests/languages/cpp/issue2347.test @@ -40,7 +40,7 @@ void MainWindow::changeWindowTitle() ["keyword", "void"], ["class-name", "MainWindow"], - ["operator", "::"], + ["double-colon", "::"], ["function", "changeWindowTitle"], ["punctuation", "("], ["punctuation", ")"], @@ -67,6 +67,4 @@ void MainWindow::changeWindowTitle() ["punctuation", ";"], ["punctuation", "}"] -] - ----------------------------------------------------- +] \ No newline at end of file diff --git a/tests/languages/cpp/operator_feature.test b/tests/languages/cpp/operator_feature.test index 83b002e82e..c619b3aac3 100644 --- a/tests/languages/cpp/operator_feature.test +++ b/tests/languages/cpp/operator_feature.test @@ -3,7 +3,7 @@ ~ & | ^ += -= *= /= %= >>= <<= &= |= ^= ! && || --> :: +-> ? : = == != < > <= >= <=> and and_eq bitand bitor not not_eq or or_eq xor xor_eq @@ -43,7 +43,6 @@ and and_eq bitand bitor not not_eq or or_eq xor xor_eq ["operator", "||"], ["operator", "->"], - ["operator", "::"], ["operator", "?"], ["operator", ":"], diff --git a/tests/languages/cpp/punctuation_feature.test b/tests/languages/cpp/punctuation_feature.test new file mode 100644 index 0000000000..5ea8918234 --- /dev/null +++ b/tests/languages/cpp/punctuation_feature.test @@ -0,0 +1,18 @@ +( ) [ ] { } +, ; . :: + +---------------------------------------------------- + +[ + ["punctuation", "("], + ["punctuation", ")"], + ["punctuation", "["], + ["punctuation", "]"], + ["punctuation", "{"], + ["punctuation", "}"], + + ["punctuation", ","], + ["punctuation", ";"], + ["punctuation", "."], + ["double-colon", "::"] +] \ No newline at end of file