From 4a070ab12d7601a5ed83963cade902a329fb540f Mon Sep 17 00:00:00 2001 From: Michael Schmidt Date: Wed, 29 Apr 2020 15:25:01 +0200 Subject: [PATCH] C: Improved macros (#2320) --- components/prism-c.js | 19 +++-- components/prism-c.min.js | 2 +- tests/languages/c/macro_feature.test | 122 +++++++++++++++++++++++---- 3 files changed, 117 insertions(+), 26 deletions(-) diff --git a/components/prism-c.js b/components/prism-c.js index c3b3ede7a2..c755712680 100644 --- a/components/prism-c.js +++ b/components/prism-c.js @@ -17,18 +17,23 @@ Prism.languages.insertBefore('c', 'string', { 'macro': { // allow for multiline macro definitions // spaces after the # character compile fine with gcc - pattern: /(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im, + pattern: /(^\s*)#\s*[a-z]+(?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im, lookbehind: true, + greedy: true, alias: 'property', inside: { - // highlight the path of the include statement as a string - 'string': { - pattern: /(#\s*include\s*)(?:<.+?>|(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2)/, - lookbehind: true - }, + 'string': [ + { + // highlight the path of the include statement as a string + pattern: /^(#\s*include\s*)<[^>]+>/, + lookbehind: true + }, + Prism.languages.c['string'] + ], + 'comment': Prism.languages.c['comment'], // highlight macro directives as keywords 'directive': { - pattern: /(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/, + pattern: /^(#\s*)[a-z]+/, lookbehind: true, alias: 'keyword' } diff --git a/components/prism-c.min.js b/components/prism-c.min.js index f34d9594ee..ccc6c806b0 100644 --- a/components/prism-c.min.js +++ b/components/prism-c.min.js @@ -1 +1 @@ -Prism.languages.c=Prism.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+/,lookbehind:!0},keyword:/\b(?:__attribute__|_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,function:/[a-z_]\w*(?=\s*\()/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/,number:/(?:\b0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(?:<.+?>|(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c.boolean; \ No newline at end of file +Prism.languages.c=Prism.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+/,lookbehind:!0},keyword:/\b(?:__attribute__|_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,function:/[a-z_]\w*(?=\s*\()/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/,number:/(?:\b0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},Prism.languages.c.string],comment:Prism.languages.c.comment,directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c.boolean; \ No newline at end of file diff --git a/tests/languages/c/macro_feature.test b/tests/languages/c/macro_feature.test index 6e65d9d590..8fb83b359c 100644 --- a/tests/languages/c/macro_feature.test +++ b/tests/languages/c/macro_feature.test @@ -1,5 +1,6 @@ # include - #define PG_locked 0 +# include "stdio.h" + #define PG_locked 0 #defined #elif @@ -16,30 +17,115 @@ #undef #using +#somethingunknown + +#define FOO /* + comment +*/ 1 + +#define FOO 1 // trailing comment + +#define MAX(a, b) \ + ((a) < (b) ? (b) : (a)) + ---------------------------------------------------- [ ["macro", [ - "# ", ["directive", "include"], + "# ", + ["directive", "include"], ["string", ""] ]], - ["macro", ["#", ["directive", "define"], " PG_locked 0"]], - ["macro", ["#", ["directive", "defined"]]], - ["macro", ["#", ["directive", "elif"]]], - ["macro", ["#", ["directive", "else"]]], - ["macro", ["#", ["directive", "endif"]]], - ["macro", ["#", ["directive", "error"]]], - ["macro", ["#", ["directive", "ifdef"]]], - ["macro", ["#", ["directive", "ifndef"]]], - ["macro", ["#", ["directive", "if"]]], - ["macro", ["#", ["directive", "import"]]], - ["macro", ["#", ["directive", "include"]]], - ["macro", ["#", ["directive", "line"]]], - ["macro", ["#", ["directive", "pragma"]]], - ["macro", ["#", ["directive", "undef"]]], - ["macro", ["#", ["directive", "using"]]] + ["macro", [ + "# ", + ["directive", "include"], + ["string", "\"stdio.h\""] + ]], + ["macro", [ + "#", + ["directive", "define"], + " PG_locked 0" + ]], + ["macro", [ + "#", + ["directive", "defined"] + ]], + ["macro", [ + "#", + ["directive", "elif"] + ]], + ["macro", [ + "#", + ["directive", "else"] + ]], + ["macro", [ + "#", + ["directive", "endif"] + ]], + ["macro", [ + "#", + ["directive", "error"] + ]], + ["macro", [ + "#", + ["directive", "ifdef"] + ]], + ["macro", [ + "#", + ["directive", "ifndef"] + ]], + ["macro", [ + "#", + ["directive", "if"] + ]], + ["macro", [ + "#", + ["directive", "import"] + ]], + ["macro", [ + "#", + ["directive", "include"] + ]], + ["macro", [ + "#", + ["directive", "line"] + ]], + ["macro", [ + "#", + ["directive", "pragma"] + ]], + ["macro", [ + "#", + ["directive", "undef"] + ]], + ["macro", [ + "#", + ["directive", "using"] + ]], + ["macro", [ + "#", + ["directive", "somethingunknown"] + ]], + ["macro", [ + "#", + ["directive", "define"], + " FOO ", + ["comment", "/*\r\n comment\r\n*/"], + " 1" + ]], + ["macro", [ + "#", + ["directive", "define"], + " FOO 1 ", + ["comment", "// trailing comment"] + ]], + ["macro", [ + "#", + ["directive", "define"], + " MAX(a, b) \\\r\n\t((a) < (b) ? (b) : (a))" + ]] ] ---------------------------------------------------- -Checks for macros and paths inside include statements. \ No newline at end of file +Checks for macros and paths inside include statements.