浏览代码

Merge pull request #84 from VarghaSabee/feature/language-dart

Feature - dart language support
Alexandru Dima 5 年之前
父节点
当前提交
250984b6d2
共有 4 个文件被更改,包括 901 次插入0 次删除
  1. 15 0
      src/dart/dart.contribution.ts
  2. 559 0
      src/dart/dart.test.ts
  3. 326 0
      src/dart/dart.ts
  4. 1 0
      src/monaco.contribution.ts

+ 15 - 0
src/dart/dart.contribution.ts

@@ -0,0 +1,15 @@
+/*---------------------------------------------------------------------------------------------
+ *  Copyright (c) Microsoft Corporation. All rights reserved.
+ *  Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+'use strict';
+
+import { registerLanguage } from '../_.contribution';
+
+registerLanguage({
+	id: 'dart',
+	extensions: ['.dart'],
+	aliases: ['Dart', 'dart'],
+	mimetypes: ['text/x-dart-source', 'text/x-dart'],
+	loader: () => import('./dart')
+});

+ 559 - 0
src/dart/dart.test.ts

@@ -0,0 +1,559 @@
+/*---------------------------------------------------------------------------------------------
+ *  Copyright (c) Microsoft Corporation. All rights reserved.
+ *  Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+"use strict";
+
+import { testTokenization } from "../test/testRunner";
+
+testTokenization("dart", [
+	// Comments - single line
+	[
+		{
+			line: "//",
+			tokens: [{ startIndex: 0, type: "comment.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "    // a comment",
+			tokens: [
+				{ startIndex: 0, type: "" },
+				{ startIndex: 4, type: "comment.dart" }
+			]
+		}
+	],
+
+	// Broken nested tokens due to invalid comment tokenization
+	[
+		{
+			line: "/* //*/ a",
+			tokens: [
+				{ startIndex: 0, type: "comment.dart" },
+				{ startIndex: 7, type: "" },
+				{ startIndex: 8, type: "identifier.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "// a comment",
+			tokens: [{ startIndex: 0, type: "comment.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "//sticky comment",
+			tokens: [{ startIndex: 0, type: "comment.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "/almost a comment",
+			tokens: [
+				{ startIndex: 0, type: "delimiter.dart" },
+				{ startIndex: 1, type: "identifier.dart" },
+				{ startIndex: 7, type: "" },
+				{ startIndex: 8, type: "identifier.dart" },
+				{ startIndex: 9, type: "" },
+				{ startIndex: 10, type: "identifier.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "1 / 2; /* comment",
+			tokens: [
+				{ startIndex: 0, type: "number.dart" },
+				{ startIndex: 1, type: "" },
+				{ startIndex: 2, type: "delimiter.dart" },
+				{ startIndex: 3, type: "" },
+				{ startIndex: 4, type: "number.dart" },
+				{ startIndex: 5, type: "delimiter.dart" },
+				{ startIndex: 6, type: "" },
+				{ startIndex: 7, type: "comment.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "var x = 1; // my comment // is a nice one",
+			tokens: [
+				{ startIndex: 0, type: "keyword.dart" },
+				{ startIndex: 3, type: "" },
+				{ startIndex: 4, type: "identifier.dart" },
+				{ startIndex: 5, type: "" },
+				{ startIndex: 6, type: "delimiter.dart" },
+				{ startIndex: 7, type: "" },
+				{ startIndex: 8, type: "number.dart" },
+				{ startIndex: 9, type: "delimiter.dart" },
+				{ startIndex: 10, type: "" },
+				{ startIndex: 11, type: "comment.dart" }
+			]
+		}
+	],
+
+	// Comments - range comment, single line
+	[
+		{
+			line: "/* a simple comment */",
+			tokens: [{ startIndex: 0, type: "comment.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "var x = /* a simple comment */ 1;",
+			tokens: [
+				{ startIndex: 0, type: "keyword.dart" },
+				{ startIndex: 3, type: "" },
+				{ startIndex: 4, type: "identifier.dart" },
+				{ startIndex: 5, type: "" },
+				{ startIndex: 6, type: "delimiter.dart" },
+				{ startIndex: 7, type: "" },
+				{ startIndex: 8, type: "comment.dart" },
+				{ startIndex: 30, type: "" },
+				{ startIndex: 31, type: "number.dart" },
+				{ startIndex: 32, type: "delimiter.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "var x = /* comment */ 1; */",
+			tokens: [
+				{ startIndex: 0, type: "keyword.dart" },
+				{ startIndex: 3, type: "" },
+				{ startIndex: 4, type: "identifier.dart" },
+				{ startIndex: 5, type: "" },
+				{ startIndex: 6, type: "delimiter.dart" },
+				{ startIndex: 7, type: "" },
+				{ startIndex: 8, type: "comment.dart" },
+				{ startIndex: 21, type: "" },
+				{ startIndex: 22, type: "number.dart" },
+				{ startIndex: 23, type: "delimiter.dart" },
+				{ startIndex: 24, type: "" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "x = /**/;",
+			tokens: [
+				{ startIndex: 0, type: "identifier.dart" },
+				{ startIndex: 1, type: "" },
+				{ startIndex: 2, type: "delimiter.dart" },
+				{ startIndex: 3, type: "" },
+				{ startIndex: 4, type: "comment.dart" },
+				{ startIndex: 8, type: "delimiter.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "x = /*/;",
+			tokens: [
+				{ startIndex: 0, type: "identifier.dart" },
+				{ startIndex: 1, type: "" },
+				{ startIndex: 2, type: "delimiter.dart" },
+				{ startIndex: 3, type: "" },
+				{ startIndex: 4, type: "comment.dart" }
+			]
+		}
+	],
+
+	// Comments - range comment, multiple lines
+	[
+		{
+			line: "/* start of multiline comment",
+			tokens: [{ startIndex: 0, type: "comment.dart" }]
+		},
+		{
+			line: "a comment between without a star",
+			tokens: [{ startIndex: 0, type: "comment.dart" }]
+		},
+		{
+			line: "end of multiline comment*/",
+			tokens: [{ startIndex: 0, type: "comment.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "var x = /* start a comment",
+			tokens: [
+				{ startIndex: 0, type: "keyword.dart" },
+				{ startIndex: 3, type: "" },
+				{ startIndex: 4, type: "identifier.dart" },
+				{ startIndex: 5, type: "" },
+				{ startIndex: 6, type: "delimiter.dart" },
+				{ startIndex: 7, type: "" },
+				{ startIndex: 8, type: "comment.dart" }
+			]
+		},
+		{
+			line: " a ",
+			tokens: [{ startIndex: 0, type: "comment.dart" }]
+		},
+		{
+			line: "and end it */ 2;",
+			tokens: [
+				{ startIndex: 0, type: "comment.dart" },
+				{ startIndex: 13, type: "" },
+				{ startIndex: 14, type: "number.dart" },
+				{ startIndex: 15, type: "delimiter.dart" }
+			]
+		}
+	],
+
+	// Keywords
+	[
+		{
+			line: "var x = function() { };",
+			tokens: [
+				{ startIndex: 0, type: "keyword.dart" },
+				{ startIndex: 3, type: "" },
+				{ startIndex: 4, type: "identifier.dart" },
+				{ startIndex: 5, type: "" },
+				{ startIndex: 6, type: "delimiter.dart" },
+				{ startIndex: 7, type: "" },
+				{ startIndex: 8, type: "identifier.dart" },
+				{ startIndex: 16, type: "delimiter.parenthesis.dart" },
+				{ startIndex: 18, type: "" },
+				{ startIndex: 19, type: "delimiter.bracket.dart" },
+				{ startIndex: 20, type: "" },
+				{ startIndex: 21, type: "delimiter.bracket.dart" },
+				{ startIndex: 22, type: "delimiter.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "    var    ",
+			tokens: [
+				{ startIndex: 0, type: "" },
+				{ startIndex: 4, type: "keyword.dart" },
+				{ startIndex: 7, type: "" }
+			]
+		}
+	],
+
+	// Numbers
+	[
+		{
+			line: "0",
+			tokens: [{ startIndex: 0, type: "number.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "0.10",
+			tokens: [{ startIndex: 0, type: "number.float.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "0x",
+			tokens: [
+				{ startIndex: 0, type: "number.dart" },
+				{ startIndex: 1, type: "identifier.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "0x123",
+			tokens: [{ startIndex: 0, type: "number.hex.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "0x5_2",
+			tokens: [{ startIndex: 0, type: "number.hex.dart" }]
+		}
+	],
+	[
+		{
+			line: "0b1010_0101",
+			tokens: [{ startIndex: 0, type: "number.binary.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "0B001",
+			tokens: [{ startIndex: 0, type: "number.binary.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "10e3",
+			tokens: [{ startIndex: 0, type: "number.float.dart" }]
+		}
+	],
+	[
+		{
+			line: "23.5",
+			tokens: [{ startIndex: 0, type: "number.float.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "23.5e3",
+			tokens: [{ startIndex: 0, type: "number.float.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "23.5e-3",
+			tokens: [{ startIndex: 0, type: "number.float.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "23.5E3",
+			tokens: [{ startIndex: 0, type: "number.float.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "23.5E-3",
+			tokens: [{ startIndex: 0, type: "number.float.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "0_52",
+			tokens: [{ startIndex: 0, type: "number.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "5_2",
+			tokens: [{ startIndex: 0, type: "number.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "5_______2",
+			tokens: [{ startIndex: 0, type: "number.dart" }]
+		}
+	],
+	[
+		{
+			line: "3._1415F",
+			tokens: [
+				{ startIndex: 0, type: "number.dart" },
+				{ startIndex: 1, type: "delimiter.dart" },
+				{ startIndex: 2, type: "identifier.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "999_99_9999_L",
+			tokens: [
+				{ startIndex: 0, type: "number.dart" },
+				{ startIndex: 11, type: "identifier.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "52_",
+			tokens: [
+				{ startIndex: 0, type: "number.dart" },
+				{ startIndex: 2, type: "identifier.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "0_x52",
+			tokens: [
+				{ startIndex: 0, type: "number.dart" },
+				{ startIndex: 1, type: "identifier.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "0x_52",
+			tokens: [
+				{ startIndex: 0, type: "number.dart" },
+				{ startIndex: 1, type: "identifier.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "0x52_",
+			tokens: [
+				{ startIndex: 0, type: "number.hex.dart" },
+				{ startIndex: 4, type: "identifier.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "052_",
+			tokens: [
+				{ startIndex: 0, type: "number.octal.dart" },
+				{ startIndex: 3, type: "identifier.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "23.5L",
+			tokens: [
+				{ startIndex: 0, type: "number.float.dart" },
+				{ startIndex: 4, type: "type.identifier.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "0+0",
+			tokens: [
+				{ startIndex: 0, type: "number.dart" },
+				{ startIndex: 1, type: "delimiter.dart" },
+				{ startIndex: 2, type: "number.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "100+10",
+			tokens: [
+				{ startIndex: 0, type: "number.dart" },
+				{ startIndex: 3, type: "delimiter.dart" },
+				{ startIndex: 4, type: "number.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: "0 + 0",
+			tokens: [
+				{ startIndex: 0, type: "number.dart" },
+				{ startIndex: 1, type: "" },
+				{ startIndex: 2, type: "delimiter.dart" },
+				{ startIndex: 3, type: "" },
+				{ startIndex: 4, type: "number.dart" }
+			]
+		}
+	],
+
+	// Strings
+	[
+		{
+			line: "var s = 's';",
+			tokens: [
+				{ startIndex: 0, type: "keyword.dart" },
+				{ startIndex: 3, type: "" },
+				{ startIndex: 4, type: "identifier.dart" },
+				{ startIndex: 5, type: "" },
+				{ startIndex: 6, type: "delimiter.dart" },
+				{ startIndex: 7, type: "" },
+				{ startIndex: 8, type: "string.dart" },
+				{ startIndex: 11, type: "delimiter.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: 'String s = "concatenated" + " String" ;',
+			tokens: [
+				{ startIndex: 0, type: "type.identifier.dart" },
+				{ startIndex: 6, type: "" },
+				{ startIndex: 7, type: "identifier.dart" },
+				{ startIndex: 8, type: "" },
+				{ startIndex: 9, type: "delimiter.dart" },
+				{ startIndex: 10, type: "" },
+				{ startIndex: 11, type: "string.dart" },
+				{ startIndex: 25, type: "" },
+				{ startIndex: 26, type: "delimiter.dart" },
+				{ startIndex: 27, type: "" },
+				{ startIndex: 28, type: "string.dart" },
+				{ startIndex: 37, type: "" },
+				{ startIndex: 38, type: "delimiter.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: '"quote in a string"',
+			tokens: [{ startIndex: 0, type: "string.dart" }]
+		}
+	],
+
+	[
+		{
+			line: '"escaping \\"quotes\\" is cool"',
+			tokens: [
+				{ startIndex: 0, type: "string.dart" },
+				{ startIndex: 10, type: "string.escape.dart" },
+				{ startIndex: 12, type: "string.dart" },
+				{ startIndex: 18, type: "string.escape.dart" },
+				{ startIndex: 20, type: "string.dart" }
+			]
+		}
+	],
+
+	[
+		{
+			line: '"\\"',
+			tokens: [{ startIndex: 0, type: "string.invalid.dart" }]
+		}
+	],
+
+	// Annotations
+	[
+		{
+			line: "@",
+			tokens: [{ startIndex: 0, type: "invalid.dart" }]
+		}
+	],
+
+	[
+		{
+			line: "@Override",
+			tokens: [{ startIndex: 0, type: "annotation.dart" }]
+		}
+	]
+]);

+ 326 - 0
src/dart/dart.ts

@@ -0,0 +1,326 @@
+/*---------------------------------------------------------------------------------------------
+ *  Copyright (c) Microsoft Corporation. All rights reserved.
+ *  Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+"use strict";
+
+import LanguageConfiguration = monaco.languages.LanguageConfiguration;
+import IMonarchLanguage = monaco.languages.IMonarchLanguage;
+
+export const conf: LanguageConfiguration = {
+	comments: {
+		lineComment: "//",
+		blockComment: ["/*", "*/"]
+	},
+	brackets: [
+		["{", "}"],
+		["[", "]"],
+		["(", ")"]
+	],
+	autoClosingPairs: [
+		{ open: "{", close: "}" },
+		{ open: "[", close: "]" },
+		{ open: "(", close: ")" },
+		{ open: "'", close: "'", notIn: ["string", "comment"] },
+		{ open: '"', close: '"', notIn: ["string"] },
+		{ open: "`", close: "`", notIn: ["string", "comment"] },
+		{ open: "/**", close: " */", notIn: ["string"] }
+	],
+	surroundingPairs: [
+		{ open: "{", close: "}" },
+		{ open: "[", close: "]" },
+		{ open: "(", close: ")" },
+
+		{ open: "<", close: ">" },
+		{ open: "'", close: "'" },
+		{ open: "(", close: ")" },
+		{ open: '"', close: '"' },
+		{ open: "`", close: "`" }
+	],
+	folding: {
+		markers: {
+			start: /^\s*\s*#?region\b/,
+			end: /^\s*\s*#?endregion\b/
+		}
+	}
+};
+
+export const language = <IMonarchLanguage>{
+	defaultToken: "invalid",
+	tokenPostfix: ".dart",
+
+	keywords: [
+		"abstract",
+		"dynamic",
+		"implements",
+		"show",
+		"as",
+		"else",
+		"import",
+		"static",
+		"assert",
+		"enum",
+		"in",
+		"super",
+		"async",
+		"export",
+		"interface",
+		"switch",
+		"await",
+		"extends",
+		"is",
+		"sync",
+		"break",
+		"external",
+		"library",
+		"this",
+		"case",
+		"factory",
+		"mixin",
+		"throw",
+		"catch",
+		"false",
+		"new",
+		"true",
+		"class",
+		"final",
+		"null",
+		"try",
+		"const",
+		"finally",
+		"on",
+		"typedef",
+		"continue",
+		"for",
+		"operator",
+		"var",
+		"covariant",
+		"Function",
+		"part",
+		"void",
+		"default",
+		"get",
+		"rethrow",
+		"while",
+		"deferred",
+		"hide",
+		"return",
+		"with",
+		"do",
+		"if",
+		"set",
+		"yield"
+	],
+	typeKeywords: ["int", "double", "String", "bool"],
+
+	operators: [
+		"+",
+		"-",
+		"*",
+		"/",
+		"~/",
+		"%",
+		"++",
+		"--",
+		"==",
+		"!=",
+		">",
+		"<",
+		">=",
+		"<=",
+		"=",
+		"-=",
+		"/=",
+		"%=",
+		">>=",
+		"^=",
+		"+=",
+		"*=",
+		"~/=",
+		"<<=",
+		"&=",
+		"!=",
+		"||",
+		"&&",
+		"&",
+		"|",
+		"^",
+		"~",
+		"<<",
+		">>",
+		"!",
+		">>>",
+		"??",
+		"?",
+		":",
+		"|="
+	],
+
+	// we include these common regular expressions
+	symbols: /[=><!~?:&|+\-*\/\^%]+/,
+	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
+	digits: /\d+(_+\d+)*/,
+	octaldigits: /[0-7]+(_+[0-7]+)*/,
+	binarydigits: /[0-1]+(_+[0-1]+)*/,
+	hexdigits: /[[0-9a-fA-F]+(_+[0-9a-fA-F]+)*/,
+
+	regexpctl: /[(){}\[\]\$\^|\-*+?\.]/,
+	regexpesc: /\\(?:[bBdDfnrstvwWn0\\\/]|@regexpctl|c[A-Z]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})/,
+
+	// The main tokenizer for our languages
+	tokenizer: {
+		root: [[/[{}]/, "delimiter.bracket"], { include: "common" }],
+
+		common: [
+			// identifiers and keywords
+			[
+				/[a-z_$][\w$]*/,
+				{
+					cases: {
+						"@typeKeywords": "type.identifier",
+						"@keywords": "keyword",
+						"@default": "identifier"
+					}
+				}
+			],
+			[
+				/(?<![a-zA-Z0-9_$])([_$]*[A-Z][a-zA-Z0-9_$]*)/,
+				"type.identifier"
+			], // to show class names nicely
+			// [/[A-Z][\w\$]*/, 'identifier'],
+
+			// whitespace
+			{ include: "@whitespace" },
+
+			// regular expression: ensure it is terminated before beginning (otherwise it is an opeator)
+			[
+				/\/(?=([^\\\/]|\\.)+\/([gimsuy]*)(\s*)(\.|;|,|\)|\]|\}|$))/,
+				{ token: "regexp", bracket: "@open", next: "@regexp" }
+			],
+
+			// @ annotations.
+			[/@[a-zA-Z]+/, "annotation"],
+			// variable
+
+			// delimiters and operators
+			[/[()\[\]]/, "@brackets"],
+			[/[<>](?!@symbols)/, "@brackets"],
+			[/!(?=([^=]|$))/, "delimiter"],
+			[
+				/@symbols/,
+				{
+					cases: {
+						"@operators": "delimiter",
+						"@default": ""
+					}
+				}
+			],
+
+			// numbers
+			[/(@digits)[eE]([\-+]?(@digits))?/, "number.float"],
+			[/(@digits)\.(@digits)([eE][\-+]?(@digits))?/, "number.float"],
+			[/0[xX](@hexdigits)n?/, "number.hex"],
+			[/0[oO]?(@octaldigits)n?/, "number.octal"],
+			[/0[bB](@binarydigits)n?/, "number.binary"],
+			[/(@digits)n?/, "number"],
+
+			// delimiter: after number because of .\d floats
+			[/[;,.]/, "delimiter"],
+
+			// strings
+			[/"([^"\\]|\\.)*$/, "string.invalid"], // non-teminated string
+			[/'([^'\\]|\\.)*$/, "string.invalid"], // non-teminated string
+			[/"/, "string", "@string_double"],
+			[/'/, "string", "@string_single"]
+
+			//   [/[a-zA-Z]+/, "variable"]
+		],
+
+		whitespace: [
+			[/[ \t\r\n]+/, ""],
+			[/\/\*\*(?!\/)/, "comment.doc", "@jsdoc"],
+			[/\/\*/, "comment", "@comment"],
+			[/\/\/\/.*$/, "comment.doc"],
+			[/\/\/.*$/, "comment"]
+		],
+
+		comment: [
+			[/[^\/*]+/, "comment"],
+			[/\*\//, "comment", "@pop"],
+			[/[\/*]/, "comment"]
+		],
+
+		jsdoc: [
+			[/[^\/*]+/, "comment.doc"],
+			[/\*\//, "comment.doc", "@pop"],
+			[/[\/*]/, "comment.doc"]
+		],
+
+		// We match regular expression quite precisely
+		regexp: [
+			[
+				/(\{)(\d+(?:,\d*)?)(\})/,
+				[
+					"regexp.escape.control",
+					"regexp.escape.control",
+					"regexp.escape.control"
+				]
+			],
+			[
+				/(\[)(\^?)(?=(?:[^\]\\\/]|\\.)+)/,
+				[
+					"regexp.escape.control",
+					{ token: "regexp.escape.control", next: "@regexrange" }
+				]
+			],
+			[
+				/(\()(\?:|\?=|\?!)/,
+				["regexp.escape.control", "regexp.escape.control"]
+			],
+			[/[()]/, "regexp.escape.control"],
+			[/@regexpctl/, "regexp.escape.control"],
+			[/[^\\\/]/, "regexp"],
+			[/@regexpesc/, "regexp.escape"],
+			[/\\\./, "regexp.invalid"],
+			[
+				/(\/)([gimsuy]*)/,
+				[
+					{ token: "regexp", bracket: "@close", next: "@pop" },
+					"keyword.other"
+				]
+			]
+		],
+
+		regexrange: [
+			[/-/, "regexp.escape.control"],
+			[/\^/, "regexp.invalid"],
+			[/@regexpesc/, "regexp.escape"],
+			[/[^\]]/, "regexp"],
+			[
+				/\]/,
+				{
+					token: "regexp.escape.control",
+					next: "@pop",
+					bracket: "@close"
+				}
+			]
+		],
+
+		string_double: [
+			[/[^\\"\$]+/, "string"], [/[^\\"]+/, "string"],
+			[/@escapes/, "string.escape"],
+			[/\\./, "string.escape.invalid"],
+			[/"/, "string", "@pop"],
+			[/\$\w+/, 'identifier']
+		],
+
+		string_single: [
+			[/[^\\'\$]+/, "string"],
+			[/@escapes/, "string.escape"],
+			[/\\./, "string.escape.invalid"],
+			[/'/, "string", "@pop"],
+			[/\$\w+/, 'identifier']
+		],
+	}
+};

+ 1 - 0
src/monaco.contribution.ts

@@ -15,6 +15,7 @@ import './cpp/cpp.contribution';
 import './csharp/csharp.contribution';
 import './csharp/csharp.contribution';
 import './csp/csp.contribution';
 import './csp/csp.contribution';
 import './css/css.contribution';
 import './css/css.contribution';
+import './dart/dart.contribution';
 import './dockerfile/dockerfile.contribution';
 import './dockerfile/dockerfile.contribution';
 import './fsharp/fsharp.contribution';
 import './fsharp/fsharp.contribution';
 import './go/go.contribution';
 import './go/go.contribution';