Quellcode durchsuchen

Handle whitespace within C++ preprocessor comments

Matt Godbolt vor 4 Jahren
Ursprung
Commit
5bca489245
2 geänderte Dateien mit 50 neuen und 11 gelöschten Zeilen
  1. 41 5
      src/cpp/cpp.test.ts
  2. 9 6
      src/cpp/cpp.ts

+ 41 - 5
src/cpp/cpp.test.ts

@@ -439,7 +439,7 @@ testTokenization('cpp', [
 		{
 		{
 			line: '#ifdef VAR',
 			line: '#ifdef VAR',
 			tokens: [
 			tokens: [
-				{ startIndex: 0, type: 'keyword.cpp' },
+				{ startIndex: 0, type: 'keyword.directive.cpp' },
 				{ startIndex: 6, type: '' },
 				{ startIndex: 6, type: '' },
 				{ startIndex: 7, type: 'identifier.cpp' }
 				{ startIndex: 7, type: 'identifier.cpp' }
 			]
 			]
@@ -447,7 +447,7 @@ testTokenization('cpp', [
 		{
 		{
 			line: '#define SUM(A,B) (A) + (B)',
 			line: '#define SUM(A,B) (A) + (B)',
 			tokens: [
 			tokens: [
-				{ startIndex: 0, type: 'keyword.cpp' },
+				{ startIndex: 0, type: 'keyword.directive.cpp' },
 				{ startIndex: 7, type: '' },
 				{ startIndex: 7, type: '' },
 				{ startIndex: 8, type: 'identifier.cpp' },
 				{ startIndex: 8, type: 'identifier.cpp' },
 				{ startIndex: 11, type: 'delimiter.parenthesis.cpp' },
 				{ startIndex: 11, type: 'delimiter.parenthesis.cpp' },
@@ -784,12 +784,12 @@ testTokenization('cpp', [
 		},
 		},
 		{
 		{
 			line: '#endif',
 			line: '#endif',
-			tokens: [{ startIndex: 0, type: 'keyword.cpp' }]
+			tokens: [{ startIndex: 0, type: 'keyword.directive.cpp' }]
 		},
 		},
 		{
 		{
 			line: '#    ifdef VAR',
 			line: '#    ifdef VAR',
 			tokens: [
 			tokens: [
-				{ startIndex: 0, type: 'keyword.cpp' },
+				{ startIndex: 0, type: 'keyword.directive.cpp' },
 				{ startIndex: 10, type: '' },
 				{ startIndex: 10, type: '' },
 				{ startIndex: 11, type: 'identifier.cpp' }
 				{ startIndex: 11, type: 'identifier.cpp' }
 			]
 			]
@@ -797,7 +797,7 @@ testTokenization('cpp', [
 		{
 		{
 			line: '#	define SUM(A,B) (A) + (B)',
 			line: '#	define SUM(A,B) (A) + (B)',
 			tokens: [
 			tokens: [
-				{ startIndex: 0, type: 'keyword.cpp' },
+				{ startIndex: 0, type: 'keyword.directive.cpp' },
 				{ startIndex: 8, type: '' },
 				{ startIndex: 8, type: '' },
 				{ startIndex: 9, type: 'identifier.cpp' },
 				{ startIndex: 9, type: 'identifier.cpp' },
 				{ startIndex: 12, type: 'delimiter.parenthesis.cpp' },
 				{ startIndex: 12, type: 'delimiter.parenthesis.cpp' },
@@ -914,5 +914,41 @@ testTokenization('cpp', [
 			line: '[ [nodiscard] ]',
 			line: '[ [nodiscard] ]',
 			tokens: [{ startIndex: 0, type: 'annotation.cpp' }]
 			tokens: [{ startIndex: 0, type: 'annotation.cpp' }]
 		}
 		}
+	],
+
+	// Preprocessor directives with whitespace inamongst the characters,
+	// and crucially checking with whitespace before the initial #.
+	[
+		{
+			line: ' # if defined(SOMETHING)',
+			tokens: [
+				{ startIndex: 0, type: 'keyword.directive.cpp' },
+				{ startIndex: 5, type: '' },
+				{ startIndex: 6, type: 'identifier.cpp' },
+				{ startIndex: 13, type: 'delimiter.parenthesis.cpp' },
+				{ startIndex: 14, type: 'identifier.cpp' },
+				{ startIndex: 23, type: 'delimiter.parenthesis.cpp' }
+			]
+		},
+		{
+			line: '        #include <io.h>',
+			tokens: [
+				{ startIndex: 0, type: 'keyword.directive.include.cpp' },
+				{ startIndex: 16, type: '' },
+				{ startIndex: 17, type: 'keyword.directive.include.begin.cpp' },
+				{ startIndex: 18, type: 'string.include.identifier.cpp' },
+				{ startIndex: 22, type: 'keyword.directive.include.end.cpp' }
+			]
+		},
+		{
+			line: '      #  include <io.h>',
+			tokens: [
+				{ startIndex: 0, type: 'keyword.directive.include.cpp' },
+				{ startIndex: 16, type: '' },
+				{ startIndex: 17, type: 'keyword.directive.include.begin.cpp' },
+				{ startIndex: 18, type: 'string.include.identifier.cpp' },
+				{ startIndex: 22, type: 'keyword.directive.include.end.cpp' }
+			]
+		}
 	]
 	]
 ]);
 ]);

+ 9 - 6
src/cpp/cpp.ts

@@ -294,17 +294,20 @@ export const language = <languages.IMonarchLanguage>{
 				}
 				}
 			],
 			],
 
 
+			// The preprocessor checks must be before whitespace as they check /^\s*#/ which
+			// otherwise fails to match later after other whitespace has been removed.
+
+			// Inclusion
+			[/^\s*#\s*include/, { token: 'keyword.directive.include', next: '@include' }],
+
+			// Preprocessor directive
+			[/^\s*#\s*\w+/, 'keyword.directive'],
+
 			// whitespace
 			// whitespace
 			{ include: '@whitespace' },
 			{ include: '@whitespace' },
 
 
 			// [[ attributes ]].
 			// [[ attributes ]].
 			[/\[\s*\[/, { token: 'annotation', next: '@annotation' }],
 			[/\[\s*\[/, { token: 'annotation', next: '@annotation' }],
-
-			[/^\s*#include/, { token: 'keyword.directive.include', next: '@include' }],
-
-			// Preprocessor directive
-			[/^\s*#\s*\w+/, 'keyword'],
-
 			// delimiters and operators
 			// delimiters and operators
 			[/[{}()\[\]]/, '@brackets'],
 			[/[{}()\[\]]/, '@brackets'],
 			[/[<>](?!@symbols)/, '@brackets'],
 			[/[<>](?!@symbols)/, '@brackets'],