1
0
Alex Dima 8 жил өмнө
parent
commit
f661c5f826
65 өөрчлөгдсөн 18663 нэмэгдсэн , 16623 устгасан
  1. 3 2
      .vscode/settings.json
  2. 24 15
      src/bat.ts
  3. 59 35
      src/coffee.ts
  4. 35 27
      src/cpp.ts
  5. 64 53
      src/csharp.ts
  6. 7 7
      src/css.ts
  7. 85 55
      src/dockerfile.ts
  8. 39 31
      src/fsharp.ts
  9. 36 28
      src/go.ts
  10. 21 21
      src/handlebars.ts
  11. 20 20
      src/html.ts
  12. 18 14
      src/ini.ts
  13. 122 42
      src/jade.ts
  14. 35 27
      src/java.ts
  15. 6 6
      src/less.ts
  16. 45 28
      src/lua.ts
  17. 170 170
      src/markdown.ts
  18. 57 57
      src/monaco.contribution.ts
  19. 144 143
      src/msdax.ts
  20. 50 43
      src/objective-c.ts
  21. 37 37
      src/php.ts
  22. 635 630
      src/postiats.ts
  23. 84 26
      src/powershell.ts
  24. 61 57
      src/python.ts
  25. 6 6
      src/r.ts
  26. 31 31
      src/razor.ts
  27. 172 132
      src/ruby.ts
  28. 268 268
      src/scss.ts
  29. 7 7
      src/solidity.ts
  30. 68 64
      src/sql.ts
  31. 55 40
      src/swift.ts
  32. 71 67
      src/vb.ts
  33. 8 8
      src/xml.ts
  34. 67 42
      src/yaml.ts
  35. 327 275
      test/bat.test.ts
  36. 2188 1929
      test/coffee.test.ts
  37. 671 586
      test/cpp.test.ts
  38. 825 731
      test/csharp.test.ts
  39. 410 366
      test/css.test.ts
  40. 203 171
      test/dockerfile.test.ts
  41. 355 303
      test/fsharp.test.ts
  42. 1267 1148
      test/go.test.ts
  43. 152 152
      test/handlebars.test.ts
  44. 275 275
      test/html.test.ts
  45. 374 321
      test/jade.test.ts
  46. 565 489
      test/java.test.ts
  47. 889 819
      test/less.test.ts
  48. 59 54
      test/lua.test.ts
  49. 31 31
      test/markdown.test.ts
  50. 340 296
      test/msdax.test.ts
  51. 248 219
      test/objective-c.test.ts
  52. 1966 1803
      test/php.test.ts
  53. 927 835
      test/postiats.test.ts
  54. 781 682
      test/powershell.test.ts
  55. 80 68
      test/python.test.ts
  56. 460 410
      test/r.test.ts
  57. 108 99
      test/razor.test.ts
  58. 106 93
      test/ruby.test.ts
  59. 640 627
      test/scss.test.ts
  60. 224 204
      test/solidity.test.ts
  61. 515 445
      test/sql.test.ts
  62. 142 132
      test/swift.test.ts
  63. 371 328
      test/vb.test.ts
  64. 552 491
      test/xml.test.ts
  65. 2 2
      test/yaml.test.ts

+ 3 - 2
.vscode/settings.json

@@ -1,12 +1,13 @@
 // Place your settings in this file to overwrite default and user settings.
 {
-	"files.trimTrailingWhitespace": true,
 	"search.exclude": {
 		"**/node_modules": true,
 		"**/release": true,
 		"**/out": true
 	},
+	"files.trimTrailingWhitespace": true,
+	"files.insertFinalNewline": true,
 	"editor.tabSize": 4,
 	"editor.insertSpaces": false,
 	"typescript.tsdk": "./node_modules/typescript/lib"
-}
+}

+ 24 - 15
src/bat.ts

@@ -8,14 +8,14 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: 'REM'
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')']
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -30,7 +30,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	ignoreCase: true,
 	tokenPostfix: '.bat',
@@ -44,23 +44,23 @@ export var language = <ILanguage> {
 	keywords: /call|defined|echo|errorlevel|exist|for|goto|if|pause|set|shift|start|title|not|pushd|popd/,
 
 	// 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})/,
+	symbols: /[=><!~?&|+\-*\/\^;\.,]+/,
+	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
 
 	// The main tokenizer for our languages
 	tokenizer: {
 		root: [
 
-			[/^(\s*)(rem(?:\s.*|))$/, ['','comment']],
+			[/^(\s*)(rem(?:\s.*|))$/, ['', 'comment']],
 
-			[/(\@?)(@keywords)(?!\w)/, [{token:'keyword'}, {token:'keyword.$2'}]],
+			[/(\@?)(@keywords)(?!\w)/, [{ token: 'keyword' }, { token: 'keyword.$2' }]],
 
 			// whitespace
 			[/[ \t\r\n]+/, ''],
 
 			// blocks
-			[/setlocal(?!\w)/, 'keyword.tag-setlocal' ],
-			[/endlocal(?!\w)/, 'keyword.tag-setlocal' ],
+			[/setlocal(?!\w)/, 'keyword.tag-setlocal'],
+			[/endlocal(?!\w)/, 'keyword.tag-setlocal'],
 
 			// words
 			[/[a-zA-Z_]\w*/, ''],
@@ -85,18 +85,27 @@ export var language = <ILanguage> {
 			[/[;,.]/, 'delimiter'],
 
 			// strings:
-			[/"/,  'string', '@string."' ],
+			[/"/, 'string', '@string."'],
 			[/'/, 'string', '@string.\''],
 		],
 
 		string: [
-			[/[^\\"'%]+/, { cases: { '@eos': {token:'string', next:'@popall'}, '@default': 'string' }}],
+			[/[^\\"'%]+/, {
+				cases: {
+					'@eos': { token: 'string', next: '@popall' },
+					'@default': 'string'
+				}
+			}],
 			[/@escapes/, 'string.escape'],
 			[/\\./, 'string.escape.invalid'],
 			[/%[\w ]+%/, 'variable'],
 			[/%%[\w]+(?!\w)/, 'variable'],
-			[/["']/,     { cases: { '$#==$S2' : { token: 'string', next: '@pop' },
-							'@default': 'string' }} ],
+			[/["']/, {
+				cases: {
+					'$#==$S2': { token: 'string', next: '@pop' },
+					'@default': 'string'
+				}
+			}],
 			[/$/, 'string', '@popall']
 		],
 

+ 59 - 35
src/coffee.ts

@@ -8,16 +8,16 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#%\^\&\*\(\)\=\$\-\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
 	comments: {
 		blockComment: ['###', '###'],
 		lineComment: '#'
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')']
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -33,22 +33,17 @@ export var conf:IRichLanguageConfiguration = {
 		{ open: '"', close: '"' },
 		{ open: '\'', close: '\'' },
 	]
-	// enhancedBrackets: [
-	// 		{ open: /for$/ }, { open: /while$/ },	{ open: /loop$/ }, { open: /if$/ }, { open: /unless$/ },
-	// 		{ open: /else$/ }, { open: /switch$/ }, { open: /try$/ }, { open: /catch$/ }, { open: /finally$/ },
-	// 		{ open: /class$/ }, { open: /->$/ }
-	// 	],
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	ignoreCase: true,
 	tokenPostfix: '.coffee',
 
 	brackets: [
-		{ open:'{', close:'}', token:'delimiter.curly'},
-		{ open:'[', close:']', token:'delimiter.square'},
-		{ open:'(', close:')', token:'delimiter.parenthesis'}
+		{ open: '{', close: '}', token: 'delimiter.curly' },
+		{ open: '[', close: ']', token: 'delimiter.square' },
+		{ open: '(', close: ')', token: 'delimiter.parenthesis' }
 	],
 
 	regEx: /\/(?!\/\/)(?:[^\/\\]|\\.)*\/[igm]*/,
@@ -61,11 +56,11 @@ export var language = <ILanguage> {
 		'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally',
 		'class', 'extends', 'super',
 		'undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when'
-		],
+	],
 
 	// 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})/,
+	symbols: /[=><!~?&%|+\-*\/\^\.,\:]+/,
+	escapes: /\\(?:[abfnrtv\\"'$]|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
 
 	// The main tokenizer for our languages
 	tokenizer: {
@@ -73,10 +68,11 @@ export var language = <ILanguage> {
 
 			// identifiers and keywords
 			[/\@[a-zA-Z_]\w*/, 'variable.predefined'],
-			[/[a-zA-Z_]\w*/, { cases: {
-				'this': 'variable.predefined',
-				'@keywords': { token: 'keyword.$0' },
-				'@default': ''
+			[/[a-zA-Z_]\w*/, {
+				cases: {
+					'this': 'variable.predefined',
+					'@keywords': { token: 'keyword.$0' },
+					'@default': ''
 				}
 			}],
 
@@ -105,9 +101,12 @@ export var language = <ILanguage> {
 
 
 			// delimiters
-			[/}/, { cases: {
-					'$S2==interpolatedstring' : { token: 'string', next: '@pop' }
-					,	'@default'   : '@brackets' } }],
+			[/}/, {
+				cases: {
+					'$S2==interpolatedstring': { token: 'string', next: '@pop' },
+					'@default': '@brackets'
+				}
+			}],
 			[/[{}()\[\]]/, '@brackets'],
 			[/@symbols/, 'delimiter'],
 
@@ -123,9 +122,19 @@ export var language = <ILanguage> {
 
 			// strings:
 			[/"""/, 'string', '@herestring."""'],
-			[/'''/,  'string', '@herestring.\'\'\''],
-			[/"/,  { cases: { '@eos': 'string', '@default': {token:'string', next:'@string."'} }} ],
-			[/'/, { cases: { '@eos': 'string', '@default': {token:'string', next:'@string.\''} }} ],
+			[/'''/, 'string', '@herestring.\'\'\''],
+			[/"/, {
+				cases: {
+					'@eos': 'string',
+					'@default': { token: 'string', next: '@string."' }
+				}
+			}],
+			[/'/, {
+				cases: {
+					'@eos': 'string',
+					'@default': { token: 'string', next: '@string.\'' }
+				}
+			}],
 		],
 
 		string: [
@@ -134,27 +143,42 @@ export var language = <ILanguage> {
 			[/\./, 'string.escape.invalid'],
 			[/\./, 'string.escape.invalid'],
 
-			[/#{/,  { cases: { '$S2=="': { token: 'string', next: 'root.interpolatedstring' }, '@default': 'string' }}],
+			[/#{/, {
+				cases: {
+					'$S2=="': { token: 'string', next: 'root.interpolatedstring' },
+					'@default': 'string'
+				}
+			}],
 
-			[/["']/,     { cases: { '$#==$S2' : { token: 'string', next: '@pop' }, '@default': 'string' }} ],
+			[/["']/, {
+				cases: {
+					'$#==$S2': { token: 'string', next: '@pop' },
+					'@default': 'string'
+				}
+			}],
 			[/#/, 'string']
 		],
 
 		herestring: [
-			[/("""|''')/, { cases: { '$1==$S2': { token: 'string', next: '@pop' }, '@default': 'string' } }],
-			[/[^#\\'"]+/,'string' ],
-			[/['"]+/,'string' ],
+			[/("""|''')/, {
+				cases: {
+					'$1==$S2': { token: 'string', next: '@pop' },
+					'@default': 'string'
+				}
+			}],
+			[/[^#\\'"]+/, 'string'],
+			[/['"]+/, 'string'],
 			[/@escapes/, 'string.escape'],
 			[/\./, 'string.escape.invalid'],
 
-			[/#{/, { token: 'string.quote', next: 'root.interpolatedstring' } ],
+			[/#{/, { token: 'string.quote', next: 'root.interpolatedstring' }],
 			[/#/, 'string']
 		],
 
 		comment: [
-			[/[^#]+/, 'comment', ],
+			[/[^#]+/, 'comment',],
 			[/###/, 'comment', '@pop'],
-			[/#/, 'comment' ],
+			[/#/, 'comment'],
 		],
 
 		hereregexp: [
@@ -165,4 +189,4 @@ export var language = <ILanguage> {
 			[/\//, 'regexp'],
 		],
 	},
-};
+};

+ 35 - 27
src/cpp.ts

@@ -8,15 +8,15 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '//',
 		blockComment: ['/*', '*/'],
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')']
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
 	],
 	autoClosingPairs: [
 		{ open: '[', close: ']' },
@@ -34,7 +34,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.cpp',
 
@@ -236,8 +236,8 @@ export var language = <ILanguage> {
 	],
 
 	// 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})/,
+	symbols: /[=><!~?:&|+\-*\/\^%]+/,
+	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
 	integersuffix: /(ll|LL|u|U|l|L)?(ll|LL|u|U|l|L)?/,
 	floatsuffix: /[fFlL]?/,
 
@@ -245,8 +245,12 @@ export var language = <ILanguage> {
 	tokenizer: {
 		root: [
 			// identifiers and keywords
-			[/[a-zA-Z_]\w*/, { cases: { '@keywords': {token:'keyword.$0'},
-										'@default': 'identifier' } }],
+			[/[a-zA-Z_]\w*/, {
+				cases: {
+					'@keywords': { token: 'keyword.$0' },
+					'@default': 'identifier'
+				}
+			}],
 
 			// whitespace
 			{ include: '@whitespace' },
@@ -260,8 +264,12 @@ export var language = <ILanguage> {
 			// delimiters and operators
 			[/[{}()\[\]]/, '@brackets'],
 			[/[<>](?!@symbols)/, '@brackets'],
-			[/@symbols/, { cases: { '@operators': 'delimiter',
-									'@default'  : '' } } ],
+			[/@symbols/, {
+				cases: {
+					'@operators': 'delimiter',
+					'@default': ''
+				}
+			}],
 
 			// numbers
 			[/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/, 'number.float'],
@@ -276,39 +284,39 @@ export var language = <ILanguage> {
 			[/[;,.]/, 'delimiter'],
 
 			// strings
-			[/"([^"\\]|\\.)*$/, 'string.invalid' ],  // non-teminated string
-			[/"/,  'string', '@string' ],
+			[/"([^"\\]|\\.)*$/, 'string.invalid'],  // non-teminated string
+			[/"/, 'string', '@string'],
 
 			// characters
 			[/'[^\\']'/, 'string'],
-			[/(')(@escapes)(')/, ['string','string.escape','string']],
+			[/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
 			[/'/, 'string.invalid']
 		],
 
 		whitespace: [
 			[/[ \t\r\n]+/, ''],
-			[/\/\*\*(?!\/)/,  'comment.doc', '@doccomment' ],
-			[/\/\*/,       		'comment', '@comment' ],
-			[/\/\/.*$/,    		'comment'],
+			[/\/\*\*(?!\/)/, 'comment.doc', '@doccomment'],
+			[/\/\*/, 'comment', '@comment'],
+			[/\/\/.*$/, 'comment'],
 		],
 
 		comment: [
-			[/[^\/*]+/, 'comment' ],
-			[/\*\//,    'comment', '@pop'  ],
-			[/[\/*]/,   'comment' ]
+			[/[^\/*]+/, 'comment'],
+			[/\*\//, 'comment', '@pop'],
+			[/[\/*]/, 'comment']
 		],
 		//Identical copy of comment above, except for the addition of .doc
 		doccomment: [
-			[/[^\/*]+/, 'comment.doc' ],
-			[/\*\//,    'comment.doc', '@pop'  ],
-			[/[\/*]/,   'comment.doc' ]
+			[/[^\/*]+/, 'comment.doc'],
+			[/\*\//, 'comment.doc', '@pop'],
+			[/[\/*]/, 'comment.doc']
 		],
 
 		string: [
-			[/[^\\"]+/,  'string'],
+			[/[^\\"]+/, 'string'],
 			[/@escapes/, 'string.escape'],
-			[/\\./,      'string.escape.invalid'],
-			[/"/,        'string', '@pop' ]
+			[/\\./, 'string.escape.invalid'],
+			[/"/, 'string', '@pop']
 		],
 	},
-};
+};

+ 64 - 53
src/csharp.ts

@@ -8,16 +8,16 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\#\$\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
 	comments: {
 		lineComment: '//',
 		blockComment: ['/*', '*/'],
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')'],
+		['{', '}'],
+		['[', ']'],
+		['(', ')'],
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -36,7 +36,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.cs',
 
@@ -61,9 +61,9 @@ export var language = <ILanguage> {
 		'internal', 'private', 'abstract', 'sealed', 'static', 'struct', 'readonly',
 		'volatile', 'virtual', 'override', 'params', 'get', 'set', 'add', 'remove',
 		'operator', 'true', 'false', 'implicit', 'explicit', 'interface', 'enum',
-		'null', 'async', 'await','fixed','sizeof','stackalloc','unsafe', 'nameof',
+		'null', 'async', 'await', 'fixed', 'sizeof', 'stackalloc', 'unsafe', 'nameof',
 		'when'
-		],
+	],
 
 	namespaceFollows: [
 		'namespace', 'using',
@@ -75,11 +75,11 @@ export var language = <ILanguage> {
 
 	operators: [
 		'=', '??', '||', '&&', '|', '^', '&', '==', '!=', '<=', '>=', '<<',
-		'+', '-', '*', '/', '%', '!', '~', '++', '--','+=',
+		'+', '-', '*', '/', '%', '!', '~', '++', '--', '+=',
 		'-=', '*=', '/=', '%=', '&=', '|=', '^=', '<<=', '>>=', '>>', '=>'
 	],
 
-	symbols:  /[=><!~?:&|+\-*\/\^%]+/,
+	symbols: /[=><!~?:&|+\-*\/\^%]+/,
 
 	// escape sequences
 	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
@@ -89,10 +89,11 @@ export var language = <ILanguage> {
 		root: [
 
 			// identifiers and keywords
-			[/\@?[a-zA-Z_]\w*/, { cases: {
-				'@namespaceFollows': { token: 'keyword.$0', next: '@namespace' },
-				'@keywords': { token: 'keyword.$0', next: '@qualified' },
-				'@default': { token: 'identifier', next: '@qualified' }
+			[/\@?[a-zA-Z_]\w*/, {
+				cases: {
+					'@namespaceFollows': { token: 'keyword.$0', next: '@namespace' },
+					'@keywords': { token: 'keyword.$0', next: '@qualified' },
+					'@default': { token: 'identifier', next: '@qualified' }
 				}
 			}],
 
@@ -100,13 +101,21 @@ export var language = <ILanguage> {
 			{ include: '@whitespace' },
 
 			// delimiters and operators
-			[/}/, { cases: {
-					'$S2==interpolatedstring' : { token: 'string.quote', next: '@pop' }
-				,	'$S2==litinterpstring' : { token: 'string.quote', next: '@pop' }
-				,	'@default'   : '@brackets' } }],
+			[/}/, {
+				cases: {
+					'$S2==interpolatedstring': { token: 'string.quote', next: '@pop' },
+					'$S2==litinterpstring': { token: 'string.quote', next: '@pop' },
+					'@default': '@brackets'
+				}
+			}],
 			[/[{}()\[\]]/, '@brackets'],
 			[/[<>](?!@symbols)/, '@brackets'],
-			[/@symbols/, { cases: { '@operators': 'delimiter', '@default'  : '' } } ],
+			[/@symbols/, {
+				cases: {
+					'@operators': 'delimiter',
+					'@default': ''
+				}
+			}],
 
 
 			// numbers
@@ -119,79 +128,81 @@ export var language = <ILanguage> {
 			[/[;,.]/, 'delimiter'],
 
 			// strings
-			[/"([^"\\]|\\.)*$/, 'string.invalid' ],  // non-teminated string
-			[/"/,  { token: 'string.quote', next: '@string' } ],
-			[/\$\@"/, { token: 'string.quote', next: '@litinterpstring' } ],
-			[/\@"/, { token: 'string.quote', next: '@litstring' } ],
-			[/\$"/, { token: 'string.quote', next: '@interpolatedstring' } ],
+			[/"([^"\\]|\\.)*$/, 'string.invalid'],  // non-teminated string
+			[/"/, { token: 'string.quote', next: '@string' }],
+			[/\$\@"/, { token: 'string.quote', next: '@litinterpstring' }],
+			[/\@"/, { token: 'string.quote', next: '@litstring' }],
+			[/\$"/, { token: 'string.quote', next: '@interpolatedstring' }],
 
 			// characters
 			[/'[^\\']'/, 'string'],
-			[/(')(@escapes)(')/, ['string','string.escape','string']],
+			[/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
 			[/'/, 'string.invalid']
 		],
 
 		qualified: [
-			[/[a-zA-Z_][\w]*/, { cases:
-				{ '@keywords': {token:'keyword.$0'},
-				'@default': 'identifier' }
+			[/[a-zA-Z_][\w]*/, {
+				cases: {
+					'@keywords': { token: 'keyword.$0' },
+					'@default': 'identifier'
+				}
 			}],
 			[/\./, 'delimiter'],
-			['','','@pop'],
+			['', '', '@pop'],
 		],
 
 		namespace: [
 			{ include: '@whitespace' },
 			[/[A-Z]\w*/, 'namespace'],
 			[/[\.=]/, 'delimiter'],
-			['','','@pop'],
+			['', '', '@pop'],
 		],
 
 		comment: [
-			[/[^\/*]+/, 'comment' ],
+			[/[^\/*]+/, 'comment'],
 			// [/\/\*/,    'comment', '@push' ],    // no nested comments :-(
-			['\\*/',    'comment', '@pop'  ],
-			[/[\/*]/,   'comment' ]
+			['\\*/', 'comment', '@pop'],
+			[/[\/*]/, 'comment']
 		],
 
 		string: [
-			[/[^\\"]+/,  'string'],
+			[/[^\\"]+/, 'string'],
 			[/@escapes/, 'string.escape'],
-			[/\\./,      'string.escape.invalid'],
-			[/"/,        { token: 'string.quote', next: '@pop' } ]
+			[/\\./, 'string.escape.invalid'],
+			[/"/, { token: 'string.quote', next: '@pop' }]
 		],
 
 		litstring: [
-			[/[^"]+/,    'string'],
-			[/""/,       'string.escape'],
-			[/"/,        { token: 'string.quote', next: '@pop' } ]
+			[/[^"]+/, 'string'],
+			[/""/, 'string.escape'],
+			[/"/, { token: 'string.quote', next: '@pop' }]
 		],
 
 		litinterpstring: [
-			[/[^"{]+/,    'string'],
-			[/""/,       'string.escape'],
-			[/{{/,       'string.escape'],
-			[/}}/,       'string.escape'],
-			[/{/,        { token: 'string.quote', next: 'root.litinterpstring' } ],
-			[/"/,        { token: 'string.quote', next: '@pop' } ]
+			[/[^"{]+/, 'string'],
+			[/""/, 'string.escape'],
+			[/{{/, 'string.escape'],
+			[/}}/, 'string.escape'],
+			[/{/, { token: 'string.quote', next: 'root.litinterpstring' }],
+			[/"/, { token: 'string.quote', next: '@pop' }]
 		],
 
 		interpolatedstring: [
 			[/[^\\"{]+/, 'string'],
 			[/@escapes/, 'string.escape'],
-			[/\\./,      'string.escape.invalid'],
-			[/{{/,       'string.escape'],
-			[/}}/,       'string.escape'],
-			[/{/,        { token: 'string.quote', next: 'root.interpolatedstring' } ],
-			[/"/,        { token: 'string.quote', next: '@pop' } ]
+			[/\\./, 'string.escape.invalid'],
+			[/{{/, 'string.escape'],
+			[/}}/, 'string.escape'],
+			[/{/, { token: 'string.quote', next: 'root.interpolatedstring' }],
+			[/"/, { token: 'string.quote', next: '@pop' }]
 		],
 
 		whitespace: [
-			[/^[ \t\v\f]*#((r)|(load))(?=\s)/, 'directive.csx' ],
-			[/^[ \t\v\f]*#\w.*$/, 'namespace.cpp' ],
+			[/^[ \t\v\f]*#((r)|(load))(?=\s)/, 'directive.csx'],
+			[/^[ \t\v\f]*#\w.*$/, 'namespace.cpp'],
 			[/[ \t\v\f\r\n]+/, ''],
-			[/\/\*/,       'comment', '@comment' ],
-			[/\/\/.*$/,    'comment'],
+			[/\/\*/, 'comment', '@comment'],
+			[/\/\/.*$/, 'comment'],
 		],
 	},
 };

+ 7 - 7
src/css.ts

@@ -8,7 +8,7 @@
 import LanguageConfiguration = monaco.languages.LanguageConfiguration;
 import IMonarchLanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:LanguageConfiguration = {
+export var conf: LanguageConfiguration = {
 	wordPattern: /(#?-?\d*\.\d\w*%?)|((::|[@#.!:])?[\w-?]+%?)|::|[@#.!:]/g,
 
 	comments: {
@@ -44,7 +44,7 @@ const TOKEN_PROPERTY = 'attribute.name';
 const TOKEN_VALUE = 'attribute.value';
 const TOKEN_AT_KEYWORD = 'keyword';
 
-export var language = <IMonarchLanguage> {
+export var language = <IMonarchLanguage>{
 	defaultToken: '',
 	tokenPostfix: '.css',
 
@@ -70,8 +70,8 @@ export var language = <IMonarchLanguage> {
 			['[@](keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes)', { token: TOKEN_AT_KEYWORD, next: '@keyframedeclaration' }],
 			['[@](page|content|font-face|-moz-document)', { token: TOKEN_AT_KEYWORD }],
 			['[@](charset|namespace)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }],
-			['(url-prefix)(\\()', ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }] ],
-			['(url)(\\()', ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }] ],
+			['(url-prefix)(\\()', ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }]],
+			['(url)(\\()', ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }]],
 			{ include: '@selectorname' },
 			['[\\*]', TOKEN_SELECTOR_TAG], // selector symbols
 			['[>\\+,]', 'delimiter'], // selector operators
@@ -96,8 +96,8 @@ export var language = <IMonarchLanguage> {
 
 		term: [
 			{ include: '@comments' },
-			['(url-prefix)(\\()', ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }] ],
-			['(url)(\\()', ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }] ],
+			['(url-prefix)(\\()', ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }]],
+			['(url)(\\()', ['attribute.value', { token: 'delimiter.parenthesis', next: '@urldeclaration' }]],
 			{ include: '@functioninvocation' },
 			{ include: '@numbers' },
 			{ include: '@name' },
@@ -204,4 +204,4 @@ export var language = <IMonarchLanguage> {
 			['.', 'string']
 		]
 	}
-};
+};

+ 85 - 55
src/dockerfile.ts

@@ -8,11 +8,11 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')']
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -40,68 +40,98 @@ export var language = <ILanguage>{
 
 	variableAfter: /ENV/,
 
-	variable:/\${?[\w]+}?/,
+	variable: /\${?[\w]+}?/,
 
 	tokenizer: {
-	root: [
+		root: [
 			{ include: '@whitespace' },
 			{ include: '@comment' },
 
 			[/(@instructionAfter)(\s+)/, ['keyword', { token: '', next: '@instructions' }]],
 			['', 'keyword', '@instructions']
-	],
+		],
 
-	instructions: [
-			[/(@variableAfter)(\s+)([\w]+)/, ['keyword', '',{token:'variable', next:'@arguments'}]],
+		instructions: [
+			[/(@variableAfter)(\s+)([\w]+)/, ['keyword', '', { token: 'variable', next: '@arguments' }]],
 			[/(@instructions)/, 'keyword', '@arguments']
-	],
+		],
 
-	arguments: [
+		arguments: [
 			{ include: '@whitespace' },
 			{ include: '@strings' },
 
-			[/(@variable)/, { cases: { '@eos': {token:'variable', next:'@popall'}, '@default': 'variable' }} ],
-			[/\\/, { cases: { '@eos': '', '@default': '' }}],
-			[/./, { cases: { '@eos': {token:'', next:'@popall'}, '@default': '' } }],
-	],
-
-	// Deal with white space, including comments
-	whitespace: [
-		[/\s+/, { cases: { '@eos': {token:'', next:'@popall'}, '@default': '' }}],
-	],
-
-	comment: [
-		[/(^#.*$)/, 'comment', '@popall']
-	],
-
-	// Recognize strings, including those broken across lines with \ (but not without)
-	strings: [
-		[/'$/, 'string', '@popall'],
-		[/'/, 'string', '@stringBody'],
-		[/"$/, 'string', '@popall'],
-		[/"/, 'string', '@dblStringBody']
-	],
-	stringBody: [
-		[/[^\\\$']/, { cases: { '@eos': {token:'string', next:'@popall'}, '@default': 'string' }}],
-
-		[/\\./, 'string.escape'],
-		[/'$/, 'string', '@popall'],
-		[/'/, 'string', '@pop'],
-		[/(@variable)/, 'variable' ],
-
-		[/\\$/, 'string'],
-		[/$/, 'string', '@popall']
-	],
-	dblStringBody: [
-		[/[^\\\$"]/, { cases: { '@eos': {token:'string', next:'@popall'}, '@default': 'string' }}],
-
-		[/\\./, 'string.escape'],
-		[/"$/, 'string', '@popall'],
-		[/"/, 'string', '@pop'],
-		[/(@variable)/, 'variable' ],
-
-		[/\\$/, 'string'],
-		[/$/, 'string', '@popall']
-	]
+			[/(@variable)/, {
+				cases: {
+					'@eos': { token: 'variable', next: '@popall' },
+					'@default': 'variable'
+				}
+			}],
+			[/\\/, {
+				cases: {
+					'@eos': '',
+					'@default': ''
+				}
+			}],
+			[/./, {
+				cases: {
+					'@eos': { token: '', next: '@popall' },
+					'@default': ''
+				}
+			}],
+		],
+
+		// Deal with white space, including comments
+		whitespace: [
+			[/\s+/, {
+				cases: {
+					'@eos': { token: '', next: '@popall' },
+					'@default': ''
+				}
+			}],
+		],
+
+		comment: [
+			[/(^#.*$)/, 'comment', '@popall']
+		],
+
+		// Recognize strings, including those broken across lines with \ (but not without)
+		strings: [
+			[/'$/, 'string', '@popall'],
+			[/'/, 'string', '@stringBody'],
+			[/"$/, 'string', '@popall'],
+			[/"/, 'string', '@dblStringBody']
+		],
+		stringBody: [
+			[/[^\\\$']/, {
+				cases: {
+					'@eos': { token: 'string', next: '@popall' },
+					'@default': 'string'
+				}
+			}],
+
+			[/\\./, 'string.escape'],
+			[/'$/, 'string', '@popall'],
+			[/'/, 'string', '@pop'],
+			[/(@variable)/, 'variable'],
+
+			[/\\$/, 'string'],
+			[/$/, 'string', '@popall']
+		],
+		dblStringBody: [
+			[/[^\\\$"]/, {
+				cases: {
+					'@eos': { token: 'string', next: '@popall' },
+					'@default': 'string'
+				}
+			}],
+
+			[/\\./, 'string.escape'],
+			[/"$/, 'string', '@popall'],
+			[/"/, 'string', '@pop'],
+			[/(@variable)/, 'variable'],
+
+			[/\\$/, 'string'],
+			[/$/, 'string', '@popall']
+		]
 	}
-};
+};

+ 39 - 31
src/fsharp.ts

@@ -8,15 +8,15 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '//',
 		blockComment: ['(*', '*)'],
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')']
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -33,7 +33,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.fs',
 
@@ -43,15 +43,15 @@ export var language = <ILanguage> {
 		'break', 'checked', 'component',
 		'const', 'constraint', 'constructor',
 		'continue', 'class', 'default',
-		'delegate','do', 'done', 'downcast',
+		'delegate', 'do', 'done', 'downcast',
 		'downto', 'elif', 'else', 'end',
 		'exception', 'eager', 'event', 'external',
-		'extern',	'false', 'finally',	'for',
-		'fun',	'function', 'fixed', 'functor',
+		'extern', 'false', 'finally', 'for',
+		'fun', 'function', 'fixed', 'functor',
 		'global', 'if', 'in', 'include', 'inherit',
 		'inline', 'interface', 'internal', 'land',
-		'lor', 'lsl','lsr', 'lxor', 'lazy', 'let',
-		'match', 'member','mod','module', 'mutable',
+		'lor', 'lsl', 'lsr', 'lxor', 'lazy', 'let',
+		'match', 'member', 'mod', 'module', 'mutable',
 		'namespace', 'method', 'mixin', 'new', 'not',
 		'null', 'of', 'open', 'or', 'object',
 		'override', 'private', 'parallel', 'process',
@@ -60,12 +60,12 @@ export var language = <ILanguage> {
 		'to', 'true', 'tailcall', 'trait',
 		'try', 'type', 'upcast', 'use',
 		'val', 'void', 'virtual', 'volatile',
-		'when', 'while','with', 'yield'
+		'when', 'while', 'with', 'yield'
 	],
 
 	// 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})/,
+	symbols: /[=><!~?:&|+\-*\^%;\.,\/]+/,
+	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
 	integersuffix: /[uU]?[yslnLI]?/,
 	floatsuffix: /[fFmM]?/,
 
@@ -73,8 +73,12 @@ export var language = <ILanguage> {
 	tokenizer: {
 		root: [
 			// identifiers and keywords
-			[/[a-zA-Z_]\w*/, { cases: { '@keywords': {token:'keyword.$0'},
-										'@default': 'identifier' } }],
+			[/[a-zA-Z_]\w*/, {
+				cases: {
+					'@keywords': { token: 'keyword.$0' },
+					'@default': 'identifier'
+				}
+			}],
 
 			// whitespace
 			{ include: '@whitespace' },
@@ -88,7 +92,7 @@ export var language = <ILanguage> {
 			// delimiters and operators
 			[/[{}()\[\]]/, '@brackets'],
 			[/[<>](?!@symbols)/, '@brackets'],
-			[/@symbols/, 'delimiter' ],
+			[/@symbols/, 'delimiter'],
 
 			// numbers
 			[/\d*\d+[eE]([\-+]?\d+)?(@floatsuffix)/, 'number.float'],
@@ -102,43 +106,47 @@ export var language = <ILanguage> {
 			[/[;,.]/, 'delimiter'],
 
 			// strings
-			[/"([^"\\]|\\.)*$/, 'string.invalid' ],  // non-teminated string
+			[/"([^"\\]|\\.)*$/, 'string.invalid'],  // non-teminated string
 			[/"""/, 'string', '@string."""'],
-			[/"/, 'string', '@string."' ],
+			[/"/, 'string', '@string."'],
 
 			// literal string
 			[/\@"/, { token: 'string.quote', next: '@litstring' }],
 
 			// characters
 			[/'[^\\']'B?/, 'string'],
-			[/(')(@escapes)(')/, ['string','string.escape','string']],
+			[/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
 			[/'/, 'string.invalid']
 		],
 
 		whitespace: [
 			[/[ \t\r\n]+/, ''],
-			[/\(\*/,       		'comment', '@comment' ],
-			[/\/\/.*$/,    		'comment'],
+			[/\(\*/, 'comment', '@comment'],
+			[/\/\/.*$/, 'comment'],
 		],
 
 		comment: [
-			[/[^\*]+/, 'comment' ],
-			[/\*\)/,    'comment', '@pop'  ],
-			[/\*/,   'comment' ]
+			[/[^\*]+/, 'comment'],
+			[/\*\)/, 'comment', '@pop'],
+			[/\*/, 'comment']
 		],
 
 		string: [
 			[/[^\\"]+/, 'string'],
 			[/@escapes/, 'string.escape'],
-			[/\\./,      'string.escape.invalid'],
-			[/("""|"B?)/,     { cases: { '$#==$S2' : { token: 'string', next: '@pop' },
-									'@default': 'string' }} ]
+			[/\\./, 'string.escape.invalid'],
+			[/("""|"B?)/, {
+				cases: {
+					'$#==$S2': { token: 'string', next: '@pop' },
+					'@default': 'string'
+				}
+			}]
 		],
 
 		litstring: [
-			[/[^"]+/,    'string'],
-			[/""/,       'string.escape'],
-			[/"/,        { token: 'string.quote', next: '@pop' } ]
+			[/[^"]+/, 'string'],
+			[/""/, 'string.escape'],
+			[/"/, { token: 'string.quote', next: '@pop' }]
 		],
 	},
-};
+};

+ 36 - 28
src/go.ts

@@ -8,15 +8,15 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '//',
 		blockComment: ['/*', '*/'],
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')']
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -36,7 +36,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 
 	defaultToken: '',
 	tokenPostfix: '.go',
@@ -99,16 +99,20 @@ export var language = <ILanguage> {
 	],
 
 	// 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})/,
+	symbols: /[=><!~?:&|+\-*\/\^%]+/,
+	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
 
 
 	// The main tokenizer for our languages
 	tokenizer: {
 		root: [
 			// identifiers and keywords
-			[/[a-zA-Z_]\w*/, { cases: { '@keywords': {token:'keyword.$0'},
-																	'@default': 'identifier' } }],
+			[/[a-zA-Z_]\w*/, {
+				cases: {
+					'@keywords': { token: 'keyword.$0' },
+					'@default': 'identifier'
+				}
+			}],
 
 			// whitespace
 			{ include: '@whitespace' },
@@ -122,8 +126,12 @@ export var language = <ILanguage> {
 			// delimiters and operators
 			[/[{}()\[\]]/, '@brackets'],
 			[/[<>](?!@symbols)/, '@brackets'],
-			[/@symbols/, { cases: { '@operators': 'delimiter',
-															'@default'  : '' } } ],
+			[/@symbols/, {
+				cases: {
+					'@operators': 'delimiter',
+					'@default': ''
+				}
+			}],
 
 			// numbers
 			[/\d*\d+[eE]([\-+]?\d+)?/, 'number.float'],
@@ -138,44 +146,44 @@ export var language = <ILanguage> {
 			[/[;,.]/, 'delimiter'],
 
 			// strings
-			[/"([^"\\]|\\.)*$/, 'string.invalid' ],  // non-teminated string
-			[/"/,  'string', '@string' ],
+			[/"([^"\\]|\\.)*$/, 'string.invalid'],  // non-teminated string
+			[/"/, 'string', '@string'],
 			[/`/, "string", "@rawstring"],
 
 			// characters
 			[/'[^\\']'/, 'string'],
-			[/(')(@escapes)(')/, ['string','string.escape','string']],
+			[/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
 			[/'/, 'string.invalid']
 		],
 
 		whitespace: [
 			[/[ \t\r\n]+/, ''],
-			[/\/\*\*(?!\/)/,  'comment.doc', '@doccomment' ],
-			[/\/\*/,       		'comment', '@comment' ],
-			[/\/\/.*$/,    		'comment'],
+			[/\/\*\*(?!\/)/, 'comment.doc', '@doccomment'],
+			[/\/\*/, 'comment', '@comment'],
+			[/\/\/.*$/, 'comment'],
 		],
 
 		comment: [
-			[/[^\/*]+/, 'comment' ],
+			[/[^\/*]+/, 'comment'],
 			// [/\/\*/, 'comment', '@push' ],    // nested comment not allowed :-(
 			// [/\/\*/,    'comment.invalid' ],    // this breaks block comments in the shape of /* //*/
-			[/\*\//,    'comment', '@pop'  ],
-			[/[\/*]/,   'comment' ]
+			[/\*\//, 'comment', '@pop'],
+			[/[\/*]/, 'comment']
 		],
 		//Identical copy of comment above, except for the addition of .doc
 		doccomment: [
-			[/[^\/*]+/, 'comment.doc' ],
+			[/[^\/*]+/, 'comment.doc'],
 			// [/\/\*/, 'comment.doc', '@push' ],    // nested comment not allowed :-(
-			[/\/\*/,    'comment.doc.invalid' ],
-			[/\*\//,    'comment.doc', '@pop'  ],
-			[/[\/*]/,   'comment.doc' ]
+			[/\/\*/, 'comment.doc.invalid'],
+			[/\*\//, 'comment.doc', '@pop'],
+			[/[\/*]/, 'comment.doc']
 		],
 
 		string: [
-			[/[^\\"]+/,  'string'],
+			[/[^\\"]+/, 'string'],
 			[/@escapes/, 'string.escape'],
-			[/\\./,      'string.escape.invalid'],
-			[/"/,        'string', '@pop' ]
+			[/\\./, 'string.escape.invalid'],
+			[/"/, 'string', '@pop']
 		],
 
 		rawstring: [
@@ -183,4 +191,4 @@ export var language = <ILanguage> {
 			[/`/, "string", "@pop"]
 		],
 	},
-};
+};

+ 21 - 21
src/handlebars.ts

@@ -11,9 +11,9 @@ import ILanguage = monaco.languages.IMonarchLanguage;
 // Allow for running under nodejs/requirejs in tests
 var _monaco: typeof monaco = (typeof monaco === 'undefined' ? (<any>self).monaco : monaco);
 
-const EMPTY_ELEMENTS:string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
+const EMPTY_ELEMENTS: string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,
 
 	comments: {
@@ -65,7 +65,7 @@ export const htmlTokenTypes = {
 	}
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '',
 	// ignoreCase: true,
@@ -77,9 +77,9 @@ export var language = <ILanguage> {
 			[/<!DOCTYPE/, 'metatag.html', '@doctype'],
 			[/<!--/, 'comment.html', '@comment'],
 			[/(<)(\w+)(\/>)/, [htmlTokenTypes.DELIM_START, 'tag.html', htmlTokenTypes.DELIM_END]],
-			[/(<)(script)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@script'} ]],
-			[/(<)(style)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@style'} ]],
-			[/(<)([:\w]+)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@otherTag'} ]],
+			[/(<)(script)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@script' }]],
+			[/(<)(style)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@style' }]],
+			[/(<)([:\w]+)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@otherTag' }]],
 			[/(<\/)(\w+)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@otherTag' }]],
 			[/</, htmlTokenTypes.DELIM_START],
 			[/\{/, htmlTokenTypes.DELIM_START],
@@ -88,8 +88,8 @@ export var language = <ILanguage> {
 
 		doctype: [
 			[/\{\{/, { token: '@rematch', switchTo: '@handlebarsInSimpleState.comment' }],
-			[/[^>]+/, 'metatag.content.html' ],
-			[/>/, 'metatag.html', '@pop' ],
+			[/[^>]+/, 'metatag.content.html'],
+			[/>/, 'metatag.html', '@pop'],
 		],
 
 		comment: [
@@ -119,15 +119,15 @@ export var language = <ILanguage> {
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
 			[/=/, 'delimiter'],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.text/javascript', nextEmbedded: 'text/javascript'} ],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.text/javascript', nextEmbedded: 'text/javascript' }],
 			[/[ \t\r\n]+/], // whitespace
-			[/(<\/)(script\s*)(>)/, [ htmlTokenTypes.DELIM_START, 'tag.html', { token: htmlTokenTypes.DELIM_END, next: '@pop' } ]]
+			[/(<\/)(script\s*)(>)/, [htmlTokenTypes.DELIM_START, 'tag.html', { token: htmlTokenTypes.DELIM_END, next: '@pop' }]]
 		],
 
 		// After <script ... type
 		scriptAfterType: [
 			[/\{\{/, { token: '@rematch', switchTo: '@handlebarsInSimpleState.scriptAfterType' }],
-			[/=/,'delimiter', '@scriptAfterTypeEquals'],
+			[/=/, 'delimiter', '@scriptAfterTypeEquals'],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
 		],
@@ -135,8 +135,8 @@ export var language = <ILanguage> {
 		// After <script ... type =
 		scriptAfterTypeEquals: [
 			[/\{\{/, { token: '@rematch', switchTo: '@handlebarsInSimpleState.scriptAfterTypeEquals' }],
-			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' } ],
-			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' } ],
+			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' }],
+			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' }],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
 		],
@@ -144,7 +144,7 @@ export var language = <ILanguage> {
 		// After <script ... type = $S2
 		scriptWithCustomType: [
 			[/\{\{/, { token: '@rematch', switchTo: '@handlebarsInSimpleState.scriptWithCustomType.$S2' }],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.$S2', nextEmbedded: '$S2'}],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.$S2', nextEmbedded: '$S2' }],
 			[/"([^"]*)"/, 'attribute.value'],
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
@@ -171,15 +171,15 @@ export var language = <ILanguage> {
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
 			[/=/, 'delimiter'],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.text/css', nextEmbedded: 'text/css'} ],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.text/css', nextEmbedded: 'text/css' }],
 			[/[ \t\r\n]+/], // whitespace
-			[/(<\/)(style\s*)(>)/, [htmlTokenTypes.DELIM_START, 'tag.html', { token: htmlTokenTypes.DELIM_END, next: '@pop' } ]]
+			[/(<\/)(style\s*)(>)/, [htmlTokenTypes.DELIM_START, 'tag.html', { token: htmlTokenTypes.DELIM_END, next: '@pop' }]]
 		],
 
 		// After <style ... type
 		styleAfterType: [
 			[/\{\{/, { token: '@rematch', switchTo: '@handlebarsInSimpleState.styleAfterType' }],
-			[/=/,'delimiter', '@styleAfterTypeEquals'],
+			[/=/, 'delimiter', '@styleAfterTypeEquals'],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
 		],
@@ -187,8 +187,8 @@ export var language = <ILanguage> {
 		// After <style ... type =
 		styleAfterTypeEquals: [
 			[/\{\{/, { token: '@rematch', switchTo: '@handlebarsInSimpleState.styleAfterTypeEquals' }],
-			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' } ],
-			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' } ],
+			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' }],
+			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' }],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
 		],
@@ -196,7 +196,7 @@ export var language = <ILanguage> {
 		// After <style ... type = $S2
 		styleWithCustomType: [
 			[/\{\{/, { token: '@rematch', switchTo: '@handlebarsInSimpleState.styleWithCustomType.$S2' }],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.$S2', nextEmbedded: '$S2'}],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.$S2', nextEmbedded: '$S2' }],
 			[/"([^"]*)"/, 'attribute.value'],
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
@@ -232,4 +232,4 @@ export var language = <ILanguage> {
 			[/[^}]/, 'variable.parameter.handlebars'],
 		],
 	},
-};
+};

+ 20 - 20
src/html.ts

@@ -11,9 +11,9 @@ import ILanguage = monaco.languages.IMonarchLanguage;
 // Allow for running under nodejs/requirejs in tests
 var _monaco: typeof monaco = (typeof monaco === 'undefined' ? (<any>self).monaco : monaco);
 
-const EMPTY_ELEMENTS:string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
+const EMPTY_ELEMENTS: string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,
 
 	comments: {
@@ -66,7 +66,7 @@ export const htmlTokenTypes = {
 	}
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.html',
 	ignoreCase: true,
@@ -77,8 +77,8 @@ export var language = <ILanguage> {
 			[/<!DOCTYPE/, 'metatag', '@doctype'],
 			[/<!--/, 'comment', '@comment'],
 			[/(<)((?:[\w\-]+:)?[\w\-]+)(\s*)(\/>)/, [htmlTokenTypes.DELIM_START, 'tag', '', htmlTokenTypes.DELIM_END]],
-			[/(<)(script)/, [htmlTokenTypes.DELIM_START, { token: 'tag', next: '@script'} ]],
-			[/(<)(style)/, [htmlTokenTypes.DELIM_START, { token: 'tag', next: '@style'} ]],
+			[/(<)(script)/, [htmlTokenTypes.DELIM_START, { token: 'tag', next: '@script' }]],
+			[/(<)(style)/, [htmlTokenTypes.DELIM_START, { token: 'tag', next: '@style' }]],
 			[/(<)((?:[\w\-]+:)?[\w\-]+)/, [htmlTokenTypes.DELIM_START, { token: 'tag', next: '@otherTag' }]],
 			[/(<\/)((?:[\w\-]+:)?[\w\-]+)/, [htmlTokenTypes.DELIM_START, { token: 'tag', next: '@otherTag' }]],
 			[/</, htmlTokenTypes.DELIM_START],
@@ -86,8 +86,8 @@ export var language = <ILanguage> {
 		],
 
 		doctype: [
-			[/[^>]+/, 'metatag.content' ],
-			[/>/, 'metatag', '@pop' ],
+			[/[^>]+/, 'metatag.content'],
+			[/>/, 'metatag', '@pop'],
 		],
 
 		comment: [
@@ -114,29 +114,29 @@ export var language = <ILanguage> {
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
 			[/=/, 'delimiter'],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded', nextEmbedded: 'text/javascript'} ],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded', nextEmbedded: 'text/javascript' }],
 			[/[ \t\r\n]+/], // whitespace
-			[/(<\/)(script\s*)(>)/, [ htmlTokenTypes.DELIM_START, 'tag', { token: htmlTokenTypes.DELIM_END, next: '@pop' } ]]
+			[/(<\/)(script\s*)(>)/, [htmlTokenTypes.DELIM_START, 'tag', { token: htmlTokenTypes.DELIM_END, next: '@pop' }]]
 		],
 
 		// After <script ... type
 		scriptAfterType: [
-			[/=/,'delimiter', '@scriptAfterTypeEquals'],
+			[/=/, 'delimiter', '@scriptAfterTypeEquals'],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
 		],
 
 		// After <script ... type =
 		scriptAfterTypeEquals: [
-			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' } ],
-			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' } ],
+			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' }],
+			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' }],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
 		],
 
 		// After <script ... type = $S2
 		scriptWithCustomType: [
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.$S2', nextEmbedded: '$S2'}],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.$S2', nextEmbedded: '$S2' }],
 			[/"([^"]*)"/, 'attribute.value'],
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
@@ -162,29 +162,29 @@ export var language = <ILanguage> {
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
 			[/=/, 'delimiter'],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded', nextEmbedded: 'text/css'} ],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded', nextEmbedded: 'text/css' }],
 			[/[ \t\r\n]+/], // whitespace
-			[/(<\/)(style\s*)(>)/, [htmlTokenTypes.DELIM_START, 'tag', { token: htmlTokenTypes.DELIM_END, next: '@pop' } ]]
+			[/(<\/)(style\s*)(>)/, [htmlTokenTypes.DELIM_START, 'tag', { token: htmlTokenTypes.DELIM_END, next: '@pop' }]]
 		],
 
 		// After <style ... type
 		styleAfterType: [
-			[/=/,'delimiter', '@styleAfterTypeEquals'],
+			[/=/, 'delimiter', '@styleAfterTypeEquals'],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
 		],
 
 		// After <style ... type =
 		styleAfterTypeEquals: [
-			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' } ],
-			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' } ],
+			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' }],
+			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' }],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
 		],
 
 		// After <style ... type = $S2
 		styleWithCustomType: [
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.$S2', nextEmbedded: '$S2'}],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.$S2', nextEmbedded: '$S2' }],
 			[/"([^"]*)"/, 'attribute.value'],
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
@@ -198,7 +198,7 @@ export var language = <ILanguage> {
 			[/[^<]+/, '']
 		],
 
-	// -- END <style> tags handling
+		// -- END <style> tags handling
 	},
 };
 

+ 18 - 14
src/ini.ts

@@ -8,14 +8,14 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '#'
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')'],
+		['{', '}'],
+		['[', ']'],
+		['(', ')'],
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -33,12 +33,12 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.ini',
 
 	// we include these common regular expressions
-	escapes:  /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
+	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
 
 	// The main tokenizer for our languages
 	tokenizer: {
@@ -57,23 +57,27 @@ export var language = <ILanguage> {
 			[/\d+/, 'number'],
 
 			// strings: recover on non-terminated strings
-			[/"([^"\\]|\\.)*$/, 'string.invalid' ],  // non-teminated string
-			[/'([^'\\]|\\.)*$/, 'string.invalid' ],  // non-teminated string
-			[/"/,  'string', '@string."' ],
+			[/"([^"\\]|\\.)*$/, 'string.invalid'],  // non-teminated string
+			[/'([^'\\]|\\.)*$/, 'string.invalid'],  // non-teminated string
+			[/"/, 'string', '@string."'],
 			[/'/, 'string', '@string.\''],
 		],
 
 		whitespace: [
 			[/[ \t\r\n]+/, ''],
-			[/^\s*[#;].*$/,    		'comment'],
+			[/^\s*[#;].*$/, 'comment'],
 		],
 
 		string: [
 			[/[^\\"']+/, 'string'],
 			[/@escapes/, 'string.escape'],
-			[/\\./,      'string.escape.invalid'],
-			[/["']/,     { cases: { '$#==$S2' : { token: 'string', next: '@pop' },
-															'@default': 'string' }} ]
+			[/\\./, 'string.escape.invalid'],
+			[/["']/, {
+				cases: {
+					'$#==$S2': { token: 'string', next: '@pop' },
+					'@default': 'string'
+				}
+			}]
 		],
 	},
-};
+};

+ 122 - 42
src/jade.ts

@@ -8,11 +8,11 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '//'
 	},
-	brackets: [['{','}'], ['[',']'], ['(',')']],
+	brackets: [['{', '}'], ['[', ']'], ['(', ')']],
 	autoClosingPairs: [
 		{ open: '"', close: '"', notIn: ['string', 'comment'] },
 		{ open: '\'', close: '\'', notIn: ['string', 'comment'] },
@@ -22,19 +22,19 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.jade',
 
 	ignoreCase: true,
 
 	brackets: [
-			{ token:'delimiter.curly', open: '{', close: '}' },
-			{ token:'delimiter.array', open: '[', close: ']' },
-			{ token:'delimiter.parenthesis', open: '(', close: ')' }
+		{ token: 'delimiter.curly', open: '{', close: '}' },
+		{ token: 'delimiter.array', open: '[', close: ']' },
+		{ token: 'delimiter.parenthesis', open: '(', close: ')' }
 	],
 
-	keywords: [	'append', 'block', 'case', 'default', 'doctype', 'each', 'else', 'extends',
+	keywords: ['append', 'block', 'case', 'default', 'doctype', 'each', 'else', 'extends',
 		'for', 'if', 'in', 'include', 'mixin', 'typeof', 'unless', 'var', 'when'],
 
 	tags: [
@@ -70,26 +70,48 @@ export var language = <ILanguage> {
 
 			// Tag or a keyword at start
 			[/^(\s*)([a-zA-Z_-][\w-]*)/,
-				{ cases: {
-					'$2@tags': { cases: { '@eos': ['', 'tag'], '@default': ['', { token: 'tag', next: '@tag.$1' }, ] } },
-					'$2@keywords': [ '', { token: 'keyword.$2'}, ],
-					'@default': [ '', '', ]}}
+				{
+					cases: {
+						'$2@tags': {
+							cases: {
+								'@eos': ['', 'tag'],
+								'@default': ['', { token: 'tag', next: '@tag.$1' },]
+							}
+						},
+						'$2@keywords': ['', { token: 'keyword.$2' },],
+						'@default': ['', '',]
+					}
+				}
 			],
 
 			// id
-			[/^(\s*)(#[a-zA-Z_-][\w-]*)/, { cases: { '@eos': ['', 'tag.id'], '@default': ['', { token: 'tag.id', next: '@tag.$1' }] }}],
+			[/^(\s*)(#[a-zA-Z_-][\w-]*)/, {
+				cases: {
+					'@eos': ['', 'tag.id'],
+					'@default': ['', { token: 'tag.id', next: '@tag.$1' }]
+				}
+			}],
 
 			// class
-			[/^(\s*)(\.[a-zA-Z_-][\w-]*)/, { cases: { '@eos': ['', 'tag.class'], '@default': ['', { token: 'tag.class', next: '@tag.$1' }] } }],
+			[/^(\s*)(\.[a-zA-Z_-][\w-]*)/, {
+				cases: {
+					'@eos': ['', 'tag.class'],
+					'@default': ['', { token: 'tag.class', next: '@tag.$1' }]
+				}
+			}],
 
 			// plain text with pipe
-			[/^(\s*)(\|.*)$/, '' ],
+			[/^(\s*)(\|.*)$/, ''],
 
 			{ include: '@whitespace' },
 
 			// keywords
-			[/[a-zA-Z_$][\w$]*/, { cases: { '@keywords': {token:'keyword.$0'},
-											'@default': '' } }],
+			[/[a-zA-Z_$][\w$]*/, {
+				cases: {
+					'@keywords': { token: 'keyword.$0' },
+					'@default': ''
+				}
+			}],
 
 			// delimiters and operators
 			[/[{}()\[\]]/, '@brackets'],
@@ -100,80 +122,138 @@ export var language = <ILanguage> {
 			[/\d+/, 'number'],
 
 			// strings:
-			[/"/,  'string', '@string."' ],
+			[/"/, 'string', '@string."'],
 			[/'/, 'string', '@string.\''],
 		],
 
 		tag: [
-			[/(\.)(\s*$)/, [ {token: 'delimiter', next:'@blockText.$S2.'}, '']],
+			[/(\.)(\s*$)/, [{ token: 'delimiter', next: '@blockText.$S2.' }, '']],
 			[/\s+/, { token: '', next: '@simpleText' }],
 
 			// id
-			[/#[a-zA-Z_-][\w-]*/, { cases: { '@eos': { token: 'tag.id', next: '@pop' }, '@default': 'tag.id' } }],
+			[/#[a-zA-Z_-][\w-]*/, {
+				cases: {
+					'@eos': { token: 'tag.id', next: '@pop' },
+					'@default': 'tag.id'
+				}
+			}],
 			// class
-			[/\.[a-zA-Z_-][\w-]*/, { cases: { '@eos': { token: 'tag.class', next: '@pop' }, '@default': 'tag.class' } }],
+			[/\.[a-zA-Z_-][\w-]*/, {
+				cases: {
+					'@eos': { token: 'tag.class', next: '@pop' },
+					'@default': 'tag.class'
+				}
+			}],
 			// attributes
 			[/\(/, { token: 'delimiter.parenthesis', next: '@attributeList' }],
 		],
 
 		simpleText: [
-			[/[^#]+$/, {token: '', next: '@popall'}],
-			[/[^#]+/, {token: ''}],
+			[/[^#]+$/, { token: '', next: '@popall' }],
+			[/[^#]+/, { token: '' }],
 
 			// interpolation
-			[/(#{)([^}]*)(})/, { cases: {
-				'@eos': ['interpolation.delimiter', 'interpolation', { token: 'interpolation.delimiter', next: '@popall' }],
-				'@default': ['interpolation.delimiter', 'interpolation', 'interpolation.delimiter'] }}],
+			[/(#{)([^}]*)(})/, {
+				cases: {
+					'@eos': ['interpolation.delimiter', 'interpolation', { token: 'interpolation.delimiter', next: '@popall' }],
+					'@default': ['interpolation.delimiter', 'interpolation', 'interpolation.delimiter']
+				}
+			}],
 
 			[/#$/, { token: '', next: '@popall' }],
 			[/#/, '']
 		],
 
 		attributeList: [
-			[/\s+/, '' ],
-			[/(\w+)(\s*=\s*)("|')/, ['attribute.name', 'delimiter', { token: 'attribute.value', next:'@value.$3'}]],
+			[/\s+/, ''],
+			[/(\w+)(\s*=\s*)("|')/, ['attribute.name', 'delimiter', { token: 'attribute.value', next: '@value.$3' }]],
 			[/\w+/, 'attribute.name'],
 
 
-			[/,/, { cases: { '@eos': { token: 'attribute.delimiter', next: '@popall' }, '@default': 'attribute.delimiter' } }],
+			[/,/, {
+				cases: {
+					'@eos': { token: 'attribute.delimiter', next: '@popall' },
+					'@default': 'attribute.delimiter'
+				}
+			}],
 
 			[/\)$/, { token: 'delimiter.parenthesis', next: '@popall' }],
 			[/\)/, { token: 'delimiter.parenthesis', next: '@pop' }],
 		],
 
 		whitespace: [
-			[/^(\s*)(\/\/.*)$/, { token: 'comment', next: '@blockText.$1.comment' } ],
+			[/^(\s*)(\/\/.*)$/, { token: 'comment', next: '@blockText.$1.comment' }],
 			[/[ \t\r\n]+/, ''],
 			[/<!--/, { token: 'comment', next: '@comment' }],
 		],
 
 		blockText: [
-			[/^\s+.*$/, { cases: { '($S2\\s+.*$)': { token: '$S3' }, '@default': { token: '@rematch', next: '@popall' } } }],
-			[/./,  { token: '@rematch', next: '@popall' }]
+			[/^\s+.*$/, {
+				cases: {
+					'($S2\\s+.*$)': { token: '$S3' },
+					'@default': { token: '@rematch', next: '@popall' }
+				}
+			}],
+			[/./, { token: '@rematch', next: '@popall' }]
 		],
 
 		comment: [
-			[/[^<\-]+/, 'comment.content' ],
-			[/-->/,  { token: 'comment', next: '@pop' } ],
+			[/[^<\-]+/, 'comment.content'],
+			[/-->/, { token: 'comment', next: '@pop' }],
 			[/<!--/, 'comment.content.invalid'],
-			[/[<\-]/, 'comment.content' ]
+			[/[<\-]/, 'comment.content']
 		],
 
 		string: [
-			[/[^\\"'#]+/, { cases: { '@eos': { token: 'string', next: '@popall' }, '@default': 'string' } }],
-			[/@escapes/, { cases: { '@eos': { token: 'string.escape', next: '@popall' }, '@default': 'string.escape' }}],
-			[/\\./, { cases: { '@eos': { token: 'string.escape.invalid', next: '@popall' }, '@default': 'string.escape.invalid' }}],
+			[/[^\\"'#]+/, {
+				cases: {
+					'@eos': { token: 'string', next: '@popall' },
+					'@default': 'string'
+				}
+			}],
+			[/@escapes/, {
+				cases: {
+					'@eos': { token: 'string.escape', next: '@popall' },
+					'@default': 'string.escape'
+				}
+			}],
+			[/\\./, {
+				cases: {
+					'@eos': { token: 'string.escape.invalid', next: '@popall' },
+					'@default': 'string.escape.invalid'
+				}
+			}],
 			// interpolation
 			[/(#{)([^}]*)(})/, ['interpolation.delimiter', 'interpolation', 'interpolation.delimiter']],
 			[/#/, 'string'],
-			[/["']/, { cases: { '$#==$S2': { token: 'string', next: '@pop' }, '@default': { token: 'string' } } }],
+			[/["']/, {
+				cases: {
+					'$#==$S2': { token: 'string', next: '@pop' },
+					'@default': { token: 'string' }
+				}
+			}],
 		],
 
 		// Almost identical to above, except for escapes and the output token
 		value: [
-			[/[^\\"']+/, { cases: { '@eos': { token: 'attribute.value', next: '@popall' }, '@default': 'attribute.value' }}],
-			[/\\./, { cases: { '@eos': { token: 'attribute.value', next: '@popall' }, '@default': 'attribute.value' }}],
-			[/["']/, { cases: { '$#==$S2': { token: 'attribute.value', next: '@pop' }, '@default': { token: 'attribute.value' } } }],
+			[/[^\\"']+/, {
+				cases: {
+					'@eos': { token: 'attribute.value', next: '@popall' },
+					'@default': 'attribute.value'
+				}
+			}],
+			[/\\./, {
+				cases: {
+					'@eos': { token: 'attribute.value', next: '@popall' },
+					'@default': 'attribute.value'
+				}
+			}],
+			[/["']/, {
+				cases: {
+					'$#==$S2': { token: 'attribute.value', next: '@pop' },
+					'@default': { token: 'attribute.value' }
+				}
+			}],
 		],
 	},
-};
+};

+ 35 - 27
src/java.ts

@@ -8,7 +8,7 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	// the default separators except `@$`
 	wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
 	comments: {
@@ -16,9 +16,9 @@ export var conf:IRichLanguageConfiguration = {
 		blockComment: ['/*', '*/'],
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')'],
+		['{', '}'],
+		['[', ']'],
+		['(', ')'],
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -37,7 +37,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.java',
 
@@ -60,7 +60,7 @@ export var language = <ILanguage> {
 	],
 
 	// we include these common regular expressions
-	symbols:  /[=><!~?:&|+\-*\/\^%]+/,
+	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]+)*/,
@@ -71,8 +71,12 @@ export var language = <ILanguage> {
 	tokenizer: {
 		root: [
 			// identifiers and keywords
-			[/[a-zA-Z_$][\w$]*/, { cases: { '@keywords': {token:'keyword.$0'},
-																	'@default': 'identifier' } }],
+			[/[a-zA-Z_$][\w$]*/, {
+				cases: {
+					'@keywords': { token: 'keyword.$0' },
+					'@default': 'identifier'
+				}
+			}],
 
 			// whitespace
 			{ include: '@whitespace' },
@@ -80,8 +84,12 @@ export var language = <ILanguage> {
 			// delimiters and operators
 			[/[{}()\[\]]/, '@brackets'],
 			[/[<>](?!@symbols)/, '@brackets'],
-			[/@symbols/, { cases: { '@operators': 'delimiter',
-															'@default'  : '' } } ],
+			[/@symbols/, {
+				cases: {
+					'@operators': 'delimiter',
+					'@default': ''
+				}
+			}],
 
 			// @ annotations.
 			[/@\s*[a-zA-Z_\$][\w\$]*/, 'annotation'],
@@ -99,43 +107,43 @@ export var language = <ILanguage> {
 			[/[;,.]/, 'delimiter'],
 
 			// strings
-			[/"([^"\\]|\\.)*$/, 'string.invalid' ],  // non-teminated string
-			[/"/,  'string', '@string' ],
+			[/"([^"\\]|\\.)*$/, 'string.invalid'],  // non-teminated string
+			[/"/, 'string', '@string'],
 
 			// characters
 			[/'[^\\']'/, 'string'],
-			[/(')(@escapes)(')/, ['string','string.escape','string']],
+			[/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
 			[/'/, 'string.invalid']
 		],
 
 		whitespace: [
 			[/[ \t\r\n]+/, ''],
-			[/\/\*\*(?!\/)/,  'comment.doc', '@javadoc' ],
-			[/\/\*/,       		'comment', '@comment' ],
-			[/\/\/.*$/,    		'comment'],
+			[/\/\*\*(?!\/)/, 'comment.doc', '@javadoc'],
+			[/\/\*/, 'comment', '@comment'],
+			[/\/\/.*$/, 'comment'],
 		],
 
 		comment: [
-			[/[^\/*]+/, 'comment' ],
+			[/[^\/*]+/, 'comment'],
 			// [/\/\*/, 'comment', '@push' ],    // nested comment not allowed :-(
 			// [/\/\*/,    'comment.invalid' ],    // this breaks block comments in the shape of /* //*/
-			[/\*\//,    'comment', '@pop'  ],
-			[/[\/*]/,   'comment' ]
+			[/\*\//, 'comment', '@pop'],
+			[/[\/*]/, 'comment']
 		],
 		//Identical copy of comment above, except for the addition of .doc
 		javadoc: [
-			[/[^\/*]+/, 'comment.doc' ],
+			[/[^\/*]+/, 'comment.doc'],
 			// [/\/\*/, 'comment.doc', '@push' ],    // nested comment not allowed :-(
-			[/\/\*/,    'comment.doc.invalid' ],
-			[/\*\//,    'comment.doc', '@pop'  ],
-			[/[\/*]/,   'comment.doc' ]
+			[/\/\*/, 'comment.doc.invalid'],
+			[/\*\//, 'comment.doc', '@pop'],
+			[/[\/*]/, 'comment.doc']
 		],
 
 		string: [
-			[/[^\\"]+/,  'string'],
+			[/[^\\"]+/, 'string'],
 			[/@escapes/, 'string.escape'],
-			[/\\./,      'string.escape.invalid'],
-			[/"/,        'string', '@pop' ]
+			[/\\./, 'string.escape.invalid'],
+			[/"/, 'string', '@pop']
 		],
 	},
-};
+};

+ 6 - 6
src/less.ts

@@ -41,7 +41,7 @@ const TOKEN_PROPERTY = 'attribute.name';
 const TOKEN_VALUE = 'attribute.value';
 const TOKEN_AT_KEYWORD = 'keyword.control.at-rule';
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.less',
 
@@ -67,7 +67,7 @@ export var language = <ILanguage> {
 			{ include: '@numbers' },
 			['[*_]?[a-zA-Z\\-\\s]+(?=:.*(;|(\\\\$)))', TOKEN_PROPERTY, '@attribute'],
 
-			['url(\\-prefix)?\\(', { token: 'tag', next: '@urldeclaration'}],
+			['url(\\-prefix)?\\(', { token: 'tag', next: '@urldeclaration' }],
 
 			['[{}()\\[\\]]', '@brackets'],
 			['[,:;]', 'delimiter'],
@@ -104,9 +104,9 @@ export var language = <ILanguage> {
 		],
 
 		urldeclaration: [
-			{ include: '@strings'},
-			[ '[^)\r\n]+', 'string' ],
-			['\\)', { token: 'tag', next: '@pop'}],
+			{ include: '@strings' },
+			['[^)\r\n]+', 'string'],
+			['\\)', { token: 'tag', next: '@pop' }],
 		],
 
 		attribute: <any[]>[
@@ -177,4 +177,4 @@ export var language = <ILanguage> {
 			['.', 'key']
 		]
 	}
-};
+};

+ 45 - 28
src/lua.ts

@@ -8,15 +8,15 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '--',
 		blockComment: ['--[[', ']]'],
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')']
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -34,7 +34,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.lua',
 
@@ -47,9 +47,9 @@ export var language = <ILanguage> {
 	],
 
 	brackets: [
-		{ token: 'delimiter.bracket', open: '{', close: '}'},
-		{ token: 'delimiter.array', open: '[', close: ']'},
-		{ token: 'delimiter.parenthesis', open: '(', close: ')'}
+		{ token: 'delimiter.bracket', open: '{', close: '}' },
+		{ token: 'delimiter.array', open: '[', close: ']' },
+		{ token: 'delimiter.parenthesis', open: '(', close: ')' }
 	],
 
 	operators: [
@@ -58,26 +58,34 @@ export var language = <ILanguage> {
 	],
 
 	// 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})/,
+	symbols: /[=><!~?:&|+\-*\/\^%]+/,
+	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
 
 	// The main tokenizer for our languages
 	tokenizer: {
 		root: [
 			// identifiers and keywords
-			[/[a-zA-Z_]\w*/, { cases: { '@keywords': {token:'keyword.$0'},
-										'@default': 'identifier' } }],
+			[/[a-zA-Z_]\w*/, {
+				cases: {
+					'@keywords': { token: 'keyword.$0' },
+					'@default': 'identifier'
+				}
+			}],
 			// whitespace
 			{ include: '@whitespace' },
 
-		// keys
-		[/(,)(\s*)([a-zA-Z_]\w*)(\s*)(:)(?!:)/, ['delimiter', '', 'key', '', 'delimiter']],
-		[/({)(\s*)([a-zA-Z_]\w*)(\s*)(:)(?!:)/, ['@brackets', '', 'key', '', 'delimiter']],
+			// keys
+			[/(,)(\s*)([a-zA-Z_]\w*)(\s*)(:)(?!:)/, ['delimiter', '', 'key', '', 'delimiter']],
+			[/({)(\s*)([a-zA-Z_]\w*)(\s*)(:)(?!:)/, ['@brackets', '', 'key', '', 'delimiter']],
 
 			// delimiters and operators
 			[/[{}()\[\]]/, '@brackets'],
-			[/@symbols/, { cases: { '@operators': 'delimiter',
-									'@default'  : '' } } ],
+			[/@symbols/, {
+				cases: {
+					'@operators': 'delimiter',
+					'@default': ''
+				}
+			}],
 
 			// numbers
 			[/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'],
@@ -88,31 +96,40 @@ export var language = <ILanguage> {
 			[/[;,.]/, 'delimiter'],
 
 			// strings: recover on non-terminated strings
-			[/"([^"\\]|\\.)*$/, 'string.invalid' ],  // non-teminated string
-			[/'([^'\\]|\\.)*$/, 'string.invalid' ],  // non-teminated string
-			[/"/,  'string', '@string."' ],
+			[/"([^"\\]|\\.)*$/, 'string.invalid'],  // non-teminated string
+			[/'([^'\\]|\\.)*$/, 'string.invalid'],  // non-teminated string
+			[/"/, 'string', '@string."'],
 			[/'/, 'string', '@string.\''],
 		],
 
 		whitespace: [
 			[/[ \t\r\n]+/, ''],
-			[/--\[([=]*)\[/,  'comment', '@comment.$1' ],
-			[/--.*$/,        'comment'],
+			[/--\[([=]*)\[/, 'comment', '@comment.$1'],
+			[/--.*$/, 'comment'],
 		],
 
 		comment: [
 			[/[^\]]+/, 'comment'],
-			[/\]([=]*)\]/, { cases: { '$1==$S2': { token: 'comment', next: '@pop' }, '@default' : 'comment' } } ],
-			[/./,   'comment' ]
+			[/\]([=]*)\]/, {
+				cases: {
+					'$1==$S2': { token: 'comment', next: '@pop' },
+					'@default': 'comment'
+				}
+			}],
+			[/./, 'comment']
 		],
 
 		string: [
 			[/[^\\"']+/, 'string'],
 			[/@escapes/, 'string.escape'],
-			[/\\./,      'string.escape.invalid'],
-			[/["']/,     { cases: { '$#==$S2' : { token: 'string', next: '@pop' },
-									'@default': 'string' }} ]
+			[/\\./, 'string.escape.invalid'],
+			[/["']/, {
+				cases: {
+					'$#==$S2': { token: 'string', next: '@pop' },
+					'@default': 'string'
+				}
+			}]
 		],
 
 	},
-};
+};

+ 170 - 170
src/markdown.ts

@@ -22,179 +22,179 @@ const ATTRIB_NAME = 'attribute.name.html';
 const ATTRIB_VALUE = 'string.html';
 
 function getTag(name: string) {
-    return 'tag';
+	return 'tag';
 }
 
 export var conf: IRichLanguageConfiguration = {
-    comments: {
-        blockComment: ['<!--', '-->',]
-    },
-    brackets: [
-        ['{', '}'],
-        ['[', ']'],
-        ['(', ')']
-    ],
-    autoClosingPairs: [
-        { open: '{', close: '}' },
-        { open: '[', close: ']' },
-        { open: '(', close: ')' },
-        { open: '<', close: '>', notIn: [ 'string' ] }
-    ],
-    surroundingPairs: [
-        { open: '(', close: ')' },
-        { open: '[', close: ']' },
-        { open: '`', close: '`' },
-    ]
+	comments: {
+		blockComment: ['<!--', '-->',]
+	},
+	brackets: [
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
+	],
+	autoClosingPairs: [
+		{ open: '{', close: '}' },
+		{ open: '[', close: ']' },
+		{ open: '(', close: ')' },
+		{ open: '<', close: '>', notIn: ['string'] }
+	],
+	surroundingPairs: [
+		{ open: '(', close: ')' },
+		{ open: '[', close: ']' },
+		{ open: '`', close: '`' },
+	]
 };
 
 export var language = <ILanguage>{
-    defaultToken: '',
-    tokenPostfix: '.md',
-
-    // escape codes
-    control: /[\\`*_\[\]{}()#+\-\.!]/,
-    noncontrol: /[^\\`*_\[\]{}()#+\-\.!]/,
-    escapes: /\\(?:@control)/,
-
-    // escape codes for javascript/CSS strings
-    jsescapes: /\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,
-
-    // non matched elements
-    empty: [
-        'area', 'base', 'basefont', 'br', 'col', 'frame',
-        'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param'
-    ],
-
-    tokenizer: {
-        root: [
-
-            // headers (with #)
-            [/^(\s{0,3})(#+)((?:[^\\#]|@escapes)+)((?:#+)?)/, ['white', TOKEN_HEADER_LEAD, TOKEN_HEADER, TOKEN_HEADER]],
-
-            // headers (with =)
-            [/^\s*(=+|\-+)\s*$/, TOKEN_EXT_HEADER],
-
-            // headers (with ***)
-            [/^\s*((\*[ ]?)+)\s*$/, TOKEN_SEPARATOR],
-
-            // quote
-            [/^\s*>+/, TOKEN_QUOTE],
-
-            // list (starting with * or number)
-            [/^\s*([\*\-+:]|\d+\.)\s/, TOKEN_LIST],
-
-            // code block (4 spaces indent)
-            [/^(\t|[ ]{4})[^ ].*$/, TOKEN_BLOCK],
-
-            // code block (3 tilde)
-            [/^\s*~~~\s*((?:\w|[\/\-#])+)?\s*$/, { token: TOKEN_BLOCK, next: '@codeblock' }],
-
-            // github style code blocks (with backticks and language)
-            [/^\s*```\s*((?:\w|[\/\-#])+)\s*$/, { token: TOKEN_BLOCK, next: '@codeblockgh', nextEmbedded: '$1' }],
-
-            // github style code blocks (with backticks but no language)
-            [/^\s*```\s*$/, { token: TOKEN_BLOCK, next: '@codeblock' }],
-
-            // markup within lines
-            { include: '@linecontent' },
-        ],
-
-        codeblock: [
-            [/^\s*~~~\s*$/, { token: TOKEN_BLOCK, next: '@pop' }],
-            [/^\s*```\s*$/, { token: TOKEN_BLOCK, next: '@pop' }],
-            [/.*$/, TOKEN_BLOCK_CODE],
-        ],
-
-        // github style code blocks
-        codeblockgh: [
-            [/```\s*$/, { token: TOKEN_BLOCK_CODE, next: '@pop', nextEmbedded: '@pop' }],
-            [/[^`]+/, TOKEN_BLOCK_CODE],
-        ],
-
-        linecontent: [
-
-            // escapes
-            [/&\w+;/, 'string.escape'],
-            [/@escapes/, 'escape'],
-
-            // various markup
-            [/\b__([^\\_]|@escapes|_(?!_))+__\b/, 'strong'],
-            [/\*\*([^\\*]|@escapes|\*(?!\*))+\*\*/, 'strong'],
-            [/\b_[^_]+_\b/, 'emphasis'],
-            [/\*([^\\*]|@escapes)+\*/, 'emphasis'],
-            [/`([^\\`]|@escapes)+`/, 'variable'],
-
-            // links
-            [/\{[^}]+\}/, 'string.target'],
-            [/(!?\[)((?:[^\]\\]|@escapes)*)(\]\([^\)]+\))/, ['string.link', '', 'string.link']],
-            [/(!?\[)((?:[^\]\\]|@escapes)*)(\])/, 'string.link'],
-
-            // or html
-            { include: 'html' },
-        ],
-
-        // Note: it is tempting to rather switch to the real HTML mode instead of building our own here
-        // but currently there is a limitation in Monarch that prevents us from doing it: The opening
-        // '<' would start the HTML mode, however there is no way to jump 1 character back to let the
-        // HTML mode also tokenize the opening angle bracket. Thus, even though we could jump to HTML,
-        // we cannot correctly tokenize it in that mode yet.
-        html: [
-            // html tags
-            [/<(\w+)\/>/, getTag('$1')],
-            [/<(\w+)/, {
-                cases: {
-                    '@empty': { token: getTag('$1'), next: '@tag.$1' },
-                    '@default': { token: getTag('$1'), next: '@tag.$1' }
-                }
-            }],
-            [/<\/(\w+)\s*>/, { token: getTag('$1') }],
-
-            [/<!--/, 'comment', '@comment']
-        ],
-
-        comment: [
-            [/[^<\-]+/, 'comment.content'],
-            [/-->/, 'comment', '@pop'],
-            [/<!--/, 'comment.content.invalid'],
-            [/[<\-]/, 'comment.content']
-        ],
-
-        // Almost full HTML tag matching, complete with embedded scripts & styles
-        tag: [
-            [/[ \t\r\n]+/, 'white'],
-            [/(type)(\s*=\s*)(")([^"]+)(")/, [ATTRIB_NAME, DELIM_ASSIGN, ATTRIB_VALUE,
-                { token: ATTRIB_VALUE, switchTo: '@tag.$S2.$4' },
-                ATTRIB_VALUE]],
-            [/(type)(\s*=\s*)(')([^']+)(')/, [ATTRIB_NAME, DELIM_ASSIGN, ATTRIB_VALUE,
-                { token: ATTRIB_VALUE, switchTo: '@tag.$S2.$4' },
-                ATTRIB_VALUE]],
-            [/(\w+)(\s*=\s*)("[^"]*"|'[^']*')/, [ATTRIB_NAME, DELIM_ASSIGN, ATTRIB_VALUE]],
-            [/\w+/, ATTRIB_NAME],
-            [/\/>/, getTag('$S2'), '@pop'],
-            [/>/, {
-                cases: {
-                    '$S2==style': { token: getTag('$S2'), switchTo: 'embeddedStyle', nextEmbedded: 'text/css' },
-                    '$S2==script': {
-                        cases: {
-                            '$S3': { token: getTag('$S2'), switchTo: 'embeddedScript', nextEmbedded: '$S3' },
-                            '@default': { token: getTag('$S2'), switchTo: 'embeddedScript', nextEmbedded: 'text/javascript' }
-                        }
-                    },
-                    '@default': { token: getTag('$S2'), next: '@pop' }
-                }
-            }],
-        ],
-
-        embeddedStyle: [
-            [/[^<]+/, ''],
-            [/<\/style\s*>/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }],
-            [/</, '']
-        ],
-
-        embeddedScript: [
-            [/[^<]+/, ''],
-            [/<\/script\s*>/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }],
-            [/</, '']
-        ],
-    }
-};
+	defaultToken: '',
+	tokenPostfix: '.md',
+
+	// escape codes
+	control: /[\\`*_\[\]{}()#+\-\.!]/,
+	noncontrol: /[^\\`*_\[\]{}()#+\-\.!]/,
+	escapes: /\\(?:@control)/,
+
+	// escape codes for javascript/CSS strings
+	jsescapes: /\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,
+
+	// non matched elements
+	empty: [
+		'area', 'base', 'basefont', 'br', 'col', 'frame',
+		'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param'
+	],
+
+	tokenizer: {
+		root: [
+
+			// headers (with #)
+			[/^(\s{0,3})(#+)((?:[^\\#]|@escapes)+)((?:#+)?)/, ['white', TOKEN_HEADER_LEAD, TOKEN_HEADER, TOKEN_HEADER]],
+
+			// headers (with =)
+			[/^\s*(=+|\-+)\s*$/, TOKEN_EXT_HEADER],
+
+			// headers (with ***)
+			[/^\s*((\*[ ]?)+)\s*$/, TOKEN_SEPARATOR],
+
+			// quote
+			[/^\s*>+/, TOKEN_QUOTE],
+
+			// list (starting with * or number)
+			[/^\s*([\*\-+:]|\d+\.)\s/, TOKEN_LIST],
+
+			// code block (4 spaces indent)
+			[/^(\t|[ ]{4})[^ ].*$/, TOKEN_BLOCK],
+
+			// code block (3 tilde)
+			[/^\s*~~~\s*((?:\w|[\/\-#])+)?\s*$/, { token: TOKEN_BLOCK, next: '@codeblock' }],
+
+			// github style code blocks (with backticks and language)
+			[/^\s*```\s*((?:\w|[\/\-#])+)\s*$/, { token: TOKEN_BLOCK, next: '@codeblockgh', nextEmbedded: '$1' }],
+
+			// github style code blocks (with backticks but no language)
+			[/^\s*```\s*$/, { token: TOKEN_BLOCK, next: '@codeblock' }],
+
+			// markup within lines
+			{ include: '@linecontent' },
+		],
+
+		codeblock: [
+			[/^\s*~~~\s*$/, { token: TOKEN_BLOCK, next: '@pop' }],
+			[/^\s*```\s*$/, { token: TOKEN_BLOCK, next: '@pop' }],
+			[/.*$/, TOKEN_BLOCK_CODE],
+		],
+
+		// github style code blocks
+		codeblockgh: [
+			[/```\s*$/, { token: TOKEN_BLOCK_CODE, next: '@pop', nextEmbedded: '@pop' }],
+			[/[^`]+/, TOKEN_BLOCK_CODE],
+		],
+
+		linecontent: [
+
+			// escapes
+			[/&\w+;/, 'string.escape'],
+			[/@escapes/, 'escape'],
+
+			// various markup
+			[/\b__([^\\_]|@escapes|_(?!_))+__\b/, 'strong'],
+			[/\*\*([^\\*]|@escapes|\*(?!\*))+\*\*/, 'strong'],
+			[/\b_[^_]+_\b/, 'emphasis'],
+			[/\*([^\\*]|@escapes)+\*/, 'emphasis'],
+			[/`([^\\`]|@escapes)+`/, 'variable'],
+
+			// links
+			[/\{[^}]+\}/, 'string.target'],
+			[/(!?\[)((?:[^\]\\]|@escapes)*)(\]\([^\)]+\))/, ['string.link', '', 'string.link']],
+			[/(!?\[)((?:[^\]\\]|@escapes)*)(\])/, 'string.link'],
+
+			// or html
+			{ include: 'html' },
+		],
+
+		// Note: it is tempting to rather switch to the real HTML mode instead of building our own here
+		// but currently there is a limitation in Monarch that prevents us from doing it: The opening
+		// '<' would start the HTML mode, however there is no way to jump 1 character back to let the
+		// HTML mode also tokenize the opening angle bracket. Thus, even though we could jump to HTML,
+		// we cannot correctly tokenize it in that mode yet.
+		html: [
+			// html tags
+			[/<(\w+)\/>/, getTag('$1')],
+			[/<(\w+)/, {
+				cases: {
+					'@empty': { token: getTag('$1'), next: '@tag.$1' },
+					'@default': { token: getTag('$1'), next: '@tag.$1' }
+				}
+			}],
+			[/<\/(\w+)\s*>/, { token: getTag('$1') }],
+
+			[/<!--/, 'comment', '@comment']
+		],
+
+		comment: [
+			[/[^<\-]+/, 'comment.content'],
+			[/-->/, 'comment', '@pop'],
+			[/<!--/, 'comment.content.invalid'],
+			[/[<\-]/, 'comment.content']
+		],
+
+		// Almost full HTML tag matching, complete with embedded scripts & styles
+		tag: [
+			[/[ \t\r\n]+/, 'white'],
+			[/(type)(\s*=\s*)(")([^"]+)(")/, [ATTRIB_NAME, DELIM_ASSIGN, ATTRIB_VALUE,
+				{ token: ATTRIB_VALUE, switchTo: '@tag.$S2.$4' },
+				ATTRIB_VALUE]],
+			[/(type)(\s*=\s*)(')([^']+)(')/, [ATTRIB_NAME, DELIM_ASSIGN, ATTRIB_VALUE,
+				{ token: ATTRIB_VALUE, switchTo: '@tag.$S2.$4' },
+				ATTRIB_VALUE]],
+			[/(\w+)(\s*=\s*)("[^"]*"|'[^']*')/, [ATTRIB_NAME, DELIM_ASSIGN, ATTRIB_VALUE]],
+			[/\w+/, ATTRIB_NAME],
+			[/\/>/, getTag('$S2'), '@pop'],
+			[/>/, {
+				cases: {
+					'$S2==style': { token: getTag('$S2'), switchTo: 'embeddedStyle', nextEmbedded: 'text/css' },
+					'$S2==script': {
+						cases: {
+							'$S3': { token: getTag('$S2'), switchTo: 'embeddedScript', nextEmbedded: '$S3' },
+							'@default': { token: getTag('$S2'), switchTo: 'embeddedScript', nextEmbedded: 'text/javascript' }
+						}
+					},
+					'@default': { token: getTag('$S2'), next: '@pop' }
+				}
+			}],
+		],
+
+		embeddedStyle: [
+			[/[^<]+/, ''],
+			[/<\/style\s*>/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }],
+			[/</, '']
+		],
+
+		embeddedScript: [
+			[/[^<]+/, ''],
+			[/<\/script\s*>/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }],
+			[/</, '']
+		],
+	}
+};

+ 57 - 57
src/monaco.contribution.ts

@@ -4,7 +4,7 @@
  *--------------------------------------------------------------------------------------------*/
 'use strict';
 
-declare var require:<T>(moduleId:[string], callback:(module:T)=>void, error:(err:any)=>void)=>void;
+declare var require: <T>(moduleId: [string], callback: (module: T) => void, error: (err: any) => void) => void;
 
 // Allow for running under nodejs/requirejs in tests
 var _monaco: typeof monaco = (typeof monaco === 'undefined' ? (<any>self).monaco : monaco);
@@ -18,9 +18,9 @@ interface ILangImpl {
 	language: monaco.languages.IMonarchLanguage;
 }
 
-let languageDefinitions:{[languageId:string]:ILang} = {};
+let languageDefinitions: { [languageId: string]: ILang } = {};
 
-function _loadLanguage(languageId:string): monaco.Promise<void> {
+function _loadLanguage(languageId: string): monaco.Promise<void> {
 	let module = languageDefinitions[languageId].module;
 	return new _monaco.Promise<void>((c, e, p) => {
 		require<ILangImpl>([module], (mod) => {
@@ -31,16 +31,16 @@ function _loadLanguage(languageId:string): monaco.Promise<void> {
 	});
 }
 
-let languagePromises:{[languageId:string]: monaco.Promise<void>} = {};
+let languagePromises: { [languageId: string]: monaco.Promise<void> } = {};
 
-export function loadLanguage(languageId:string): monaco.Promise<void> {
+export function loadLanguage(languageId: string): monaco.Promise<void> {
 	if (!languagePromises[languageId]) {
 		languagePromises[languageId] = _loadLanguage(languageId);
 	}
 	return languagePromises[languageId];
 }
 
-function registerLanguage(def:ILang): void {
+function registerLanguage(def: ILang): void {
 	let languageId = def.id;
 
 	languageDefinitions[languageId] = def;
@@ -53,52 +53,52 @@ function registerLanguage(def:ILang): void {
 
 registerLanguage({
 	id: 'bat',
-	extensions: [ '.bat', '.cmd'],
-	aliases: [ 'Batch', 'bat' ],
+	extensions: ['.bat', '.cmd'],
+	aliases: ['Batch', 'bat'],
 	module: './bat'
 });
 registerLanguage({
 	id: 'coffeescript',
-	extensions: [ '.coffee' ],
-	aliases: [ 'CoffeeScript', 'coffeescript', 'coffee' ],
+	extensions: ['.coffee'],
+	aliases: ['CoffeeScript', 'coffeescript', 'coffee'],
 	mimetypes: ['text/x-coffeescript', 'text/coffeescript'],
 	module: './coffee'
 });
 registerLanguage({
 	id: 'c',
-	extensions: [ '.c', '.h' ],
-	aliases: [ 'C', 'c' ],
+	extensions: ['.c', '.h'],
+	aliases: ['C', 'c'],
 	module: './cpp'
 });
 registerLanguage({
 	id: 'cpp',
-	extensions: [ '.cpp', '.cc', '.cxx', '.hpp', '.hh', '.hxx' ],
-	aliases: [ 'C++', 'Cpp', 'cpp'],
+	extensions: ['.cpp', '.cc', '.cxx', '.hpp', '.hh', '.hxx'],
+	aliases: ['C++', 'Cpp', 'cpp'],
 	module: './cpp'
 });
 registerLanguage({
 	id: 'csharp',
-	extensions: [ '.cs', '.csx' ],
-	aliases: [ 'C#', 'csharp' ],
+	extensions: ['.cs', '.csx'],
+	aliases: ['C#', 'csharp'],
 	module: './csharp'
 });
 registerLanguage({
 	id: 'dockerfile',
-	extensions: [ '.dockerfile' ],
-	filenames: [ 'Dockerfile' ],
-	aliases: [ 'Dockerfile' ],
+	extensions: ['.dockerfile'],
+	filenames: ['Dockerfile'],
+	aliases: ['Dockerfile'],
 	module: './dockerfile'
 });
 registerLanguage({
 	id: 'fsharp',
-	extensions: [ '.fs', '.fsi', '.ml', '.mli', '.fsx', '.fsscript' ],
-	aliases: [ 'F#', 'FSharp', 'fsharp' ],
+	extensions: ['.fs', '.fsi', '.ml', '.mli', '.fsx', '.fsscript'],
+	aliases: ['F#', 'FSharp', 'fsharp'],
 	module: './fsharp'
 });
 registerLanguage({
 	id: 'go',
-	extensions: [ '.go' ],
-	aliases: [ 'Go' ],
+	extensions: ['.go'],
+	aliases: ['Go'],
 	module: './go'
 });
 registerLanguage({
@@ -117,28 +117,28 @@ registerLanguage({
 });
 registerLanguage({
 	id: 'ini',
-	extensions: [ '.ini', '.properties', '.gitconfig' ],
+	extensions: ['.ini', '.properties', '.gitconfig'],
 	filenames: ['config', '.gitattributes', '.gitconfig', '.editorconfig'],
-	aliases: [ 'Ini', 'ini' ],
+	aliases: ['Ini', 'ini'],
 	module: './ini'
 });
 registerLanguage({
 	id: 'jade',
-	extensions: [ '.jade', '.pug' ],
-	aliases: [ 'Jade', 'jade' ],
+	extensions: ['.jade', '.pug'],
+	aliases: ['Jade', 'jade'],
 	module: './jade'
 });
 registerLanguage({
 	id: 'java',
-	extensions: [ '.java', '.jav' ],
-	aliases: [ 'Java', 'java' ],
+	extensions: ['.java', '.jav'],
+	aliases: ['Java', 'java'],
 	mimetypes: ['text/x-java-source', 'text/x-java'],
 	module: './java'
 });
 registerLanguage({
 	id: 'lua',
-	extensions: [ '.lua' ],
-	aliases: [ 'Lua', 'lua' ],
+	extensions: ['.lua'],
+	aliases: ['Lua', 'lua'],
 	module: './lua'
 });
 registerLanguage({
@@ -155,14 +155,14 @@ registerLanguage({
 });
 registerLanguage({
 	id: 'objective-c',
-	extensions: [ '.m' ],
-	aliases: [ 'Objective-C'],
+	extensions: ['.m'],
+	aliases: ['Objective-C'],
 	module: './objective-c'
 });
- registerLanguage({
+registerLanguage({
 	id: 'postiats',
-	extensions: [ '.dats', '.sats', '.hats' ],
-	aliases: [ 'ATS', 'ATS/Postiats' ],
+	extensions: ['.dats', '.sats', '.hats'],
+	aliases: ['ATS', 'ATS/Postiats'],
 	module: './postiats'
 });
 registerLanguage({
@@ -174,21 +174,21 @@ registerLanguage({
 });
 registerLanguage({
 	id: 'powershell',
-	extensions: [ '.ps1', '.psm1', '.psd1' ],
-	aliases: [ 'PowerShell', 'powershell', 'ps', 'ps1' ],
+	extensions: ['.ps1', '.psm1', '.psd1'],
+	aliases: ['PowerShell', 'powershell', 'ps', 'ps1'],
 	module: './powershell'
 });
 registerLanguage({
 	id: 'python',
-	extensions: [ '.py', '.rpy', '.pyw', '.cpy', '.gyp', '.gypi' ],
-	aliases: [ 'Python', 'py' ],
+	extensions: ['.py', '.rpy', '.pyw', '.cpy', '.gyp', '.gypi'],
+	aliases: ['Python', 'py'],
 	firstLine: '^#!/.*\\bpython[0-9.-]*\\b',
 	module: './python'
 });
 registerLanguage({
 	id: 'r',
-	extensions: [ '.r', '.rhistory', '.rprofile', '.rt' ],
-	aliases: [ 'R', 'r' ],
+	extensions: ['.r', '.rhistory', '.rprofile', '.rt'],
+	aliases: ['R', 'r'],
 	module: './r'
 });
 registerLanguage({
@@ -200,35 +200,35 @@ registerLanguage({
 });
 registerLanguage({
 	id: 'ruby',
-	extensions: [ '.rb', '.rbx', '.rjs', '.gemspec', '.pp' ],
-	filenames: [ 'rakefile' ],
-	aliases: [ 'Ruby', 'rb' ],
+	extensions: ['.rb', '.rbx', '.rjs', '.gemspec', '.pp'],
+	filenames: ['rakefile'],
+	aliases: ['Ruby', 'rb'],
 	module: './ruby'
 });
 registerLanguage({
 	id: 'swift',
-	aliases: ['Swift','swift'],
+	aliases: ['Swift', 'swift'],
 	extensions: ['.swift'],
 	mimetypes: ['text/swift'],
 	module: './swift'
 });
 registerLanguage({
 	id: 'sql',
-	extensions: [ '.sql' ],
-	aliases: [ 'SQL' ],
+	extensions: ['.sql'],
+	aliases: ['SQL'],
 	module: './sql'
 });
 registerLanguage({
 	id: 'vb',
-	extensions: [ '.vb' ],
-	aliases: [ 'Visual Basic', 'vb' ],
+	extensions: ['.vb'],
+	aliases: ['Visual Basic', 'vb'],
 	module: './vb'
 });
 registerLanguage({
 	id: 'xml',
-	extensions: [ '.xml', '.dtd', '.ascx', '.csproj', '.config', '.wxi', '.wxl', '.wxs', '.xaml', '.svg', '.svgz' ],
-	firstLine : '(\\<\\?xml.*)|(\\<svg)|(\\<\\!doctype\\s+svg)',
-	aliases: [ 'XML', 'xml' ],
+	extensions: ['.xml', '.dtd', '.ascx', '.csproj', '.config', '.wxi', '.wxl', '.wxs', '.xaml', '.svg', '.svgz'],
+	firstLine: '(\\<\\?xml.*)|(\\<svg)|(\\<\\!doctype\\s+svg)',
+	aliases: ['XML', 'xml'],
 	mimetypes: ['text/xml', 'application/xml', 'application/xaml+xml', 'application/xml-dtd'],
 	module: './xml'
 });
@@ -261,8 +261,8 @@ registerLanguage({
 	module: './yaml'
 });
 registerLanguage({
-  	id: 'sol',
-  	extensions: [ '.sol' ],
-  	aliases: [ 'sol','solidity','Solidity' ],
-  	module: './solidity'
+	id: 'sol',
+	extensions: ['.sol'],
+	aliases: ['sol', 'solidity', 'Solidity'],
+	module: './solidity'
 });

+ 144 - 143
src/msdax.ts

@@ -8,48 +8,48 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '//',
 		blockComment: ['/*', '*/'],
 	},
-	brackets: [['[',']'],['(',')'],['{','}']],
+	brackets: [['[', ']'], ['(', ')'], ['{', '}']],
 	autoClosingPairs: [
 		{ open: '"', close: '"', notIn: ['string', 'comment'] },
 		{ open: '\'', close: '\'', notIn: ['string', 'comment'] },
 		{ open: '[', close: ']', notIn: ['string', 'comment'] },
-    { open: '(', close: ')', notIn: ['string', 'comment'] },
-    { open: '{', close: '}', notIn: ['string', 'comment'] },
+		{ open: '(', close: ')', notIn: ['string', 'comment'] },
+		{ open: '{', close: '}', notIn: ['string', 'comment'] },
 	]
 };
 
-export var language = <ILanguage> {
-  defaultToken: '',
-  tokenPostfix: '.msdax',
-  ignoreCase: true,
+export var language = <ILanguage>{
+	defaultToken: '',
+	tokenPostfix: '.msdax',
+	ignoreCase: true,
 
-  brackets: [
-    { open: '[', close: ']', token: 'delimiter.square' },
-    { open: '{', close: '}', token: 'delimiter.brackets' },
-    { open: '(', close: ')', token: 'delimiter.parenthesis' }
-  ],
+	brackets: [
+		{ open: '[', close: ']', token: 'delimiter.square' },
+		{ open: '{', close: '}', token: 'delimiter.brackets' },
+		{ open: '(', close: ')', token: 'delimiter.parenthesis' }
+	],
 
-  keywords: [
+	keywords: [
 		// Query keywords
-    'VAR',
-    'RETURN',
-    'NOT',
-    'EVALUATE',
-    'DATATABLE',
-    'ORDER',
-    'BY',
-    'START',
-    'AT',
-    'DEFINE',
-    'MEASURE',
-    'ASC',
-    'DESC',
-    'IN',
+		'VAR',
+		'RETURN',
+		'NOT',
+		'EVALUATE',
+		'DATATABLE',
+		'ORDER',
+		'BY',
+		'START',
+		'AT',
+		'DEFINE',
+		'MEASURE',
+		'ASC',
+		'DESC',
+		'IN',
 		// Datatable types
 		'BOOLEAN',
 		'DOUBLE',
@@ -57,119 +57,120 @@ export var language = <ILanguage> {
 		'DATETIME',
 		'CURRENCY',
 		'STRING'
-  ],
-  functions: [
-    // Relational
-    'CLOSINGBALANCEMONTH', 'CLOSINGBALANCEQUARTER', 'CLOSINGBALANCEYEAR', 'DATEADD', 'DATESBETWEEN',
-    'DATESINPERIOD', 'DATESMTD', 'DATESQTD', 'DATESYTD', 'ENDOFMONTH',
-    'ENDOFQUARTER', 'ENDOFYEAR', 'FIRSTDATE', 'FIRSTNONBLANK', 'LASTDATE',
-    'LASTNONBLANK', 'NEXTDAY', 'NEXTMONTH', 'NEXTQUARTER', 'NEXTYEAR',
-    'OPENINGBALANCEMONTH', 'OPENINGBALANCEQUARTER', 'OPENINGBALANCEYEAR', 'PARALLELPERIOD', 'PREVIOUSDAY',
-    'PREVIOUSMONTH', 'PREVIOUSQUARTER', 'PREVIOUSYEAR', 'SAMEPERIODLASTYEAR', 'STARTOFMONTH',
-    'STARTOFQUARTER', 'STARTOFYEAR', 'TOTALMTD', 'TOTALQTD', 'TOTALYTD',
-    'ADDCOLUMNS', 'ADDMISSINGITEMS', 'ALL', 'ALLEXCEPT', 'ALLNOBLANKROW',
-    'ALLSELECTED', 'CALCULATE', 'CALCULATETABLE', 'CALENDAR', 'CALENDARAUTO',
-    'CROSSFILTER', 'CROSSJOIN', 'CURRENTGROUP', 'DATATABLE', 'DETAILROWS',
-    'DISTINCT', 'EARLIER', 'EARLIEST', 'EXCEPT', 'FILTER',
-    'FILTERS', 'GENERATE', 'GENERATEALL', 'GROUPBY', 'IGNORE',
-    'INTERSECT', 'ISONORAFTER', 'KEEPFILTERS', 'LOOKUPVALUE', 'NATURALINNERJOIN',
-    'NATURALLEFTOUTERJOIN', 'RELATED', 'RELATEDTABLE', 'ROLLUP', 'ROLLUPADDISSUBTOTAL',
-    'ROLLUPGROUP', 'ROLLUPISSUBTOTAL', 'ROW', 'SAMPLE', 'SELECTCOLUMNS',
-    'SUBSTITUTEWITHINDEX', 'SUMMARIZE', 'SUMMARIZECOLUMNS', 'TOPN', 'TREATAS',
-    'UNION', 'USERELATIONSHIP', 'VALUES', 'SUM', 'SUMX',
-    'PATH', 'PATHCONTAINS', 'PATHITEM', 'PATHITEMREVERSE', 'PATHLENGTH',
-    'AVERAGE', 'AVERAGEA', 'AVERAGEX', 'COUNT', 'COUNTA',
-    'COUNTAX', 'COUNTBLANK', 'COUNTROWS', 'COUNTX', 'DISTINCTCOUNT',
-    'DIVIDE', 'GEOMEAN', 'GEOMEANX', 'MAX', 'MAXA',
-    'MAXX', 'MEDIAN', 'MEDIANX', 'MIN', 'MINA',
-    'MINX', 'PERCENTILE.EXC', 'PERCENTILE.INC', 'PERCENTILEX.EXC', 'PERCENTILEX.INC',
-    'PRODUCT', 'PRODUCTX', 'RANK.EQ', 'RANKX', 'STDEV.P',
-    'STDEV.S', 'STDEVX.P', 'STDEVX.S', 'VAR.P', 'VAR.S',
-    'VARX.P', 'VARX.S', 'XIRR', 'XNPV',
-    // Scalar
-    'DATE', 'DATEDIFF', 'DATEVALUE', 'DAY', 'EDATE',
-    'EOMONTH', 'HOUR', 'MINUTE', 'MONTH', 'NOW',
-    'SECOND', 'TIME', 'TIMEVALUE', 'TODAY', 'WEEKDAY',
-    'WEEKNUM', 'YEAR', 'YEARFRAC', 'CONTAINS', 'CONTAINSROW',
-    'CUSTOMDATA', 'ERROR', 'HASONEFILTER', 'HASONEVALUE', 'ISBLANK',
-    'ISCROSSFILTERED', 'ISEMPTY', 'ISERROR', 'ISEVEN', 'ISFILTERED',
-    'ISLOGICAL', 'ISNONTEXT', 'ISNUMBER', 'ISODD', 'ISSUBTOTAL',
-    'ISTEXT', 'USERNAME', 'USERPRINCIPALNAME', 'AND', 'FALSE',
-    'IF', 'IFERROR', 'NOT', 'OR', 'SWITCH',
-    'TRUE', 'ABS', 'ACOS', 'ACOSH', 'ACOT',
-    'ACOTH', 'ASIN', 'ASINH', 'ATAN', 'ATANH',
-    'BETA.DIST', 'BETA.INV', 'CEILING', 'CHISQ.DIST', 'CHISQ.DIST.RT',
-    'CHISQ.INV', 'CHISQ.INV.RT', 'COMBIN', 'COMBINA', 'CONFIDENCE.NORM',
-    'CONFIDENCE.T', 'COS', 'COSH', 'COT', 'COTH',
-    'CURRENCY', 'DEGREES', 'EVEN', 'EXP', 'EXPON.DIST',
-    'FACT', 'FLOOR', 'GCD', 'INT', 'ISO.CEILING',
-    'LCM', 'LN', 'LOG', 'LOG10', 'MOD',
-    'MROUND', 'ODD', 'PERMUT', 'PI', 'POISSON.DIST',
-    'POWER', 'QUOTIENT', 'RADIANS', 'RAND', 'RANDBETWEEN',
-    'ROUND', 'ROUNDDOWN', 'ROUNDUP', 'SIGN', 'SIN',
-    'SINH', 'SQRT', 'SQRTPI', 'TAN', 'TANH',
-    'TRUNC', 'BLANK', 'CONCATENATE', 'CONCATENATEX', 'EXACT',
-    'FIND', 'FIXED', 'FORMAT', 'LEFT', 'LEN',
-    'LOWER', 'MID', 'REPLACE', 'REPT', 'RIGHT',
-    'SEARCH', 'SUBSTITUTE', 'TRIM', 'UNICHAR', 'UNICODE',
-    'UPPER', 'VALUE'
-  ],
-  tokenizer: {
-    root: [
-      { include: '@comments' },
-      { include: '@whitespace' },
-      { include: '@numbers' },
-      { include: '@strings' },
-      { include: '@complexIdentifiers' },
-      [/[;,.]/, 'delimiter'],
-      [/[({})]/, '@brackets'],
-			[/[a-z_][a-zA-Z0-9_]*/,
-							  { cases: { '@keywords': 'keyword'
-							           , '@functions': 'keyword'
-							           , '@default': 'identifier' }
-							  }
-],
-      [/[<>=!%&+\-*/|~^]/, 'operator'],
-    ],
-    whitespace: [
-      [/\s+/, 'white']
-    ],
-    comments: [
-      [/\/\/+.*/, 'comment'],
-      [/\/\*/, { token: 'comment.quote', next: '@comment' }]
-    ],
-    comment: [
-      [/[^*/]+/, 'comment'],
-      [/\*\//, { token: 'comment.quote', next: '@pop' }],
-      [/./, 'comment']
-    ],
-    numbers: [
-      [/0[xX][0-9a-fA-F]*/, 'number'],
-      [/[$][+-]*\d*(\.\d*)?/, 'number'],
-      [/((\d+(\.\d*)?)|(\.\d+))([eE][\-+]?\d+)?/, 'number']
-    ],
-    strings: [
-      [/N"/, { token: 'string', next: '@string' }],
-      [/"/, { token: 'string', next: '@string' }]
-    ],
-    string: [
-      [/[^"]+/, 'string'],
-      [/""/, 'string'],
-      [/"/, { token: 'string', next: '@pop' }]
-    ],
-    complexIdentifiers: [
-      [/\[/, { token: 'identifier.quote', next: '@bracketedIdentifier' }],
-      [/'/, { token: 'identifier.quote', next: '@quotedIdentifier' }]
-    ],
-    bracketedIdentifier: [
-      [/[^\]]+/, 'identifier'],
-      [/]]/, 'identifier'],
-      [/]/, { token: 'identifier.quote', next: '@pop' }]
-    ],
-    quotedIdentifier: [
-      [/[^']+/, 'identifier'],
-      [/''/, 'identifier'],
-      [/'/, { token: 'identifier.quote', next: '@pop' }]
-    ]
-  }
+	],
+	functions: [
+		// Relational
+		'CLOSINGBALANCEMONTH', 'CLOSINGBALANCEQUARTER', 'CLOSINGBALANCEYEAR', 'DATEADD', 'DATESBETWEEN',
+		'DATESINPERIOD', 'DATESMTD', 'DATESQTD', 'DATESYTD', 'ENDOFMONTH',
+		'ENDOFQUARTER', 'ENDOFYEAR', 'FIRSTDATE', 'FIRSTNONBLANK', 'LASTDATE',
+		'LASTNONBLANK', 'NEXTDAY', 'NEXTMONTH', 'NEXTQUARTER', 'NEXTYEAR',
+		'OPENINGBALANCEMONTH', 'OPENINGBALANCEQUARTER', 'OPENINGBALANCEYEAR', 'PARALLELPERIOD', 'PREVIOUSDAY',
+		'PREVIOUSMONTH', 'PREVIOUSQUARTER', 'PREVIOUSYEAR', 'SAMEPERIODLASTYEAR', 'STARTOFMONTH',
+		'STARTOFQUARTER', 'STARTOFYEAR', 'TOTALMTD', 'TOTALQTD', 'TOTALYTD',
+		'ADDCOLUMNS', 'ADDMISSINGITEMS', 'ALL', 'ALLEXCEPT', 'ALLNOBLANKROW',
+		'ALLSELECTED', 'CALCULATE', 'CALCULATETABLE', 'CALENDAR', 'CALENDARAUTO',
+		'CROSSFILTER', 'CROSSJOIN', 'CURRENTGROUP', 'DATATABLE', 'DETAILROWS',
+		'DISTINCT', 'EARLIER', 'EARLIEST', 'EXCEPT', 'FILTER',
+		'FILTERS', 'GENERATE', 'GENERATEALL', 'GROUPBY', 'IGNORE',
+		'INTERSECT', 'ISONORAFTER', 'KEEPFILTERS', 'LOOKUPVALUE', 'NATURALINNERJOIN',
+		'NATURALLEFTOUTERJOIN', 'RELATED', 'RELATEDTABLE', 'ROLLUP', 'ROLLUPADDISSUBTOTAL',
+		'ROLLUPGROUP', 'ROLLUPISSUBTOTAL', 'ROW', 'SAMPLE', 'SELECTCOLUMNS',
+		'SUBSTITUTEWITHINDEX', 'SUMMARIZE', 'SUMMARIZECOLUMNS', 'TOPN', 'TREATAS',
+		'UNION', 'USERELATIONSHIP', 'VALUES', 'SUM', 'SUMX',
+		'PATH', 'PATHCONTAINS', 'PATHITEM', 'PATHITEMREVERSE', 'PATHLENGTH',
+		'AVERAGE', 'AVERAGEA', 'AVERAGEX', 'COUNT', 'COUNTA',
+		'COUNTAX', 'COUNTBLANK', 'COUNTROWS', 'COUNTX', 'DISTINCTCOUNT',
+		'DIVIDE', 'GEOMEAN', 'GEOMEANX', 'MAX', 'MAXA',
+		'MAXX', 'MEDIAN', 'MEDIANX', 'MIN', 'MINA',
+		'MINX', 'PERCENTILE.EXC', 'PERCENTILE.INC', 'PERCENTILEX.EXC', 'PERCENTILEX.INC',
+		'PRODUCT', 'PRODUCTX', 'RANK.EQ', 'RANKX', 'STDEV.P',
+		'STDEV.S', 'STDEVX.P', 'STDEVX.S', 'VAR.P', 'VAR.S',
+		'VARX.P', 'VARX.S', 'XIRR', 'XNPV',
+		// Scalar
+		'DATE', 'DATEDIFF', 'DATEVALUE', 'DAY', 'EDATE',
+		'EOMONTH', 'HOUR', 'MINUTE', 'MONTH', 'NOW',
+		'SECOND', 'TIME', 'TIMEVALUE', 'TODAY', 'WEEKDAY',
+		'WEEKNUM', 'YEAR', 'YEARFRAC', 'CONTAINS', 'CONTAINSROW',
+		'CUSTOMDATA', 'ERROR', 'HASONEFILTER', 'HASONEVALUE', 'ISBLANK',
+		'ISCROSSFILTERED', 'ISEMPTY', 'ISERROR', 'ISEVEN', 'ISFILTERED',
+		'ISLOGICAL', 'ISNONTEXT', 'ISNUMBER', 'ISODD', 'ISSUBTOTAL',
+		'ISTEXT', 'USERNAME', 'USERPRINCIPALNAME', 'AND', 'FALSE',
+		'IF', 'IFERROR', 'NOT', 'OR', 'SWITCH',
+		'TRUE', 'ABS', 'ACOS', 'ACOSH', 'ACOT',
+		'ACOTH', 'ASIN', 'ASINH', 'ATAN', 'ATANH',
+		'BETA.DIST', 'BETA.INV', 'CEILING', 'CHISQ.DIST', 'CHISQ.DIST.RT',
+		'CHISQ.INV', 'CHISQ.INV.RT', 'COMBIN', 'COMBINA', 'CONFIDENCE.NORM',
+		'CONFIDENCE.T', 'COS', 'COSH', 'COT', 'COTH',
+		'CURRENCY', 'DEGREES', 'EVEN', 'EXP', 'EXPON.DIST',
+		'FACT', 'FLOOR', 'GCD', 'INT', 'ISO.CEILING',
+		'LCM', 'LN', 'LOG', 'LOG10', 'MOD',
+		'MROUND', 'ODD', 'PERMUT', 'PI', 'POISSON.DIST',
+		'POWER', 'QUOTIENT', 'RADIANS', 'RAND', 'RANDBETWEEN',
+		'ROUND', 'ROUNDDOWN', 'ROUNDUP', 'SIGN', 'SIN',
+		'SINH', 'SQRT', 'SQRTPI', 'TAN', 'TANH',
+		'TRUNC', 'BLANK', 'CONCATENATE', 'CONCATENATEX', 'EXACT',
+		'FIND', 'FIXED', 'FORMAT', 'LEFT', 'LEN',
+		'LOWER', 'MID', 'REPLACE', 'REPT', 'RIGHT',
+		'SEARCH', 'SUBSTITUTE', 'TRIM', 'UNICHAR', 'UNICODE',
+		'UPPER', 'VALUE'
+	],
+	tokenizer: {
+		root: [
+			{ include: '@comments' },
+			{ include: '@whitespace' },
+			{ include: '@numbers' },
+			{ include: '@strings' },
+			{ include: '@complexIdentifiers' },
+			[/[;,.]/, 'delimiter'],
+			[/[({})]/, '@brackets'],
+			[/[a-z_][a-zA-Z0-9_]*/, {
+				cases: {
+					'@keywords': 'keyword',
+					'@functions': 'keyword',
+					'@default': 'identifier'
+				}
+			}],
+			[/[<>=!%&+\-*/|~^]/, 'operator'],
+		],
+		whitespace: [
+			[/\s+/, 'white']
+		],
+		comments: [
+			[/\/\/+.*/, 'comment'],
+			[/\/\*/, { token: 'comment.quote', next: '@comment' }]
+		],
+		comment: [
+			[/[^*/]+/, 'comment'],
+			[/\*\//, { token: 'comment.quote', next: '@pop' }],
+			[/./, 'comment']
+		],
+		numbers: [
+			[/0[xX][0-9a-fA-F]*/, 'number'],
+			[/[$][+-]*\d*(\.\d*)?/, 'number'],
+			[/((\d+(\.\d*)?)|(\.\d+))([eE][\-+]?\d+)?/, 'number']
+		],
+		strings: [
+			[/N"/, { token: 'string', next: '@string' }],
+			[/"/, { token: 'string', next: '@string' }]
+		],
+		string: [
+			[/[^"]+/, 'string'],
+			[/""/, 'string'],
+			[/"/, { token: 'string', next: '@pop' }]
+		],
+		complexIdentifiers: [
+			[/\[/, { token: 'identifier.quote', next: '@bracketedIdentifier' }],
+			[/'/, { token: 'identifier.quote', next: '@quotedIdentifier' }]
+		],
+		bracketedIdentifier: [
+			[/[^\]]+/, 'identifier'],
+			[/]]/, 'identifier'],
+			[/]/, { token: 'identifier.quote', next: '@pop' }]
+		],
+		quotedIdentifier: [
+			[/[^']+/, 'identifier'],
+			[/''/, 'identifier'],
+			[/'/, { token: 'identifier.quote', next: '@pop' }]
+		]
+	}
 };

+ 50 - 43
src/objective-c.ts

@@ -8,15 +8,15 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '//',
 		blockComment: ['/*', '*/'],
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')']
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -34,7 +34,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.objective-c',
 
@@ -150,7 +150,7 @@ export var language = <ILanguage> {
 	decimal: /0|@decpart/,
 
 	tokenizer: {
-	root: [
+		root: [
 			{ include: '@comments' },
 			{ include: '@whitespace' },
 			{ include: '@numbers' },
@@ -159,53 +159,60 @@ export var language = <ILanguage> {
 			[/[,:;]/, 'delimiter'],
 			[/[{}\[\]()<>]/, '@brackets'],
 
-			[/[a-zA-Z@#]\w*/, { cases: { '@keywords': 'keyword',
-										'@default': 'identifier' } }],
+			[/[a-zA-Z@#]\w*/, {
+				cases: {
+					'@keywords': 'keyword',
+					'@default': 'identifier'
+				}
+			}],
 
 			[/[<>=\\+\\-\\*\\/\\^\\|\\~,]|and\\b|or\\b|not\\b]/, 'operator'],
-	],
+		],
 
-	whitespace: [
-		[/\s+/, 'white'],
-	],
+		whitespace: [
+			[/\s+/, 'white'],
+		],
 
-	comments: [
-			['\\/\\*','comment','@comment' ],
-			['\\/\\/+.*','comment' ],
+		comments: [
+			['\\/\\*', 'comment', '@comment'],
+			['\\/\\/+.*', 'comment'],
 		],
 
-	comment: [
-			['\\*\\/','comment','@pop' ],
-			['.', 'comment', ],
+		comment: [
+			['\\*\\/', 'comment', '@pop'],
+			['.', 'comment',],
 		],
 
-	numbers: [
+		numbers: [
 			[/0[xX][0-9a-fA-F]*(_?[0-9a-fA-F])*/, 'number.hex'],
 			[/@decimal((\.@decpart)?([eE][\-+]?@decpart)?)[fF]*/, {
-				cases: {  	'(\\d)*': 'number',
-							'$0':'number.float' }} ]
+				cases: {
+					'(\\d)*': 'number',
+					'$0': 'number.float'
+				}
+			}]
 		],
 
-	// Recognize strings, including those broken across lines with \ (but not without)
-	strings: [
-		[/'$/, 'string.escape', '@popall'],
-		[/'/, 'string.escape', '@stringBody'],
-		[/"$/, 'string.escape', '@popall'],
-		[/"/, 'string.escape', '@dblStringBody']
-	],
-	stringBody: [
-		[/\\./, 'string'],
-		[/'/, 'string.escape', '@popall'],
-		[/.(?=.*')/, 'string'],
-		[/.*\\$/, 'string'],
-		[/.*$/, 'string', '@popall']
-	],
-	dblStringBody: [
-		[/\\./, 'string'],
-		[/"/, 'string.escape', '@popall'],
-		[/.(?=.*")/, 'string'],
-		[/.*\\$/, 'string'],
-		[/.*$/, 'string', '@popall']
-	]
+		// Recognize strings, including those broken across lines with \ (but not without)
+		strings: [
+			[/'$/, 'string.escape', '@popall'],
+			[/'/, 'string.escape', '@stringBody'],
+			[/"$/, 'string.escape', '@popall'],
+			[/"/, 'string.escape', '@dblStringBody']
+		],
+		stringBody: [
+			[/\\./, 'string'],
+			[/'/, 'string.escape', '@popall'],
+			[/.(?=.*')/, 'string'],
+			[/.*\\$/, 'string'],
+			[/.*$/, 'string', '@popall']
+		],
+		dblStringBody: [
+			[/\\./, 'string'],
+			[/"/, 'string.escape', '@popall'],
+			[/.(?=.*")/, 'string'],
+			[/.*\\$/, 'string'],
+			[/.*$/, 'string', '@popall']
+		]
 	}
-};
+};

+ 37 - 37
src/php.ts

@@ -8,7 +8,7 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
 
 	comments: {
@@ -41,7 +41,7 @@ export const htmlTokenTypes = {
 	}
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '',
 	// ignoreCase: true,
@@ -53,9 +53,9 @@ export var language = <ILanguage> {
 			[/<!DOCTYPE/, 'metatag.html', '@doctype'],
 			[/<!--/, 'comment.html', '@comment'],
 			[/(<)(\w+)(\/>)/, [htmlTokenTypes.DELIM_START, 'tag.html', htmlTokenTypes.DELIM_END]],
-			[/(<)(script)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@script'} ]],
-			[/(<)(style)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@style'} ]],
-			[/(<)([:\w]+)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@otherTag'} ]],
+			[/(<)(script)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@script' }]],
+			[/(<)(style)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@style' }]],
+			[/(<)([:\w]+)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@otherTag' }]],
 			[/(<\/)(\w+)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@otherTag' }]],
 			[/</, htmlTokenTypes.DELIM_START],
 			[/[^<]+/] // text
@@ -63,8 +63,8 @@ export var language = <ILanguage> {
 
 		doctype: [
 			[/<\?((php)|=)?/, { token: '@rematch', switchTo: '@phpInSimpleState.comment' }],
-			[/[^>]+/, 'metatag.content.html' ],
-			[/>/, 'metatag.html', '@pop' ],
+			[/[^>]+/, 'metatag.content.html'],
+			[/>/, 'metatag.html', '@pop'],
 		],
 
 		comment: [
@@ -94,15 +94,15 @@ export var language = <ILanguage> {
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
 			[/=/, 'delimiter'],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.text/javascript', nextEmbedded: 'text/javascript'} ],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.text/javascript', nextEmbedded: 'text/javascript' }],
 			[/[ \t\r\n]+/], // whitespace
-			[/(<\/)(script\s*)(>)/, [ htmlTokenTypes.DELIM_START, 'tag.html', { token: htmlTokenTypes.DELIM_END, next: '@pop' } ]]
+			[/(<\/)(script\s*)(>)/, [htmlTokenTypes.DELIM_START, 'tag.html', { token: htmlTokenTypes.DELIM_END, next: '@pop' }]]
 		],
 
 		// After <script ... type
 		scriptAfterType: [
 			[/<\?((php)|=)?/, { token: '@rematch', switchTo: '@phpInSimpleState.scriptAfterType' }],
-			[/=/,'delimiter', '@scriptAfterTypeEquals'],
+			[/=/, 'delimiter', '@scriptAfterTypeEquals'],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
 		],
@@ -110,8 +110,8 @@ export var language = <ILanguage> {
 		// After <script ... type =
 		scriptAfterTypeEquals: [
 			[/<\?((php)|=)?/, { token: '@rematch', switchTo: '@phpInSimpleState.scriptAfterTypeEquals' }],
-			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' } ],
-			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' } ],
+			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' }],
+			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' }],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
 		],
@@ -119,7 +119,7 @@ export var language = <ILanguage> {
 		// After <script ... type = $S2
 		scriptWithCustomType: [
 			[/<\?((php)|=)?/, { token: '@rematch', switchTo: '@phpInSimpleState.scriptWithCustomType.$S2' }],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.$S2', nextEmbedded: '$S2'}],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.$S2', nextEmbedded: '$S2' }],
 			[/"([^"]*)"/, 'attribute.value'],
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
@@ -146,15 +146,15 @@ export var language = <ILanguage> {
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
 			[/=/, 'delimiter'],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.text/css', nextEmbedded: 'text/css'} ],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.text/css', nextEmbedded: 'text/css' }],
 			[/[ \t\r\n]+/], // whitespace
-			[/(<\/)(style\s*)(>)/, [htmlTokenTypes.DELIM_START, 'tag.html', { token: htmlTokenTypes.DELIM_END, next: '@pop' } ]]
+			[/(<\/)(style\s*)(>)/, [htmlTokenTypes.DELIM_START, 'tag.html', { token: htmlTokenTypes.DELIM_END, next: '@pop' }]]
 		],
 
 		// After <style ... type
 		styleAfterType: [
 			[/<\?((php)|=)?/, { token: '@rematch', switchTo: '@phpInSimpleState.styleAfterType' }],
-			[/=/,'delimiter', '@styleAfterTypeEquals'],
+			[/=/, 'delimiter', '@styleAfterTypeEquals'],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
 		],
@@ -162,8 +162,8 @@ export var language = <ILanguage> {
 		// After <style ... type =
 		styleAfterTypeEquals: [
 			[/<\?((php)|=)?/, { token: '@rematch', switchTo: '@phpInSimpleState.styleAfterTypeEquals' }],
-			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' } ],
-			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' } ],
+			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' }],
+			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' }],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
 		],
@@ -171,7 +171,7 @@ export var language = <ILanguage> {
 		// After <style ... type = $S2
 		styleWithCustomType: [
 			[/<\?((php)|=)?/, { token: '@rematch', switchTo: '@phpInSimpleState.styleWithCustomType.$S2' }],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.$S2', nextEmbedded: '$S2'}],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.$S2', nextEmbedded: '$S2' }],
 			[/"([^"]*)"/, 'attribute.value'],
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
@@ -203,22 +203,22 @@ export var language = <ILanguage> {
 		phpRoot: [
 			[/[a-zA-Z_]\w*/, {
 				cases: {
-					'@phpKeywords': { token:'keyword.php' },
-					'@phpCompileTimeConstants': { token: 'constant.php'},
+					'@phpKeywords': { token: 'keyword.php' },
+					'@phpCompileTimeConstants': { token: 'constant.php' },
 					'@default': 'identifier.php'
 				}
 			}],
 			[/[$a-zA-Z_]\w*/, {
 				cases: {
-					'@phpPreDefinedVariables': { token:'variable.predefined.php' },
+					'@phpPreDefinedVariables': { token: 'variable.predefined.php' },
 					'@default': 'variable.php'
 				}
 			}],
 
 			// brackets
-			[/[{}]/, 'delimiter.bracket.php' ],
-			[/[\[\]]/, 'delimiter.array.php' ],
-			[/[()]/, 'delimiter.parenthesis.php' ],
+			[/[{}]/, 'delimiter.bracket.php'],
+			[/[\[\]]/, 'delimiter.array.php'],
+			[/[()]/, 'delimiter.parenthesis.php'],
 
 			// whitespace
 			[/[ \t\r\n]+/],
@@ -228,14 +228,14 @@ export var language = <ILanguage> {
 			[/\/\//, 'comment.php', '@phpLineComment'],
 
 			// block comments
-			[/\/\*/, 'comment.php', '@phpComment' ],
+			[/\/\*/, 'comment.php', '@phpComment'],
 
 			// strings
-			[/"/, 'string.php', '@phpDoubleQuoteString' ],
-			[/'/, 'string.php', '@phpSingleQuoteString' ],
+			[/"/, 'string.php', '@phpDoubleQuoteString'],
+			[/'/, 'string.php', '@phpSingleQuoteString'],
 
 			// delimiters
-			[/[\+\-\*\%\&\|\^\~\!\=\<\>\/\?\;\:\.\,\@]/, 'delimiter.php' ],
+			[/[\+\-\*\%\&\|\^\~\!\=\<\>\/\?\;\:\.\,\@]/, 'delimiter.php'],
 
 			// numbers
 			[/\d*\d+[eE]([\-+]?\d+)?/, 'number.float.php'],
@@ -262,17 +262,17 @@ export var language = <ILanguage> {
 		],
 
 		phpDoubleQuoteString: [
-			[/[^\\"]+/,  'string.php'],
+			[/[^\\"]+/, 'string.php'],
 			[/@escapes/, 'string.escape.php'],
-			[/\\./,      'string.escape.invalid.php'],
-			[/"/,        'string.php', '@pop' ]
+			[/\\./, 'string.escape.invalid.php'],
+			[/"/, 'string.php', '@pop']
 		],
 
 		phpSingleQuoteString: [
-			[/[^\\']+/,  'string.php'],
+			[/[^\\']+/, 'string.php'],
 			[/@escapes/, 'string.escape.php'],
-			[/\\./,      'string.escape.invalid.php'],
-			[/'/,        'string.php', '@pop' ]
+			[/\\./, 'string.escape.invalid.php'],
+			[/'/, 'string.php', '@pop']
 		],
 	},
 
@@ -321,7 +321,7 @@ export var language = <ILanguage> {
 		'$argv'
 	],
 
-	escapes:  /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
+	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
 };
 
 // TESTED WITH
@@ -426,4 +426,4 @@ export var language = <ILanguage> {
 // ?>
 
 // </body>
-// </html>
+// </html>

+ 635 - 630
src/postiats.ts

@@ -10,12 +10,12 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '//',
 		blockComment: ['(*', '*)'],
 	},
-	brackets: [['{','}'], ['[',']'], ['(',')'], ['<','>']],
+	brackets: [['{', '}'], ['[', ']'], ['(', ')'], ['<', '>']],
 	autoClosingPairs: [
 		{ open: '"', close: '"', notIn: ['string', 'comment'] },
 		{ open: '{', close: '}', notIn: ['string', 'comment'] },
@@ -24,633 +24,638 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
-  tokenPostfix: '.pats',
-
-  // TODO: staload and dynload are followed by a special kind of string literals
-  // with {$IDENTIFER} variables, and it also may make sense to highlight
-  // the punctuation (. and / and \) differently.
-
-  // Set defaultToken to invalid to see what you do not tokenize yet
-  defaultToken: 'invalid',
-
-  // keyword reference: https://github.com/githwxi/ATS-Postiats/blob/master/src/pats_lexing_token.dats
-
-  keywords: [
-//
-    "abstype", // ABSTYPE
-    "abst0ype", // ABST0YPE
-    "absprop", // ABSPROP
-    "absview", // ABSVIEW
-    "absvtype", // ABSVIEWTYPE
-    "absviewtype", // ABSVIEWTYPE
-    "absvt0ype", // ABSVIEWT0YPE
-    "absviewt0ype", // ABSVIEWT0YPE
-//
-    "as", // T_AS
-//
-    "and", // T_AND
-//
-    "assume", // T_ASSUME
-//
-    "begin", // T_BEGIN
-//
-/*
-    "case", // CASE
-*/
-//
-    "classdec", // T_CLASSDEC
-//
-    "datasort", // T_DATASORT
-//
-    "datatype", // DATATYPE
-    "dataprop", // DATAPROP
-    "dataview", // DATAVIEW
-    "datavtype", // DATAVIEWTYPE
-    "dataviewtype", // DATAVIEWTYPE
-//
-    "do", // T_DO
-//
-    "end", // T_END
-//
-    "extern", // T_EXTERN
-    "extype", // T_EXTYPE
-    "extvar", // T_EXTVAR
-//
-    "exception", // T_EXCEPTION
-//
-    "fn", // FN // non-recursive
-    "fnx", // FNX // mutual tail-rec.
-    "fun", // FUN // general-recursive
-//
-    "prfn", // PRFN
-    "prfun", // PRFUN
-//
-    "praxi", // PRAXI
-    "castfn", // CASTFN
-//
-    "if", // T_IF
-    "then", // T_THEN
-    "else", // T_ELSE
-//
-    "ifcase", // T_IFCASE
-//
-    "in", // T_IN
-//
-    "infix", // INFIX
-    "infixl", // INFIXL
-    "infixr", // INFIXR
-    "prefix", // PREFIX
-    "postfix", // POSTFIX
-//
-    "implmnt", // IMPLMNT // 0
-    "implement", // IMPLEMENT // 1
-//
-    "primplmnt", // PRIMPLMNT // ~1
-    "primplement", // PRIMPLMNT // ~1
-//
-    "import", // T_IMPORT // for importing packages
-//
-/*
-    "lam", // LAM
-    "llam", // LLAM
-    "fix", // FIX
-*/
-//
-    "let", // T_LET
-//
-    "local", // T_LOCAL
-//
-    "macdef", // MACDEF
-    "macrodef", // MACRODEF
-//
-    "nonfix", // T_NONFIX
-//
-    "symelim", // T_SYMELIM
-    "symintr", // T_SYMINTR
-    "overload", // T_OVERLOAD
-//
-    "of", // T_OF
-    "op", // T_OP
-//
-    "rec", // T_REC
-//
-    "sif", // T_SIF
-    "scase", // T_SCASE
-//
-    "sortdef", // T_SORTDEF
-/*
-// HX: [sta] is now deprecated
-*/
-    "sta", // T_STACST
-    "stacst", // T_STACST
-    "stadef", // T_STADEF
-    "static", // T_STATIC
-/*
-    "stavar", // T_STAVAR
-*/
-//
-    "staload", // T_STALOAD
-    "dynload", // T_DYNLOAD
-//
-    "try", // T_TRY
-//
-    "tkindef", // T_TKINDEF // HX-2012-05-23
-//
-/*
-    "type", // TYPE
-*/
-    "typedef", // TYPEDEF
-    "propdef", // PROPDEF
-    "viewdef", // VIEWDEF
-    "vtypedef", // VIEWTYPEDEF
-    "viewtypedef", // VIEWTYPEDEF
-//
-/*
-    "val", // VAL
-*/
-    "prval", // PRVAL
-//
-    "var", // VAR
-    "prvar", // PRVAR
-//
-    "when", // T_WHEN
-    "where", // T_WHERE
-//
-/*
-    "for", // T_FOR
-    "while", // T_WHILE
-*/
-//
-    "with", // T_WITH
-//
-    "withtype", // WITHTYPE
-    "withprop", // WITHPROP
-    "withview", // WITHVIEW
-    "withvtype", // WITHVIEWTYPE
-    "withviewtype", // WITHVIEWTYPE
-//
-  ],
-  keywords_dlr: [
-    "$delay", // DLRDELAY
-    "$ldelay", // DLRLDELAY
-//
-    "$arrpsz", // T_DLRARRPSZ
-    "$arrptrsize", // T_DLRARRPSZ
-//
-    "$d2ctype", // T_DLRD2CTYPE
-//
-    "$effmask", // DLREFFMASK
-    "$effmask_ntm", // DLREFFMASK_NTM
-    "$effmask_exn", // DLREFFMASK_EXN
-    "$effmask_ref", // DLREFFMASK_REF
-    "$effmask_wrt", // DLREFFMASK_WRT
-    "$effmask_all", // DLREFFMASK_ALL
-//
-    "$extern", // T_DLREXTERN
-    "$extkind", // T_DLREXTKIND
-    "$extype", // T_DLREXTYPE
-    "$extype_struct", // T_DLREXTYPE_STRUCT
-//
-    "$extval", // T_DLREXTVAL
-    "$extfcall", // T_DLREXTFCALL
-    "$extmcall", // T_DLREXTMCALL
-//
-    "$literal", // T_DLRLITERAL
-//
-    "$myfilename", // T_DLRMYFILENAME
-    "$mylocation", // T_DLRMYLOCATION
-    "$myfunction", // T_DLRMYFUNCTION
-//
-    "$lst", // DLRLST
-    "$lst_t", // DLRLST_T
-    "$lst_vt", // DLRLST_VT
-    "$list", // DLRLST
-    "$list_t", // DLRLST_T
-    "$list_vt", // DLRLST_VT
-//
-    "$rec", // DLRREC
-    "$rec_t", // DLRREC_T
-    "$rec_vt", // DLRREC_VT
-    "$record", // DLRREC
-    "$record_t", // DLRREC_T
-    "$record_vt", // DLRREC_VT
-//
-    "$tup", // DLRTUP
-    "$tup_t", // DLRTUP_T
-    "$tup_vt", // DLRTUP_VT
-    "$tuple", // DLRTUP
-    "$tuple_t", // DLRTUP_T
-    "$tuple_vt", // DLRTUP_VT
-//
-    "$break", // T_DLRBREAK
-    "$continue", // T_DLRCONTINUE
-//
-    "$raise", // T_DLRRAISE
-//
-    "$showtype", // T_DLRSHOWTYPE
-//
-    "$vcopyenv_v", // DLRVCOPYENV_V
-    "$vcopyenv_vt", // DLRVCOPYENV_VT
-//
-    "$tempenver", // T_DLRTEMPENVER
-//
-    "$solver_assert", // T_DLRSOLASSERT
-    "$solver_verify", // T_DLRSOLVERIFY
-  ],
-  keywords_srp: [
-//
-    "#if", // T_SRPIF
-    "#ifdef", // T_SRPIFDEF
-    "#ifndef", // T_SRPIFNDEF
-//
-    "#then", // T_SRPTHEN
-//
-    "#elif", // T_SRPELIF
-    "#elifdef", // T_SRPELIFDEF
-    "#elifndef", // T_SRPELIFNDEF
-//
-    "#else", // T_SRPELSE
-    "#endif", // T_SRPENDIF
-//
-    "#error", // T_SRPERROR
-//
-    "#prerr", // T_SRPPRERR // outpui to stderr
-    "#print", // T_SRPPRINT // output to stdout
-//
-    "#assert", // T_SRPASSERT
-//
-    "#undef", // T_SRPUNDEF
-    "#define", // T_SRPDEFINE
-//
-    "#include", // T_SRPINCLUDE
-    "#require", // T_SRPREQUIRE
-//
-    "#pragma", // T_SRPPRAGMA // HX: general pragma
-    "#codegen2", // T_SRPCODEGEN2 // for level-2 codegen
-    "#codegen3", // T_SRPCODEGEN3 // for level-3 codegen
-//
-// HX: end of special tokens
-//
-  ],
-
-  irregular_keyword_list: [
-    "val+",
-    "val-",
-    "val",
-    "case+",
-    "case-",
-    "case",
-    "addr@",
-    "addr",
-    "fold@",
-    "free@",
-    "fix@",
-    "fix",
-    "lam@",
-    "lam",
-    "llam@",
-    "llam",
-    "viewt@ype+",
-    "viewt@ype-",
-    "viewt@ype",
-    "viewtype+",
-    "viewtype-",
-    "viewtype",
-    "view+",
-    "view-",
-    "view@",
-    "view",
-    "type+",
-    "type-",
-    "type",
-    "vtype+",
-    "vtype-",
-    "vtype",
-    "vt@ype+",
-    "vt@ype-",
-    "vt@ype",
-    "viewt@ype+",
-    "viewt@ype-",
-    "viewt@ype",
-    "viewtype+",
-    "viewtype-",
-    "viewtype",
-    "prop+",
-    "prop-",
-    "prop",
-    "type+",
-    "type-",
-    "type",
-    "t@ype",
-    "t@ype+",
-    "t@ype-",
-    "abst@ype",
-    "abstype",
-    "absviewt@ype",
-    "absvt@ype",
-    "for*",
-    "for",
-    "while*",
-    "while"
-  ],
-
-  keywords_types: [
-    'bool',
-    'double',
-    'byte',
-    'int',
-    'short',
-    'char',
-    'void',
-    'unit',
-    'long',
-    'float',
-    'string',
-    'strptr'
-  ],
-
-  // TODO: reference for this?
-  keywords_effects: [
-    "0",  // no effects
-    "fun",
-    "clo",
-    "prf",
-    "funclo",
-    "cloptr",
-    "cloref",
-    "ref",
-    "ntm",
-    "1" // all effects
-  ],
-
-  operators: [
-    "@", // T_AT
-    "!", // T_BANG
-    "|", // T_BAR
-    "`", // T_BQUOTE
-    ":", // T_COLON
-    "$", // T_DOLLAR
-    ".", // T_DOT
-    "=", // T_EQ
-    "#", // T_HASH
-    "~", // T_TILDE
-    //
-    "..", // T_DOTDOT
-    "...", // T_DOTDOTDOT
-//
-    "=>", // T_EQGT
-    // "=<", // T_EQLT
-    "=<>", // T_EQLTGT
-    "=/=>", // T_EQSLASHEQGT
-    "=>>", // T_EQGTGT
-    "=/=>>", // T_EQSLASHEQGTGT
-//
-    "<", // T_LT // opening a tmparg
-    ">", // T_GT // closing a tmparg
-//
-    "><", // T_GTLT
-//
-    ".<", // T_DOTLT
-    ">.", // T_GTDOT
-//
-    ".<>.", // T_DOTLTGTDOT
-//
-    "->", // T_MINUSGT
-    //"-<", // T_MINUSLT
-    "-<>", // T_MINUSLTGT
-//
-/*
-    ":<", // T_COLONLT
-*/
-  ],
-
-  brackets: [
-    {open: ',(', close: ')', token: 'delimiter.parenthesis'}, // meta-programming syntax
-    {open: '`(', close: ')', token: 'delimiter.parenthesis'},
-    {open: '%(', close: ')', token: 'delimiter.parenthesis'},
-    {open: '\'(', close: ')', token: 'delimiter.parenthesis'},
-    {open: '\'{', close: '}', token: 'delimiter.parenthesis'},
-    {open: '@(', close: ')', token: 'delimiter.parenthesis'},
-    {open: '@{', close: '}', token: 'delimiter.brace'},
-    {open: '@[', close: ']', token: 'delimiter.square'},
-    {open: '#[', close: ']', token: 'delimiter.square'},
-    {open: '{', close: '}', token: 'delimiter.curly'},
-    {open: '[', close: ']', token: 'delimiter.square'},
-    {open: '(', close: ')', token: 'delimiter.parenthesis'},
-    {open: '<', close: '>', token:'delimiter.angle'}
-  ],
-
-  // we include these common regular expressions
-  symbols:  /[=><!~?:&|+\-*\/\^%]+/,
-
-  IDENTFST: /[a-zA-Z_]/,
-  IDENTRST: /[a-zA-Z0-9_'$]/,
-  symbolic: /[%&+-./:=@~`^|*!$#?<>]/,
-  digit: /[0-9]/,
-  digitseq0: /@digit*/,
-  xdigit: /[0-9A-Za-z]/,
-  xdigitseq0: /@xdigit*/,
-  INTSP: /[lLuU]/,
-  FLOATSP: /[fFlL]/,
-  fexponent: /[eE][+-]?[0-9]+/,
-  fexponent_bin: /[pP][+-]?[0-9]+/,
-  deciexp: /\.[0-9]*@fexponent?/,
-  hexiexp: /\.[0-9a-zA-Z]*@fexponent_bin?/,
-  irregular_keywords: /val[+-]?|case[+-]?|addr\@?|fold\@|free\@|fix\@?|lam\@?|llam\@?|prop[+-]?|type[+-]?|view[+-@]?|viewt@?ype[+-]?|t@?ype[+-]?|v(iew)?t@?ype[+-]?|abst@?ype|absv(iew)?t@?ype|for\*?|while\*?/,
-  ESCHAR: /[ntvbrfa\\\?'"\(\[\{]/,
-
-  start: 'root',
-
-  // The main tokenizer for ATS/Postiats
-  // reference: https://github.com/githwxi/ATS-Postiats/blob/master/src/pats_lexing.dats
-  tokenizer: {
-    root: [
-      // lexing_blankseq0
-      {regex: /[ \t\r\n]+/, action: {token: ''}},
-
-      // NOTE: (*) is an invalid ML-like comment!
-      {regex: /\(\*\)/, action: { token: 'invalid' }},
-      {regex: /\(\*/, action: { token: 'comment', next: 'lexing_COMMENT_block_ml' } },
-      {regex: /\(/, action: '@brackets'/*{ token: 'delimiter.parenthesis' }*/ },
-      {regex: /\)/, action: '@brackets'/*{ token: 'delimiter.parenthesis' }*/ },
-      {regex: /\[/, action: '@brackets'/*{ token: 'delimiter.bracket' }*/ },
-      {regex: /\]/, action: '@brackets'/*{ token: 'delimiter.bracket' }*/ },
-      {regex: /\{/, action: '@brackets'/*{ token: 'delimiter.brace' }*/ },
-      {regex: /\}/, action: '@brackets'/*{ token: 'delimiter.brace' }*/ },
-
-      // lexing_COMMA
-      {regex: /,\(/, action: '@brackets'/*{ token: 'delimiter.parenthesis' }*/ }, // meta-programming syntax
-      {regex: /,/, action: { token: 'delimiter.comma' } },
-
-      {regex: /;/, action: { token: 'delimiter.semicolon' } },
-
-      // lexing_AT
-      {regex: /@\(/, action: '@brackets'/* { token: 'delimiter.parenthesis' }*/ },
-      {regex: /@\[/, action: '@brackets'/* { token: 'delimiter.bracket' }*/ },
-      {regex: /@\{/, action: '@brackets'/*{ token: 'delimiter.brace' }*/ },
-
-      // lexing_COLON
-      {regex: /:</, action: { token: 'keyword', next: '@lexing_EFFECT_commaseq0'} }, // T_COLONLT
-
-      /*
-      lexing_DOT:
-
-      . // SYMBOLIC => lexing_IDENT_sym
-      . FLOATDOT => lexing_FLOAT_deciexp
-      . DIGIT => T_DOTINT
-      */
-      {regex: /\.@symbolic+/, action: { token: 'identifier.sym' } },
-      // FLOATDOT case
-      {regex: /\.@digit*@fexponent@FLOATSP*/, action: { token: 'number.float' } },
-      {regex: /\.@digit+/, action: { token: 'number.float' } }, // T_DOTINT
-
-      // lexing_DOLLAR:
-      // '$' IDENTFST IDENTRST* => lexing_IDENT_dlr, _ => lexing_IDENT_sym
-      {regex: /\$@IDENTFST@IDENTRST*/,
-        action: {
-          cases: {
-           '@keywords_dlr': { token: 'keyword.dlr' },
-           '@default': { token: 'namespace' }, // most likely a module qualifier
-          }
-        }
-      },
-      // lexing_SHARP:
-      // '#' IDENTFST IDENTRST* => lexing_ident_srp, _ => lexing_IDENT_sym
-      {regex: /\#@IDENTFST@IDENTRST*/,
-        action: {
-            cases: {
-              '@keywords_srp': { token: 'keyword.srp' },
-              '@default': { token: 'identifier' },
-            }
-        }
-      },
-
-      // lexing_PERCENT:
-      {regex: /%\(/, action: { token: 'delimiter.parenthesis' } },
-      {regex: /^%{(#|\^|\$)?/, action: { token: 'keyword', next: '@lexing_EXTCODE', nextEmbedded: 'text/javascript' } },
-      {regex: /^%}/, action: { token: 'keyword' } },
-
-      // lexing_QUOTE
-      {regex: /'\(/, action: { token: 'delimiter.parenthesis' } },
-      {regex: /'\[/, action: { token: 'delimiter.bracket' } },
-      {regex: /'\{/, action: { token: 'delimiter.brace' } },
-      [/(')(\\@ESCHAR|\\[xX]@xdigit+|\\@digit+)(')/, ['string', 'string.escape', 'string']],
-      [/'[^\\']'/, 'string'],
-
-      // lexing_DQUOTE
-      [/"/, 'string.quote', '@lexing_DQUOTE'],
-
-      // lexing_BQUOTE
-      {regex: /`\(/, action: '@brackets'/* { token: 'delimiter.parenthesis' }*/},
-      // TODO: otherwise, try lexing_IDENT_sym
-
-      {regex: /\\/, action: { token: 'punctuation' } }, // just T_BACKSLASH
-
-      // lexing_IDENT_alp:
-      // NOTE: (?!regex) is syntax for "not-followed-by" regex
-      // to resolve ambiguity such as foreach$fwork being incorrectly lexed as [for] [each$fwork]!
-      {regex: /@irregular_keywords(?!@IDENTRST)/, action: { token: 'keyword' } },
-      {regex: /@IDENTFST@IDENTRST*[<!\[]?/,
-        action: {
-          cases: {
-            // TODO: dynload and staload should be specially parsed
-            // dynload whitespace+ "special_string"
-            // this special string is really:
-            //  '/' '\\' '.' => punctuation
-            // ({\$)([a-zA-Z_][a-zA-Z_0-9]*)(}) => punctuation,keyword,punctuation
-            // [^"] => identifier/literal
-            '@keywords': { token: 'keyword' },
-            '@keywords_types': { token: 'type' },
-            '@default': { token: 'identifier' }
-          }
-        }
-      },
-      // lexing_IDENT_sym:
-      {regex: /\/\/\/\//, action: { token: 'comment', next: '@lexing_COMMENT_rest' }},
-      {regex: /\/\/.*$/, action: { token: 'comment' }},
-      {regex: /\/\*/, action: { token: 'comment', next: '@lexing_COMMENT_block_c' }},
-      // AS-20160627: specifically for effect annotations
-      {regex: /-<|=</, action: { token: 'keyword', next: '@lexing_EFFECT_commaseq0'}},
-      {regex: /@symbolic+/,
-        action: {
-          cases: {
-            '@operators': 'keyword',
-            '@default': 'operator'
-          }
-        }
-      },
-
-      // lexing_ZERO:
-      // FIXME: this one is quite messy/unfinished yet
-      // TODO: lexing_INT_hex
-      // - testing_hexiexp => lexing_FLOAT_hexiexp
-      // - testing_fexponent_bin => lexing_FLOAT_hexiexp
-      // - testing_intspseq0 => T_INT_hex
-
-      // lexing_INT_hex:
-      {regex: /0[xX]@xdigit+(@hexiexp|@fexponent_bin)@FLOATSP*/, action: { token: 'number.float' } },
-      {regex: /0[xX]@xdigit+@INTSP*/, action: {token: 'number.hex' } },
-      {regex: /0[0-7]+(?![0-9])@INTSP*/, action: { token: 'number.octal' } }, // lexing_INT_oct
-      //{regex: /0/, action: { token: 'number' } }, // INTZERO
-
-      // lexing_INT_dec:
-      // - testing_deciexp => lexing_FLOAT_deciexp
-      // - testing_fexponent => lexing_FLOAT_deciexp
-      // - otherwise => intspseq0 ([0-9]*[lLuU]?)
-      {regex: /@digit+(@fexponent|@deciexp)@FLOATSP*/, action: { token: 'number.float' } },
-      {regex: /@digit@digitseq0@INTSP*/, action: { token: 'number.decimal' } },
-      // DIGIT, if followed by digitseq0, is lexing_INT_dec
-      {regex: /@digit+@INTSP*/, action: { token: 'number' } },
-
-    ],
-
-    lexing_COMMENT_block_ml: [
-      [/[^\(\*]+/, 'comment'],
-      [/\(\*/, 'comment', '@push' ],
-      [/\(\*/, 'comment.invalid' ],
-      [/\*\)/, 'comment', '@pop' ],
-      [/\*/, 'comment']
-    ],
-    lexing_COMMENT_block_c: [
-      [/[^\/*]+/, 'comment' ],
-      // [/\/\*/, 'comment', '@push' ],    // nested C-style block comments not allowed
-      // [/\/\*/,    'comment.invalid' ],	// NOTE: this breaks block comments in the shape of /* //*/
-      [/\*\//,    'comment', '@pop'  ],
-      [/[\/*]/,   'comment' ]
-    ],
-    lexing_COMMENT_rest: [
-      [/$/, 'comment', '@pop'], // FIXME: does it match? docs say 'no'
-      [/.*/, 'comment']
-    ],
-
-    // NOTE: added by AS, specifically for highlighting
-    lexing_EFFECT_commaseq0: [
-      {regex: /@IDENTFST@IDENTRST+|@digit+/,
-        action: {
-          cases: {
-            '@keywords_effects': {token: 'type.effect'},
-            '@default': {token: 'identifier'}
-          }
-        }
-      },
-      {regex: /,/, action: {token: 'punctuation'}},
-      {regex: />/, action: { token: '@rematch', next: '@pop' }},
-    ],
-
-    lexing_EXTCODE: [
-      {regex: /^%}/, action: { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }},
-      {regex: /[^%]+/, action: ''},
-    ],
-
-    lexing_DQUOTE: [
-      {regex: /"/, action: { token: 'string.quote', next: '@pop' }},
-      // AS-20160628: additional hi-lighting for variables in staload/dynload strings
-      {regex: /(\{\$)(@IDENTFST@IDENTRST*)(\})/, action: [{token: 'string.escape'},{ token: 'identifier' },{token: 'string.escape'}]},
-      {regex: /\\$/, action: { token: 'string.escape' }},
-      {regex: /\\(@ESCHAR|[xX]@xdigit+|@digit+)/, action: { token: 'string.escape' }},
-      {regex: /[^\\"]+/, action: {token: 'string' }}
-    ],
-  },
+export var language = <ILanguage>{
+	tokenPostfix: '.pats',
+
+	// TODO: staload and dynload are followed by a special kind of string literals
+	// with {$IDENTIFER} variables, and it also may make sense to highlight
+	// the punctuation (. and / and \) differently.
+
+	// Set defaultToken to invalid to see what you do not tokenize yet
+	defaultToken: 'invalid',
+
+	// keyword reference: https://github.com/githwxi/ATS-Postiats/blob/master/src/pats_lexing_token.dats
+
+	keywords: [
+		//
+		"abstype", // ABSTYPE
+		"abst0ype", // ABST0YPE
+		"absprop", // ABSPROP
+		"absview", // ABSVIEW
+		"absvtype", // ABSVIEWTYPE
+		"absviewtype", // ABSVIEWTYPE
+		"absvt0ype", // ABSVIEWT0YPE
+		"absviewt0ype", // ABSVIEWT0YPE
+		//
+		"as", // T_AS
+		//
+		"and", // T_AND
+		//
+		"assume", // T_ASSUME
+		//
+		"begin", // T_BEGIN
+		//
+		/*
+				"case", // CASE
+		*/
+		//
+		"classdec", // T_CLASSDEC
+		//
+		"datasort", // T_DATASORT
+		//
+		"datatype", // DATATYPE
+		"dataprop", // DATAPROP
+		"dataview", // DATAVIEW
+		"datavtype", // DATAVIEWTYPE
+		"dataviewtype", // DATAVIEWTYPE
+		//
+		"do", // T_DO
+		//
+		"end", // T_END
+		//
+		"extern", // T_EXTERN
+		"extype", // T_EXTYPE
+		"extvar", // T_EXTVAR
+		//
+		"exception", // T_EXCEPTION
+		//
+		"fn", // FN // non-recursive
+		"fnx", // FNX // mutual tail-rec.
+		"fun", // FUN // general-recursive
+		//
+		"prfn", // PRFN
+		"prfun", // PRFUN
+		//
+		"praxi", // PRAXI
+		"castfn", // CASTFN
+		//
+		"if", // T_IF
+		"then", // T_THEN
+		"else", // T_ELSE
+		//
+		"ifcase", // T_IFCASE
+		//
+		"in", // T_IN
+		//
+		"infix", // INFIX
+		"infixl", // INFIXL
+		"infixr", // INFIXR
+		"prefix", // PREFIX
+		"postfix", // POSTFIX
+		//
+		"implmnt", // IMPLMNT // 0
+		"implement", // IMPLEMENT // 1
+		//
+		"primplmnt", // PRIMPLMNT // ~1
+		"primplement", // PRIMPLMNT // ~1
+		//
+		"import", // T_IMPORT // for importing packages
+		//
+		/*
+				"lam", // LAM
+				"llam", // LLAM
+				"fix", // FIX
+		*/
+		//
+		"let", // T_LET
+		//
+		"local", // T_LOCAL
+		//
+		"macdef", // MACDEF
+		"macrodef", // MACRODEF
+		//
+		"nonfix", // T_NONFIX
+		//
+		"symelim", // T_SYMELIM
+		"symintr", // T_SYMINTR
+		"overload", // T_OVERLOAD
+		//
+		"of", // T_OF
+		"op", // T_OP
+		//
+		"rec", // T_REC
+		//
+		"sif", // T_SIF
+		"scase", // T_SCASE
+		//
+		"sortdef", // T_SORTDEF
+		/*
+		// HX: [sta] is now deprecated
+		*/
+		"sta", // T_STACST
+		"stacst", // T_STACST
+		"stadef", // T_STADEF
+		"static", // T_STATIC
+		/*
+				"stavar", // T_STAVAR
+		*/
+		//
+		"staload", // T_STALOAD
+		"dynload", // T_DYNLOAD
+		//
+		"try", // T_TRY
+		//
+		"tkindef", // T_TKINDEF // HX-2012-05-23
+		//
+		/*
+				"type", // TYPE
+		*/
+		"typedef", // TYPEDEF
+		"propdef", // PROPDEF
+		"viewdef", // VIEWDEF
+		"vtypedef", // VIEWTYPEDEF
+		"viewtypedef", // VIEWTYPEDEF
+		//
+		/*
+				"val", // VAL
+		*/
+		"prval", // PRVAL
+		//
+		"var", // VAR
+		"prvar", // PRVAR
+		//
+		"when", // T_WHEN
+		"where", // T_WHERE
+		//
+		/*
+				"for", // T_FOR
+				"while", // T_WHILE
+		*/
+		//
+		"with", // T_WITH
+		//
+		"withtype", // WITHTYPE
+		"withprop", // WITHPROP
+		"withview", // WITHVIEW
+		"withvtype", // WITHVIEWTYPE
+		"withviewtype", // WITHVIEWTYPE
+		//
+	],
+	keywords_dlr: [
+		"$delay", // DLRDELAY
+		"$ldelay", // DLRLDELAY
+		//
+		"$arrpsz", // T_DLRARRPSZ
+		"$arrptrsize", // T_DLRARRPSZ
+		//
+		"$d2ctype", // T_DLRD2CTYPE
+		//
+		"$effmask", // DLREFFMASK
+		"$effmask_ntm", // DLREFFMASK_NTM
+		"$effmask_exn", // DLREFFMASK_EXN
+		"$effmask_ref", // DLREFFMASK_REF
+		"$effmask_wrt", // DLREFFMASK_WRT
+		"$effmask_all", // DLREFFMASK_ALL
+		//
+		"$extern", // T_DLREXTERN
+		"$extkind", // T_DLREXTKIND
+		"$extype", // T_DLREXTYPE
+		"$extype_struct", // T_DLREXTYPE_STRUCT
+		//
+		"$extval", // T_DLREXTVAL
+		"$extfcall", // T_DLREXTFCALL
+		"$extmcall", // T_DLREXTMCALL
+		//
+		"$literal", // T_DLRLITERAL
+		//
+		"$myfilename", // T_DLRMYFILENAME
+		"$mylocation", // T_DLRMYLOCATION
+		"$myfunction", // T_DLRMYFUNCTION
+		//
+		"$lst", // DLRLST
+		"$lst_t", // DLRLST_T
+		"$lst_vt", // DLRLST_VT
+		"$list", // DLRLST
+		"$list_t", // DLRLST_T
+		"$list_vt", // DLRLST_VT
+		//
+		"$rec", // DLRREC
+		"$rec_t", // DLRREC_T
+		"$rec_vt", // DLRREC_VT
+		"$record", // DLRREC
+		"$record_t", // DLRREC_T
+		"$record_vt", // DLRREC_VT
+		//
+		"$tup", // DLRTUP
+		"$tup_t", // DLRTUP_T
+		"$tup_vt", // DLRTUP_VT
+		"$tuple", // DLRTUP
+		"$tuple_t", // DLRTUP_T
+		"$tuple_vt", // DLRTUP_VT
+		//
+		"$break", // T_DLRBREAK
+		"$continue", // T_DLRCONTINUE
+		//
+		"$raise", // T_DLRRAISE
+		//
+		"$showtype", // T_DLRSHOWTYPE
+		//
+		"$vcopyenv_v", // DLRVCOPYENV_V
+		"$vcopyenv_vt", // DLRVCOPYENV_VT
+		//
+		"$tempenver", // T_DLRTEMPENVER
+		//
+		"$solver_assert", // T_DLRSOLASSERT
+		"$solver_verify", // T_DLRSOLVERIFY
+	],
+	keywords_srp: [
+		//
+		"#if", // T_SRPIF
+		"#ifdef", // T_SRPIFDEF
+		"#ifndef", // T_SRPIFNDEF
+		//
+		"#then", // T_SRPTHEN
+		//
+		"#elif", // T_SRPELIF
+		"#elifdef", // T_SRPELIFDEF
+		"#elifndef", // T_SRPELIFNDEF
+		//
+		"#else", // T_SRPELSE
+		"#endif", // T_SRPENDIF
+		//
+		"#error", // T_SRPERROR
+		//
+		"#prerr", // T_SRPPRERR // outpui to stderr
+		"#print", // T_SRPPRINT // output to stdout
+		//
+		"#assert", // T_SRPASSERT
+		//
+		"#undef", // T_SRPUNDEF
+		"#define", // T_SRPDEFINE
+		//
+		"#include", // T_SRPINCLUDE
+		"#require", // T_SRPREQUIRE
+		//
+		"#pragma", // T_SRPPRAGMA // HX: general pragma
+		"#codegen2", // T_SRPCODEGEN2 // for level-2 codegen
+		"#codegen3", // T_SRPCODEGEN3 // for level-3 codegen
+		//
+		// HX: end of special tokens
+		//
+	],
+
+	irregular_keyword_list: [
+		"val+",
+		"val-",
+		"val",
+		"case+",
+		"case-",
+		"case",
+		"addr@",
+		"addr",
+		"fold@",
+		"free@",
+		"fix@",
+		"fix",
+		"lam@",
+		"lam",
+		"llam@",
+		"llam",
+		"viewt@ype+",
+		"viewt@ype-",
+		"viewt@ype",
+		"viewtype+",
+		"viewtype-",
+		"viewtype",
+		"view+",
+		"view-",
+		"view@",
+		"view",
+		"type+",
+		"type-",
+		"type",
+		"vtype+",
+		"vtype-",
+		"vtype",
+		"vt@ype+",
+		"vt@ype-",
+		"vt@ype",
+		"viewt@ype+",
+		"viewt@ype-",
+		"viewt@ype",
+		"viewtype+",
+		"viewtype-",
+		"viewtype",
+		"prop+",
+		"prop-",
+		"prop",
+		"type+",
+		"type-",
+		"type",
+		"t@ype",
+		"t@ype+",
+		"t@ype-",
+		"abst@ype",
+		"abstype",
+		"absviewt@ype",
+		"absvt@ype",
+		"for*",
+		"for",
+		"while*",
+		"while"
+	],
+
+	keywords_types: [
+		'bool',
+		'double',
+		'byte',
+		'int',
+		'short',
+		'char',
+		'void',
+		'unit',
+		'long',
+		'float',
+		'string',
+		'strptr'
+	],
+
+	// TODO: reference for this?
+	keywords_effects: [
+		"0",  // no effects
+		"fun",
+		"clo",
+		"prf",
+		"funclo",
+		"cloptr",
+		"cloref",
+		"ref",
+		"ntm",
+		"1" // all effects
+	],
+
+	operators: [
+		"@", // T_AT
+		"!", // T_BANG
+		"|", // T_BAR
+		"`", // T_BQUOTE
+		":", // T_COLON
+		"$", // T_DOLLAR
+		".", // T_DOT
+		"=", // T_EQ
+		"#", // T_HASH
+		"~", // T_TILDE
+		//
+		"..", // T_DOTDOT
+		"...", // T_DOTDOTDOT
+		//
+		"=>", // T_EQGT
+		// "=<", // T_EQLT
+		"=<>", // T_EQLTGT
+		"=/=>", // T_EQSLASHEQGT
+		"=>>", // T_EQGTGT
+		"=/=>>", // T_EQSLASHEQGTGT
+		//
+		"<", // T_LT // opening a tmparg
+		">", // T_GT // closing a tmparg
+		//
+		"><", // T_GTLT
+		//
+		".<", // T_DOTLT
+		">.", // T_GTDOT
+		//
+		".<>.", // T_DOTLTGTDOT
+		//
+		"->", // T_MINUSGT
+		//"-<", // T_MINUSLT
+		"-<>", // T_MINUSLTGT
+		//
+		/*
+				":<", // T_COLONLT
+		*/
+	],
+
+	brackets: [
+		{ open: ',(', close: ')', token: 'delimiter.parenthesis' }, // meta-programming syntax
+		{ open: '`(', close: ')', token: 'delimiter.parenthesis' },
+		{ open: '%(', close: ')', token: 'delimiter.parenthesis' },
+		{ open: '\'(', close: ')', token: 'delimiter.parenthesis' },
+		{ open: '\'{', close: '}', token: 'delimiter.parenthesis' },
+		{ open: '@(', close: ')', token: 'delimiter.parenthesis' },
+		{ open: '@{', close: '}', token: 'delimiter.brace' },
+		{ open: '@[', close: ']', token: 'delimiter.square' },
+		{ open: '#[', close: ']', token: 'delimiter.square' },
+		{ open: '{', close: '}', token: 'delimiter.curly' },
+		{ open: '[', close: ']', token: 'delimiter.square' },
+		{ open: '(', close: ')', token: 'delimiter.parenthesis' },
+		{ open: '<', close: '>', token: 'delimiter.angle' }
+	],
+
+	// we include these common regular expressions
+	symbols: /[=><!~?:&|+\-*\/\^%]+/,
+
+	IDENTFST: /[a-zA-Z_]/,
+	IDENTRST: /[a-zA-Z0-9_'$]/,
+	symbolic: /[%&+-./:=@~`^|*!$#?<>]/,
+	digit: /[0-9]/,
+	digitseq0: /@digit*/,
+	xdigit: /[0-9A-Za-z]/,
+	xdigitseq0: /@xdigit*/,
+	INTSP: /[lLuU]/,
+	FLOATSP: /[fFlL]/,
+	fexponent: /[eE][+-]?[0-9]+/,
+	fexponent_bin: /[pP][+-]?[0-9]+/,
+	deciexp: /\.[0-9]*@fexponent?/,
+	hexiexp: /\.[0-9a-zA-Z]*@fexponent_bin?/,
+	irregular_keywords: /val[+-]?|case[+-]?|addr\@?|fold\@|free\@|fix\@?|lam\@?|llam\@?|prop[+-]?|type[+-]?|view[+-@]?|viewt@?ype[+-]?|t@?ype[+-]?|v(iew)?t@?ype[+-]?|abst@?ype|absv(iew)?t@?ype|for\*?|while\*?/,
+	ESCHAR: /[ntvbrfa\\\?'"\(\[\{]/,
+
+	start: 'root',
+
+	// The main tokenizer for ATS/Postiats
+	// reference: https://github.com/githwxi/ATS-Postiats/blob/master/src/pats_lexing.dats
+	tokenizer: {
+		root: [
+			// lexing_blankseq0
+			{ regex: /[ \t\r\n]+/, action: { token: '' } },
+
+			// NOTE: (*) is an invalid ML-like comment!
+			{ regex: /\(\*\)/, action: { token: 'invalid' } },
+			{ regex: /\(\*/, action: { token: 'comment', next: 'lexing_COMMENT_block_ml' } },
+			{ regex: /\(/, action: '@brackets'/*{ token: 'delimiter.parenthesis' }*/ },
+			{ regex: /\)/, action: '@brackets'/*{ token: 'delimiter.parenthesis' }*/ },
+			{ regex: /\[/, action: '@brackets'/*{ token: 'delimiter.bracket' }*/ },
+			{ regex: /\]/, action: '@brackets'/*{ token: 'delimiter.bracket' }*/ },
+			{ regex: /\{/, action: '@brackets'/*{ token: 'delimiter.brace' }*/ },
+			{ regex: /\}/, action: '@brackets'/*{ token: 'delimiter.brace' }*/ },
+
+			// lexing_COMMA
+			{ regex: /,\(/, action: '@brackets'/*{ token: 'delimiter.parenthesis' }*/ }, // meta-programming syntax
+			{ regex: /,/, action: { token: 'delimiter.comma' } },
+
+			{ regex: /;/, action: { token: 'delimiter.semicolon' } },
+
+			// lexing_AT
+			{ regex: /@\(/, action: '@brackets'/* { token: 'delimiter.parenthesis' }*/ },
+			{ regex: /@\[/, action: '@brackets'/* { token: 'delimiter.bracket' }*/ },
+			{ regex: /@\{/, action: '@brackets'/*{ token: 'delimiter.brace' }*/ },
+
+			// lexing_COLON
+			{ regex: /:</, action: { token: 'keyword', next: '@lexing_EFFECT_commaseq0' } }, // T_COLONLT
+
+			/*
+			lexing_DOT:
+
+			. // SYMBOLIC => lexing_IDENT_sym
+			. FLOATDOT => lexing_FLOAT_deciexp
+			. DIGIT => T_DOTINT
+			*/
+			{ regex: /\.@symbolic+/, action: { token: 'identifier.sym' } },
+			// FLOATDOT case
+			{ regex: /\.@digit*@fexponent@FLOATSP*/, action: { token: 'number.float' } },
+			{ regex: /\.@digit+/, action: { token: 'number.float' } }, // T_DOTINT
+
+			// lexing_DOLLAR:
+			// '$' IDENTFST IDENTRST* => lexing_IDENT_dlr, _ => lexing_IDENT_sym
+			{
+				regex: /\$@IDENTFST@IDENTRST*/,
+				action: {
+					cases: {
+						'@keywords_dlr': { token: 'keyword.dlr' },
+						'@default': { token: 'namespace' }, // most likely a module qualifier
+					}
+				}
+			},
+			// lexing_SHARP:
+			// '#' IDENTFST IDENTRST* => lexing_ident_srp, _ => lexing_IDENT_sym
+			{
+				regex: /\#@IDENTFST@IDENTRST*/,
+				action: {
+					cases: {
+						'@keywords_srp': { token: 'keyword.srp' },
+						'@default': { token: 'identifier' },
+					}
+				}
+			},
+
+			// lexing_PERCENT:
+			{ regex: /%\(/, action: { token: 'delimiter.parenthesis' } },
+			{ regex: /^%{(#|\^|\$)?/, action: { token: 'keyword', next: '@lexing_EXTCODE', nextEmbedded: 'text/javascript' } },
+			{ regex: /^%}/, action: { token: 'keyword' } },
+
+			// lexing_QUOTE
+			{ regex: /'\(/, action: { token: 'delimiter.parenthesis' } },
+			{ regex: /'\[/, action: { token: 'delimiter.bracket' } },
+			{ regex: /'\{/, action: { token: 'delimiter.brace' } },
+			[/(')(\\@ESCHAR|\\[xX]@xdigit+|\\@digit+)(')/, ['string', 'string.escape', 'string']],
+			[/'[^\\']'/, 'string'],
+
+			// lexing_DQUOTE
+			[/"/, 'string.quote', '@lexing_DQUOTE'],
+
+			// lexing_BQUOTE
+			{ regex: /`\(/, action: '@brackets'/* { token: 'delimiter.parenthesis' }*/ },
+			// TODO: otherwise, try lexing_IDENT_sym
+
+			{ regex: /\\/, action: { token: 'punctuation' } }, // just T_BACKSLASH
+
+			// lexing_IDENT_alp:
+			// NOTE: (?!regex) is syntax for "not-followed-by" regex
+			// to resolve ambiguity such as foreach$fwork being incorrectly lexed as [for] [each$fwork]!
+			{ regex: /@irregular_keywords(?!@IDENTRST)/, action: { token: 'keyword' } },
+			{
+				regex: /@IDENTFST@IDENTRST*[<!\[]?/,
+				action: {
+					cases: {
+						// TODO: dynload and staload should be specially parsed
+						// dynload whitespace+ "special_string"
+						// this special string is really:
+						//  '/' '\\' '.' => punctuation
+						// ({\$)([a-zA-Z_][a-zA-Z_0-9]*)(}) => punctuation,keyword,punctuation
+						// [^"] => identifier/literal
+						'@keywords': { token: 'keyword' },
+						'@keywords_types': { token: 'type' },
+						'@default': { token: 'identifier' }
+					}
+				}
+			},
+			// lexing_IDENT_sym:
+			{ regex: /\/\/\/\//, action: { token: 'comment', next: '@lexing_COMMENT_rest' } },
+			{ regex: /\/\/.*$/, action: { token: 'comment' } },
+			{ regex: /\/\*/, action: { token: 'comment', next: '@lexing_COMMENT_block_c' } },
+			// AS-20160627: specifically for effect annotations
+			{ regex: /-<|=</, action: { token: 'keyword', next: '@lexing_EFFECT_commaseq0' } },
+			{
+				regex: /@symbolic+/,
+				action: {
+					cases: {
+						'@operators': 'keyword',
+						'@default': 'operator'
+					}
+				}
+			},
+
+			// lexing_ZERO:
+			// FIXME: this one is quite messy/unfinished yet
+			// TODO: lexing_INT_hex
+			// - testing_hexiexp => lexing_FLOAT_hexiexp
+			// - testing_fexponent_bin => lexing_FLOAT_hexiexp
+			// - testing_intspseq0 => T_INT_hex
+
+			// lexing_INT_hex:
+			{ regex: /0[xX]@xdigit+(@hexiexp|@fexponent_bin)@FLOATSP*/, action: { token: 'number.float' } },
+			{ regex: /0[xX]@xdigit+@INTSP*/, action: { token: 'number.hex' } },
+			{ regex: /0[0-7]+(?![0-9])@INTSP*/, action: { token: 'number.octal' } }, // lexing_INT_oct
+			//{regex: /0/, action: { token: 'number' } }, // INTZERO
+
+			// lexing_INT_dec:
+			// - testing_deciexp => lexing_FLOAT_deciexp
+			// - testing_fexponent => lexing_FLOAT_deciexp
+			// - otherwise => intspseq0 ([0-9]*[lLuU]?)
+			{ regex: /@digit+(@fexponent|@deciexp)@FLOATSP*/, action: { token: 'number.float' } },
+			{ regex: /@digit@digitseq0@INTSP*/, action: { token: 'number.decimal' } },
+			// DIGIT, if followed by digitseq0, is lexing_INT_dec
+			{ regex: /@digit+@INTSP*/, action: { token: 'number' } },
+
+		],
+
+		lexing_COMMENT_block_ml: [
+			[/[^\(\*]+/, 'comment'],
+			[/\(\*/, 'comment', '@push'],
+			[/\(\*/, 'comment.invalid'],
+			[/\*\)/, 'comment', '@pop'],
+			[/\*/, 'comment']
+		],
+		lexing_COMMENT_block_c: [
+			[/[^\/*]+/, 'comment'],
+			// [/\/\*/, 'comment', '@push' ],    // nested C-style block comments not allowed
+			// [/\/\*/,    'comment.invalid' ],	// NOTE: this breaks block comments in the shape of /* //*/
+			[/\*\//, 'comment', '@pop'],
+			[/[\/*]/, 'comment']
+		],
+		lexing_COMMENT_rest: [
+			[/$/, 'comment', '@pop'], // FIXME: does it match? docs say 'no'
+			[/.*/, 'comment']
+		],
+
+		// NOTE: added by AS, specifically for highlighting
+		lexing_EFFECT_commaseq0: [
+			{
+				regex: /@IDENTFST@IDENTRST+|@digit+/,
+				action: {
+					cases: {
+						'@keywords_effects': { token: 'type.effect' },
+						'@default': { token: 'identifier' }
+					}
+				}
+			},
+			{ regex: /,/, action: { token: 'punctuation' } },
+			{ regex: />/, action: { token: '@rematch', next: '@pop' } },
+		],
+
+		lexing_EXTCODE: [
+			{ regex: /^%}/, action: { token: '@rematch', next: '@pop', nextEmbedded: '@pop' } },
+			{ regex: /[^%]+/, action: '' },
+		],
+
+		lexing_DQUOTE: [
+			{ regex: /"/, action: { token: 'string.quote', next: '@pop' } },
+			// AS-20160628: additional hi-lighting for variables in staload/dynload strings
+			{ regex: /(\{\$)(@IDENTFST@IDENTRST*)(\})/, action: [{ token: 'string.escape' }, { token: 'identifier' }, { token: 'string.escape' }] },
+			{ regex: /\\$/, action: { token: 'string.escape' } },
+			{ regex: /\\(@ESCHAR|[xX]@xdigit+|@digit+)/, action: { token: 'string.escape' } },
+			{ regex: /[^\\"]+/, action: { token: 'string' } }
+		],
+	},
 };
 

+ 84 - 26
src/powershell.ts

@@ -8,7 +8,7 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	// the default separators except `$-`
 	wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#%\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
 	comments: {
@@ -16,9 +16,9 @@ export var conf:IRichLanguageConfiguration = {
 		blockComment: ['<#', '#>'],
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')']
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -36,7 +36,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	ignoreCase: true,
 	tokenPostfix: '.ps1',
@@ -67,8 +67,12 @@ export var language = <ILanguage> {
 		root: [
 
 			// commands and keywords
-			[/[a-zA-Z_][\w-]*/, { cases: { '@keywords': {token:'keyword.$0'},
-											'@default': '' } }],
+			[/[a-zA-Z_][\w-]*/, {
+				cases: {
+					'@keywords': { token: 'keyword.$0' },
+					'@default': ''
+				}
+			}],
 
 			// whitespace
 			[/[ \t\r\n]+/, ''],
@@ -97,36 +101,90 @@ export var language = <ILanguage> {
 
 			// strings:
 			[/\@"/, 'string', '@herestring."'],
-			[/\@'/,  'string', '@herestring.\''],
-			[/"/,  { cases: { '@eos': 'string', '@default': {token:'string', next:'@string."'} }} ],
-			[/'/, { cases: { '@eos': 'string', '@default': {token:'string', next:'@string.\''} }} ],
+			[/\@'/, 'string', '@herestring.\''],
+			[/"/, {
+				cases: {
+					'@eos': 'string',
+					'@default': { token: 'string', next: '@string."' }
+				}
+			}],
+			[/'/, {
+				cases: {
+					'@eos': 'string',
+					'@default': { token: 'string', next: '@string.\'' }
+				}
+			}],
 		],
 
 		string: [
-			[/[^"'\$`]+/, { cases: { '@eos': {token:'string', next:'@popall'}, '@default': 'string' }}],
-			[/@escapes/, { cases: { '@eos': {token:'string.escape', next:'@popall'}, '@default': 'string.escape' }}],
-			[/`./, { cases: { '@eos': {token:'string.escape.invalid', next:'@popall'}, '@default': 'string.escape.invalid' }}],
-
-			[/\$[\w]+$/, { cases: { '$S2=="': { token: 'variable', next: '@popall' }, '@default': { token: 'string', next: '@popall' } } }],
-			[/\$[\w]+/, { cases: { '$S2=="': 'variable', '@default': 'string' }}],
-
-			[/["']/,     { cases: { '$#==$S2' : { token: 'string', next: '@pop' },
-									'@default': { cases: { '@eos': {token:'string', next:'@popall'}, '@default': 'string' }} }} ],
+			[/[^"'\$`]+/, {
+				cases: {
+					'@eos': { token: 'string', next: '@popall' },
+					'@default': 'string'
+				}
+			}],
+			[/@escapes/, {
+				cases: {
+					'@eos': { token: 'string.escape', next: '@popall' },
+					'@default': 'string.escape'
+				}
+			}],
+			[/`./, {
+				cases: {
+					'@eos': { token: 'string.escape.invalid', next: '@popall' },
+					'@default': 'string.escape.invalid'
+				}
+			}],
+
+			[/\$[\w]+$/, {
+				cases: {
+					'$S2=="': { token: 'variable', next: '@popall' },
+					'@default': { token: 'string', next: '@popall' }
+				}
+			}],
+			[/\$[\w]+/, {
+				cases: {
+					'$S2=="': 'variable',
+					'@default': 'string'
+				}
+			}],
+
+			[/["']/, {
+				cases: {
+					'$#==$S2': { token: 'string', next: '@pop' },
+					'@default': {
+						cases: {
+							'@eos': { token: 'string', next: '@popall' },
+							'@default': 'string'
+						}
+					}
+				}
+			}],
 		],
 
 		herestring: [
-			[/^\s*(["'])@/, { cases: { '$1==$S2': { token: 'string', next: '@pop' }, '@default': 'string' } }],
-			[/[^\$`]+/,'string' ],
+			[/^\s*(["'])@/, {
+				cases: {
+					'$1==$S2': { token: 'string', next: '@pop' },
+					'@default': 'string'
+				}
+			}],
+			[/[^\$`]+/, 'string'],
 			[/@escapes/, 'string.escape'],
 			[/`./, 'string.escape.invalid'],
-			[/\$[\w]+/, { cases: { '$S2=="': 'variable', '@default': 'string' } }],
+			[/\$[\w]+/, {
+				cases: {
+					'$S2=="': 'variable',
+					'@default': 'string'
+				}
+			}],
 		],
 
 		comment: [
-			[/[^#\.]+/, 'comment' ],
+			[/[^#\.]+/, 'comment'],
 			[/#>/, 'comment', '@pop'],
-			[/(\.)(@helpKeywords)(?!\w)/, { token: 'comment.keyword.$2' } ],
-			[/[\.#]/,   'comment' ]
+			[/(\.)(@helpKeywords)(?!\w)/, { token: 'comment.keyword.$2' }],
+			[/[\.#]/, 'comment']
 		],
 	},
-};
+};

+ 61 - 57
src/python.ts

@@ -8,15 +8,15 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '#',
 		blockComment: ['\'\'\'', '\'\'\''],
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')']
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -34,7 +34,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.python',
 
@@ -178,7 +178,7 @@ export var language = <ILanguage> {
 	],
 
 	tokenizer: {
-	root: [
+		root: [
 			{ include: '@whitespace' },
 			{ include: '@numbers' },
 			{ include: '@strings' },
@@ -187,55 +187,59 @@ export var language = <ILanguage> {
 			[/[{}\[\]()]/, '@brackets'],
 
 			[/@[a-zA-Z]\w*/, 'tag'],
-			[/[a-zA-Z]\w*/, { cases: { '@keywords': 'keyword',
-										'@default': 'identifier' } }]
-	],
-
-	// Deal with white space, including single and multi-line comments
-	whitespace: [
-		[/\s+/, 'white'],
-		[/(^#.*$)/, 'comment'],
-		[/('''.*''')|(""".*""")/, 'string'],
-		[/'''.*$/, 'string', '@endDocString'],
-		[/""".*$/, 'string', '@endDblDocString']
-	],
-	endDocString: [
-		[/\\'/, 'string'],
-		[/.*'''/, 'string', '@popall'],
-		[/.*$/, 'string']
-	],
-	endDblDocString: [
-		[/\\"/, 'string'],
-		[/.*"""/, 'string', '@popall'],
-		[/.*$/, 'string']
-	],
-
-	// Recognize hex, negatives, decimals, imaginaries, longs, and scientific notation
-	numbers: [
-		[/-?0x([abcdef]|[ABCDEF]|\d)+[lL]?/, 'number.hex'],
-		[/-?(\d*\.)?\d+([eE][+\-]?\d+)?[jJ]?[lL]?/, 'number']
-	],
-
-	// Recognize strings, including those broken across lines with \ (but not without)
-	strings: [
-		[/'$/, 'string.escape', '@popall'],
-		[/'/, 'string.escape', '@stringBody'],
-		[/"$/, 'string.escape', '@popall'],
-		[/"/, 'string.escape', '@dblStringBody']
-	],
-	stringBody: [
-		[/\\./, 'string'],
-		[/'/, 'string.escape', '@popall'],
-		[/.(?=.*')/, 'string'],
-		[/.*\\$/, 'string'],
-		[/.*$/, 'string', '@popall']
-	],
-	dblStringBody: [
-		[/\\./, 'string'],
-		[/"/, 'string.escape', '@popall'],
-		[/.(?=.*")/, 'string'],
-		[/.*\\$/, 'string'],
-		[/.*$/, 'string', '@popall']
-	]
+			[/[a-zA-Z]\w*/, {
+				cases: {
+					'@keywords': 'keyword',
+					'@default': 'identifier'
+				}
+			}]
+		],
+
+		// Deal with white space, including single and multi-line comments
+		whitespace: [
+			[/\s+/, 'white'],
+			[/(^#.*$)/, 'comment'],
+			[/('''.*''')|(""".*""")/, 'string'],
+			[/'''.*$/, 'string', '@endDocString'],
+			[/""".*$/, 'string', '@endDblDocString']
+		],
+		endDocString: [
+			[/\\'/, 'string'],
+			[/.*'''/, 'string', '@popall'],
+			[/.*$/, 'string']
+		],
+		endDblDocString: [
+			[/\\"/, 'string'],
+			[/.*"""/, 'string', '@popall'],
+			[/.*$/, 'string']
+		],
+
+		// Recognize hex, negatives, decimals, imaginaries, longs, and scientific notation
+		numbers: [
+			[/-?0x([abcdef]|[ABCDEF]|\d)+[lL]?/, 'number.hex'],
+			[/-?(\d*\.)?\d+([eE][+\-]?\d+)?[jJ]?[lL]?/, 'number']
+		],
+
+		// Recognize strings, including those broken across lines with \ (but not without)
+		strings: [
+			[/'$/, 'string.escape', '@popall'],
+			[/'/, 'string.escape', '@stringBody'],
+			[/"$/, 'string.escape', '@popall'],
+			[/"/, 'string.escape', '@dblStringBody']
+		],
+		stringBody: [
+			[/\\./, 'string'],
+			[/'/, 'string.escape', '@popall'],
+			[/.(?=.*')/, 'string'],
+			[/.*\\$/, 'string'],
+			[/.*$/, 'string', '@popall']
+		],
+		dblStringBody: [
+			[/\\./, 'string'],
+			[/"/, 'string.escape', '@popall'],
+			[/.(?=.*")/, 'string'],
+			[/.*\\$/, 'string'],
+			[/.*$/, 'string', '@popall']
+		]
 	}
-};
+};

+ 6 - 6
src/r.ts

@@ -8,14 +8,14 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '#'
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')']
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -31,7 +31,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.r',
 
@@ -236,4 +236,4 @@ export var language = <ILanguage> {
 			[/./, 'string'],
 		]
 	}
-};
+};

+ 31 - 31
src/razor.ts

@@ -11,9 +11,9 @@ import ILanguage = monaco.languages.IMonarchLanguage;
 // Allow for running under nodejs/requirejs in tests
 var _monaco: typeof monaco = (typeof monaco === 'undefined' ? (<any>self).monaco : monaco);
 
-const EMPTY_ELEMENTS:string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
+const EMPTY_ELEMENTS: string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,
 
 	comments: {
@@ -64,7 +64,7 @@ export const htmlTokenTypes = {
 	}
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '',
 	// ignoreCase: true,
@@ -77,9 +77,9 @@ export var language = <ILanguage> {
 			[/<!DOCTYPE/, 'metatag.html', '@doctype'],
 			[/<!--/, 'comment.html', '@comment'],
 			[/(<)(\w+)(\/>)/, [htmlTokenTypes.DELIM_START, 'tag.html', htmlTokenTypes.DELIM_END]],
-			[/(<)(script)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@script'} ]],
-			[/(<)(style)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@style'} ]],
-			[/(<)([:\w]+)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@otherTag'} ]],
+			[/(<)(script)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@script' }]],
+			[/(<)(style)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@style' }]],
+			[/(<)([:\w]+)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@otherTag' }]],
 			[/(<\/)(\w+)/, [htmlTokenTypes.DELIM_START, { token: 'tag.html', next: '@otherTag' }]],
 			[/</, htmlTokenTypes.DELIM_START],
 			[/[ \t\r\n]+/], // whitespace
@@ -88,8 +88,8 @@ export var language = <ILanguage> {
 
 		doctype: [
 			[/@[^@]/, { token: '@rematch', switchTo: '@razorInSimpleState.comment' }],
-			[/[^>]+/, 'metatag.content.html' ],
-			[/>/, 'metatag.html', '@pop' ],
+			[/[^>]+/, 'metatag.content.html'],
+			[/>/, 'metatag.html', '@pop'],
 		],
 
 		comment: [
@@ -119,15 +119,15 @@ export var language = <ILanguage> {
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
 			[/=/, 'delimiter'],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.text/javascript', nextEmbedded: 'text/javascript'} ],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.text/javascript', nextEmbedded: 'text/javascript' }],
 			[/[ \t\r\n]+/], // whitespace
-			[/(<\/)(script\s*)(>)/, [ htmlTokenTypes.DELIM_START, 'tag.html', { token: htmlTokenTypes.DELIM_END, next: '@pop' } ]]
+			[/(<\/)(script\s*)(>)/, [htmlTokenTypes.DELIM_START, 'tag.html', { token: htmlTokenTypes.DELIM_END, next: '@pop' }]]
 		],
 
 		// After <script ... type
 		scriptAfterType: [
 			[/@[^@]/, { token: '@rematch', switchTo: '@razorInSimpleState.scriptAfterType' }],
-			[/=/,'delimiter', '@scriptAfterTypeEquals'],
+			[/=/, 'delimiter', '@scriptAfterTypeEquals'],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
 		],
@@ -135,8 +135,8 @@ export var language = <ILanguage> {
 		// After <script ... type =
 		scriptAfterTypeEquals: [
 			[/@[^@]/, { token: '@rematch', switchTo: '@razorInSimpleState.scriptAfterTypeEquals' }],
-			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' } ],
-			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' } ],
+			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' }],
+			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@scriptWithCustomType.$1' }],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
 		],
@@ -144,7 +144,7 @@ export var language = <ILanguage> {
 		// After <script ... type = $S2
 		scriptWithCustomType: [
 			[/@[^@]/, { token: '@rematch', switchTo: '@razorInSimpleState.scriptWithCustomType.$S2' }],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.$S2', nextEmbedded: '$S2'}],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@scriptEmbedded.$S2', nextEmbedded: '$S2' }],
 			[/"([^"]*)"/, 'attribute.value'],
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
@@ -171,15 +171,15 @@ export var language = <ILanguage> {
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
 			[/=/, 'delimiter'],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.text/css', nextEmbedded: 'text/css'} ],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.text/css', nextEmbedded: 'text/css' }],
 			[/[ \t\r\n]+/], // whitespace
-			[/(<\/)(style\s*)(>)/, [htmlTokenTypes.DELIM_START, 'tag.html', { token: htmlTokenTypes.DELIM_END, next: '@pop' } ]]
+			[/(<\/)(style\s*)(>)/, [htmlTokenTypes.DELIM_START, 'tag.html', { token: htmlTokenTypes.DELIM_END, next: '@pop' }]]
 		],
 
 		// After <style ... type
 		styleAfterType: [
 			[/@[^@]/, { token: '@rematch', switchTo: '@razorInSimpleState.styleAfterType' }],
-			[/=/,'delimiter', '@styleAfterTypeEquals'],
+			[/=/, 'delimiter', '@styleAfterTypeEquals'],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
 		],
@@ -187,8 +187,8 @@ export var language = <ILanguage> {
 		// After <style ... type =
 		styleAfterTypeEquals: [
 			[/@[^@]/, { token: '@rematch', switchTo: '@razorInSimpleState.styleAfterTypeEquals' }],
-			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' } ],
-			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' } ],
+			[/"([^"]*)"/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' }],
+			[/'([^']*)'/, { token: 'attribute.value', switchTo: '@styleWithCustomType.$1' }],
 			[/[ \t\r\n]+/], // whitespace
 			[/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
 		],
@@ -196,7 +196,7 @@ export var language = <ILanguage> {
 		// After <style ... type = $S2
 		styleWithCustomType: [
 			[/@[^@]/, { token: '@rematch', switchTo: '@razorInSimpleState.styleWithCustomType.$S2' }],
-			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.$S2', nextEmbedded: '$S2'}],
+			[/>/, { token: htmlTokenTypes.DELIM_END, next: '@styleEmbedded.$S2', nextEmbedded: '$S2' }],
 			[/"([^"]*)"/, 'attribute.value'],
 			[/'([^']*)'/, 'attribute.value'],
 			[/[\w\-]+/, 'attribute.name'],
@@ -216,7 +216,7 @@ export var language = <ILanguage> {
 		razorInSimpleState: [
 			[/@\*/, 'comment.cs', '@razorBlockCommentTopLevel'],
 			[/@[{(]/, 'metatag.cs', '@razorRootTopLevel'],
-			[/(@)(\s*[\w]+)/, ['metatag.cs', { token: 'identifier.cs', switchTo: '@$S2.$S3'} ]],
+			[/(@)(\s*[\w]+)/, ['metatag.cs', { token: 'identifier.cs', switchTo: '@$S2.$S3' }]],
 			[/[})]/, { token: 'metatag.cs', switchTo: '@$S2.$S3' }],
 			[/\*@/, { token: 'comment.cs', switchTo: '@$S2.$S3' }],
 		],
@@ -224,7 +224,7 @@ export var language = <ILanguage> {
 		razorInEmbeddedState: [
 			[/@\*/, 'comment.cs', '@razorBlockCommentTopLevel'],
 			[/@[{(]/, 'metatag.cs', '@razorRootTopLevel'],
-			[/(@)(\s*[\w]+)/, ['metatag.cs', { token: 'identifier.cs', switchTo: '@$S2.$S3', nextEmbedded: '$S3'} ]],
+			[/(@)(\s*[\w]+)/, ['metatag.cs', { token: 'identifier.cs', switchTo: '@$S2.$S3', nextEmbedded: '$S3' }]],
 			[/[})]/, { token: 'metatag.cs', switchTo: '@$S2.$S3', nextEmbedded: '$S3' }],
 			[/\*@/, { token: 'comment.cs', switchTo: '@$S2.$S3', nextEmbedded: '$S3' }],
 		],
@@ -242,30 +242,30 @@ export var language = <ILanguage> {
 		],
 
 		razorRootTopLevel: [
-			[/\{/, 'delimiter.bracket.cs', '@razorRoot'] ,
-			[/\(/, 'delimiter.parenthesis.cs', '@razorRoot'] ,
+			[/\{/, 'delimiter.bracket.cs', '@razorRoot'],
+			[/\(/, 'delimiter.parenthesis.cs', '@razorRoot'],
 			[/[})]/, '@rematch', '@pop'],
 			{ include: 'razorCommon' }
 		],
 
 		razorRoot: [
-			[/\{/, 'delimiter.bracket.cs', '@razorRoot'] ,
-			[/\(/, 'delimiter.parenthesis.cs', '@razorRoot'] ,
+			[/\{/, 'delimiter.bracket.cs', '@razorRoot'],
+			[/\(/, 'delimiter.parenthesis.cs', '@razorRoot'],
 			[/\}/, 'delimiter.bracket.cs', '@pop'],
 			[/\)/, 'delimiter.parenthesis.cs', '@pop'],
 			{ include: 'razorCommon' }
 		],
 
 		razorCommon: [
- 			[/[a-zA-Z_]\w*/, {
+			[/[a-zA-Z_]\w*/, {
 				cases: {
-					'@razorKeywords': { token:'keyword.cs' },
+					'@razorKeywords': { token: 'keyword.cs' },
 					'@default': 'identifier.cs'
 				}
 			}],
 
 			// brackets
-			[/[\[\]]/, 'delimiter.array.cs' ],
+			[/[\[\]]/, 'delimiter.array.cs'],
 
 			// whitespace
 			[/[ \t\r\n]+/],
@@ -275,7 +275,7 @@ export var language = <ILanguage> {
 			[/@\*/, 'comment.cs', '@razorBlockComment'],
 
 			// strings
- 			[/"([^"]*)"/, 'string.cs'],
+			[/"([^"]*)"/, 'string.cs'],
 			[/'([^']*)'/, 'string.cs'],
 
 			// simple html
@@ -284,7 +284,7 @@ export var language = <ILanguage> {
 			[/(<\/)(\w+)(>)/, [htmlTokenTypes.DELIM_START, 'tag.html', htmlTokenTypes.DELIM_END]],
 
 			// delimiters
-			[/[\+\-\*\%\&\|\^\~\!\=\<\>\/\?\;\:\.\,]/, 'delimiter.cs' ],
+			[/[\+\-\*\%\&\|\^\~\!\=\<\>\/\?\;\:\.\,]/, 'delimiter.cs'],
 
 			// numbers
 			[/\d*\d+[eE]([\-+]?\d+)?/, 'number.float.cs'],

+ 172 - 132
src/ruby.ts

@@ -8,15 +8,15 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '#',
 		blockComment: ['=begin', '=end'],
 	},
 	brackets: [
-		['(',')'],
-		['{','}'],
-		['[',']']
+		['(', ')'],
+		['{', '}'],
+		['[', ']']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -83,7 +83,7 @@ export var conf:IRichLanguageConfiguration = {
  * regular expression can also contain comments.
  */
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	tokenPostfix: '.ruby',
 
 	keywords: [
@@ -105,11 +105,11 @@ export var language = <ILanguage> {
 
 	// these are closed by 'end' (if, while and until are handled separately)
 	declarations: [
-		'module','class','def','case','do','begin','for','if','while','until','unless'
+		'module', 'class', 'def', 'case', 'do', 'begin', 'for', 'if', 'while', 'until', 'unless'
 	],
 
 	linedecls: [
-		'def','case','do','begin','for','if','while','until','unless'
+		'def', 'case', 'do', 'begin', 'for', 'if', 'while', 'until', 'unless'
 	],
 
 	operators: [
@@ -119,22 +119,22 @@ export var language = <ILanguage> {
 	],
 
 	brackets: [
-		{ open: '(', close: ')', token: 'delimiter.parenthesis'},
-		{ open: '{', close: '}', token: 'delimiter.curly'},
-		{ open: '[', close: ']', token: 'delimiter.square'}
+		{ open: '(', close: ')', token: 'delimiter.parenthesis' },
+		{ open: '{', close: '}', token: 'delimiter.curly' },
+		{ open: '[', close: ']', token: 'delimiter.square' }
 	],
 
 	// we include these common regular expressions
-	symbols:  /[=><!~?:&|+\-*\/\^%\.]+/,
+	symbols: /[=><!~?:&|+\-*\/\^%\.]+/,
 
 	// escape sequences
-	escape:  /(?:[abefnrstv\\"'\n\r]|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}|u[0-9A-Fa-f]{4})/,
+	escape: /(?:[abefnrstv\\"'\n\r]|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}|u[0-9A-Fa-f]{4})/,
 	escapes: /\\(?:C\-(@escape|.)|c(@escape|.)|@escape)/,
 
 	decpart: /\d(_?\d)*/,
 	decimal: /0|@decpart/,
 
-	delim:     /[^a-zA-Z0-9\s\n\r]/,
+	delim: /[^a-zA-Z0-9\s\n\r]/,
 	heredelim: /(?:\w+|'[^']*'|"[^"]*"|`[^`]*`)/,
 
 	regexpctl: /[(){}\[\]\$\^|\-*+?\.]/,
@@ -150,56 +150,68 @@ export var language = <ILanguage> {
 			// most complexity here is due to matching 'end' correctly with declarations.
 			// We distinguish a declaration that comes first on a line, versus declarations further on a line (which are most likey modifiers)
 			[/^(\s*)([a-z_]\w*[!?=]?)/, ['white',
-				{ cases: { 'for|until|while': { token: 'keyword.$2', next: '@dodecl.$2' },
-							'@declarations':   { token: 'keyword.$2', next: '@root.$2' },
-							'end': { token: 'keyword.$S2', next: '@pop' },
-							'@keywords': 'keyword',
-							'@builtins': 'predefined',
-							'@default': 'identifier' } }]],
+				{
+					cases: {
+						'for|until|while': { token: 'keyword.$2', next: '@dodecl.$2' },
+						'@declarations': { token: 'keyword.$2', next: '@root.$2' },
+						'end': { token: 'keyword.$S2', next: '@pop' },
+						'@keywords': 'keyword',
+						'@builtins': 'predefined',
+						'@default': 'identifier'
+					}
+				}]],
 			[/[a-z_]\w*[!?=]?/,
-				{ cases: { 'if|unless|while|until': { token: 'keyword.$0x', next: '@modifier.$0x' },
-							'for': { token: 'keyword.$2', next: '@dodecl.$2' },
-							'@linedecls': { token: 'keyword.$0', next: '@root.$0' },
-							'end': { token: 'keyword.$S2', next: '@pop' },
-							'@keywords': 'keyword',
-							'@builtins': 'predefined',
-							'@default': 'identifier' } }],
-
-			[/[A-Z][\w]*[!?=]?/, 'constructor.identifier' ],     // constant
-			[/\$[\w]*/,    'global.constant' ],               // global
-			[/@[\w]*/,     'namespace.instance.identifier' ], // instance
-			[/@@[\w]*/,    'namespace.class.identifier' ],    // class
+				{
+					cases: {
+						'if|unless|while|until': { token: 'keyword.$0x', next: '@modifier.$0x' },
+						'for': { token: 'keyword.$2', next: '@dodecl.$2' },
+						'@linedecls': { token: 'keyword.$0', next: '@root.$0' },
+						'end': { token: 'keyword.$S2', next: '@pop' },
+						'@keywords': 'keyword',
+						'@builtins': 'predefined',
+						'@default': 'identifier'
+					}
+				}],
+
+			[/[A-Z][\w]*[!?=]?/, 'constructor.identifier'],     // constant
+			[/\$[\w]*/, 'global.constant'],               // global
+			[/@[\w]*/, 'namespace.instance.identifier'], // instance
+			[/@@[\w]*/, 'namespace.class.identifier'],    // class
 
 			// here document
-			[/<<-(@heredelim).*/, { token: 'string.heredoc.delimiter', next: '@heredoc.$1' } ],
-			[/[ \t\r\n]+<<(@heredelim).*/, { token: 'string.heredoc.delimiter', next: '@heredoc.$1' } ],
-			[/^<<(@heredelim).*/, { token: 'string.heredoc.delimiter', next: '@heredoc.$1' } ],
+			[/<<-(@heredelim).*/, { token: 'string.heredoc.delimiter', next: '@heredoc.$1' }],
+			[/[ \t\r\n]+<<(@heredelim).*/, { token: 'string.heredoc.delimiter', next: '@heredoc.$1' }],
+			[/^<<(@heredelim).*/, { token: 'string.heredoc.delimiter', next: '@heredoc.$1' }],
 
 
 			// whitespace
 			{ include: '@whitespace' },
 
 			// strings
-			[/"/,  { token: 'string.d.delim', next: '@dstring.d."'} ],
-			[/'/,  { token: 'string.sq.delim', next: '@sstring.sq' } ],
+			[/"/, { token: 'string.d.delim', next: '@dstring.d."' }],
+			[/'/, { token: 'string.sq.delim', next: '@sstring.sq' }],
 
 			// % literals. For efficiency, rematch in the 'pstring' state
-			[/%([rsqxwW]|Q?)/,  { token: '@rematch', next: 'pstring' } ],
+			[/%([rsqxwW]|Q?)/, { token: '@rematch', next: 'pstring' }],
 
 			// commands and symbols
-			[/`/,  { token: 'string.x.delim', next: '@dstring.x.`' } ],
+			[/`/, { token: 'string.x.delim', next: '@dstring.x.`' }],
 			[/:(\w|[$@])\w*[!?=]?/, 'string.s'],
-			[/:"/, { token: 'string.s.delim', next: '@dstring.s."' } ],
-			[/:'/, { token: 'string.s.delim', next: '@sstring.s' } ],
+			[/:"/, { token: 'string.s.delim', next: '@dstring.s."' }],
+			[/:'/, { token: 'string.s.delim', next: '@sstring.s' }],
 
 			// regular expressions. Lookahead for a (not escaped) closing forwardslash on the same line
-			[/\/(?=(\\\/|[^\/\n])+\/)/, { token: 'regexp.delim', next: '@regexp' } ],
+			[/\/(?=(\\\/|[^\/\n])+\/)/, { token: 'regexp.delim', next: '@regexp' }],
 
 			// delimiters and operators
 			[/[{}()\[\]]/, '@brackets'],
-			[/@symbols/, { cases: { '@keywordops': 'keyword',
-									'@operators' : 'operator',
-									'@default'   : '' } } ],
+			[/@symbols/, {
+				cases: {
+					'@keywordops': 'keyword',
+					'@operators': 'operator',
+					'@default': ''
+				}
+			}],
 
 			[/[;,]/, 'delimiter'],
 
@@ -208,8 +220,12 @@ export var language = <ILanguage> {
 			[/0[_oO][0-7](_?[0-7])*/, 'number.octal'],
 			[/0[bB][01](_?[01])*/, 'number.binary'],
 			[/0[dD]@decpart/, 'number'],
-			[/@decimal((\.@decpart)?([eE][\-+]?@decpart)?)/, { cases: { '$1': 'number.float',
-																		'@default': 'number' }}],
+			[/@decimal((\.@decpart)?([eE][\-+]?@decpart)?)/, {
+				cases: {
+					'$1': 'number.float',
+					'@default': 'number'
+				}
+			}],
 
 		],
 
@@ -218,12 +234,16 @@ export var language = <ILanguage> {
 		// dodecl.<decl> where decl is the declarations started, like 'while'
 		dodecl: [
 			[/^/, { token: '', switchTo: '@root.$S2' }], // get out of do-skipping mode on a new line
-			[/[a-z_]\w*[!?=]?/, { cases: { 'end': { token: 'keyword.$S2', next: '@pop' }, // end on same line
-											'do' : { token: 'keyword', switchTo: '@root.$S2' }, // do on same line: not an open bracket here
-											'@linedecls': { token: '@rematch', switchTo: '@root.$S2' }, // other declaration on same line: rematch
-											'@keywords': 'keyword',
-											'@builtins': 'predefined',
-											'@default': 'identifier' } }],
+			[/[a-z_]\w*[!?=]?/, {
+				cases: {
+					'end': { token: 'keyword.$S2', next: '@pop' }, // end on same line
+					'do': { token: 'keyword', switchTo: '@root.$S2' }, // do on same line: not an open bracket here
+					'@linedecls': { token: '@rematch', switchTo: '@root.$S2' }, // other declaration on same line: rematch
+					'@keywords': 'keyword',
+					'@builtins': 'predefined',
+					'@default': 'identifier'
+				}
+			}],
 			{ include: '@root' }
 		],
 
@@ -232,22 +252,26 @@ export var language = <ILanguage> {
 		// modifier.<decl>x where decl is the declaration starter, like 'if'
 		modifier: [
 			[/^/, '', '@pop'], // it was a modifier: get out of modifier mode on a new line
-			[/[a-z_]\w*[!?=]?/, { cases: { 'end': { token: 'keyword.$S2', next: '@pop' }, // end on same line
-											'then|else|elsif|do': { token: 'keyword', switchTo: '@root.$S2' }, // real declaration and not a modifier
-											'@linedecls': { token: '@rematch', switchTo: '@root.$S2' }, // other declaration => not a modifier
-											'@keywords': 'keyword',
-											'@builtins': 'predefined',
-											'@default': 'identifier' } }],
+			[/[a-z_]\w*[!?=]?/, {
+				cases: {
+					'end': { token: 'keyword.$S2', next: '@pop' }, // end on same line
+					'then|else|elsif|do': { token: 'keyword', switchTo: '@root.$S2' }, // real declaration and not a modifier
+					'@linedecls': { token: '@rematch', switchTo: '@root.$S2' }, // other declaration => not a modifier
+					'@keywords': 'keyword',
+					'@builtins': 'predefined',
+					'@default': 'identifier'
+				}
+			}],
 			{ include: '@root' }
 		],
 
 		// single quote strings (also used for symbols)
 		// sstring.<kind>  where kind is 'sq' (single quote) or 's' (symbol)
 		sstring: [
-			[/[^\\']+/,      'string.$S2' ],
+			[/[^\\']+/, 'string.$S2'],
 			[/\\\\|\\'|\\$/, 'string.$S2.escape'],
-			[/\\./,          'string.$S2.invalid'],
-			[/'/,            { token: 'string.$S2.delim', next: '@pop'} ]
+			[/\\./, 'string.$S2.invalid'],
+			[/'/, { token: 'string.$S2.delim', next: '@pop' }]
 		],
 
 		// double quoted "string".
@@ -255,34 +279,42 @@ export var language = <ILanguage> {
 		// and delim is the ending delimiter (" or `)
 		dstring: [
 			[/[^\\`"#]+/, 'string.$S2'],
-			[/#/,         'string.$S2.escape', '@interpolated' ],
-			[/\\$/,       'string.$S2.escape' ],
-			[/@escapes/,  'string.$S2.escape'],
-			[/\\./,       'string.$S2.escape.invalid'],
-			[/[`"]/,      { cases: { '$#==$S3':  { token: 'string.$S2.delim', next: '@pop'},
-										'@default': 'string.$S2' } } ]
+			[/#/, 'string.$S2.escape', '@interpolated'],
+			[/\\$/, 'string.$S2.escape'],
+			[/@escapes/, 'string.$S2.escape'],
+			[/\\./, 'string.$S2.escape.invalid'],
+			[/[`"]/, {
+				cases: {
+					'$#==$S3': { token: 'string.$S2.delim', next: '@pop' },
+					'@default': 'string.$S2'
+				}
+			}]
 		],
 
 		// literal documents
 		// heredoc.<close> where close is the closing delimiter
 		heredoc: [
-			[/^(\s*)(@heredelim)$/, { cases: { '$2==$S2': ['string.heredoc', { token: 'string.heredoc.delimiter', next: '@pop' }],
-												'@default': ['string.heredoc','string.heredoc'] }}],
-			[/.*/, 'string.heredoc' ],
+			[/^(\s*)(@heredelim)$/, {
+				cases: {
+					'$2==$S2': ['string.heredoc', { token: 'string.heredoc.delimiter', next: '@pop' }],
+					'@default': ['string.heredoc', 'string.heredoc']
+				}
+			}],
+			[/.*/, 'string.heredoc'],
 		],
 
 		// interpolated sequence
 		interpolated: [
-			[/\$\w*/,      'global.constant', '@pop' ],
-			[/@\w*/,       'namespace.class.identifier', '@pop' ],
-			[/@@\w*/,      'namespace.instance.identifier', '@pop' ],
+			[/\$\w*/, 'global.constant', '@pop'],
+			[/@\w*/, 'namespace.class.identifier', '@pop'],
+			[/@@\w*/, 'namespace.instance.identifier', '@pop'],
 			[/[{]/, { token: 'string.escape.curly', switchTo: '@interpolated_compound' }],
-			['', '', '@pop' ], // just a # is interpreted as a #
+			['', '', '@pop'], // just a # is interpreted as a #
 		],
 
 		// any code
 		interpolated_compound: [
-			[/[}]/, { token: 'string.escape.curly', next: '@pop'} ],
+			[/[}]/, { token: 'string.escape.curly', next: '@pop' }],
 			{ include: '@root' },
 		],
 
@@ -293,72 +325,76 @@ export var language = <ILanguage> {
 			// turns out that you can quote using regex control characters, aargh!
 			// for example; %r|kgjgaj| is ok (even though | is used for alternation)
 			// so, we need to match those first
-			[/[^\(\{\[\\]/, { cases: { '$#==$S3' : { token: 'regexp.delim', next: '@pop' },
-										'$#==$S2' : { token: 'regexp.delim', next: '@push' }, // nested delimiters are allowed..
-										'~[)}\\]]' : '@brackets.regexp.escape.control',
-										'~@regexpctl': 'regexp.escape.control',
-										'@default': 'regexp' }}],
+			[/[^\(\{\[\\]/, {
+				cases: {
+					'$#==$S3': { token: 'regexp.delim', next: '@pop' },
+					'$#==$S2': { token: 'regexp.delim', next: '@push' }, // nested delimiters are allowed..
+					'~[)}\\]]': '@brackets.regexp.escape.control',
+					'~@regexpctl': 'regexp.escape.control',
+					'@default': 'regexp'
+				}
+			}],
 			{ include: '@regexcontrol' },
 		],
 
 		// We match regular expression quite precisely
 		regexp: [
-			{ include:   '@regexcontrol' },
-			[/[^\\\/]/,  'regexp' ],
-			['/[ixmp]*', { token: 'regexp.delim'}, '@pop' ],
+			{ include: '@regexcontrol' },
+			[/[^\\\/]/, 'regexp'],
+			['/[ixmp]*', { token: 'regexp.delim' }, '@pop'],
 		],
 
 		regexcontrol: [
-			[/(\{)(\d+(?:,\d*)?)(\})/, ['@brackets.regexp.escape.control', 'regexp.escape.control', '@brackets.regexp.escape.control'] ],
-			[/(\[)(\^?)/,     ['@brackets.regexp.escape.control',{ token: 'regexp.escape.control', next: '@regexrange'}]],
-			[/(\()(\?[:=!])/, ['@brackets.regexp.escape.control', 'regexp.escape.control'] ],
-			[/\(\?#/,         { token: 'regexp.escape.control', next: '@regexpcomment' }],
-			[/[()]/,        '@brackets.regexp.escape.control'],
-			[/@regexpctl/,  'regexp.escape.control'],
-			[/\\$/,         'regexp.escape' ],
-			[/@regexpesc/,  'regexp.escape' ],
-			[/\\\./,        'regexp.invalid' ],
-			[/#/,           'regexp.escape', '@interpolated' ],
+			[/(\{)(\d+(?:,\d*)?)(\})/, ['@brackets.regexp.escape.control', 'regexp.escape.control', '@brackets.regexp.escape.control']],
+			[/(\[)(\^?)/, ['@brackets.regexp.escape.control', { token: 'regexp.escape.control', next: '@regexrange' }]],
+			[/(\()(\?[:=!])/, ['@brackets.regexp.escape.control', 'regexp.escape.control']],
+			[/\(\?#/, { token: 'regexp.escape.control', next: '@regexpcomment' }],
+			[/[()]/, '@brackets.regexp.escape.control'],
+			[/@regexpctl/, 'regexp.escape.control'],
+			[/\\$/, 'regexp.escape'],
+			[/@regexpesc/, 'regexp.escape'],
+			[/\\\./, 'regexp.invalid'],
+			[/#/, 'regexp.escape', '@interpolated'],
 		],
 
 		regexrange: [
-			[/-/,     'regexp.escape.control'],
-			[/\^/,    'regexp.invalid'],
-			[/\\$/,   'regexp.escape' ],
+			[/-/, 'regexp.escape.control'],
+			[/\^/, 'regexp.invalid'],
+			[/\\$/, 'regexp.escape'],
 			[/@regexpesc/, 'regexp.escape'],
 			[/[^\]]/, 'regexp'],
-			[/\]/,    '@brackets.regexp.escape.control', '@pop'],
+			[/\]/, '@brackets.regexp.escape.control', '@pop'],
 		],
 
 		regexpcomment: [
-			[ /[^)]+/, 'comment' ],
-			[ /\)/, { token: 'regexp.escape.control', next: '@pop' } ]
+			[/[^)]+/, 'comment'],
+			[/\)/, { token: 'regexp.escape.control', next: '@pop' }]
 		],
 
 
 		// % quoted strings
 		// A bit repetitive since we need to often special case the kind of ending delimiter
 		pstring: [
-			[/%([qws])\(/,  { token: 'string.$1.delim', switchTo: '@qstring.$1.(.)' } ],
-			[/%([qws])\[/,  { token: 'string.$1.delim', switchTo: '@qstring.$1.[.]' } ],
-			[/%([qws])\{/,  { token: 'string.$1.delim', switchTo: '@qstring.$1.{.}' } ],
-			[/%([qws])</,   { token: 'string.$1.delim', switchTo: '@qstring.$1.<.>' } ],
-			[/%([qws])(@delim)/, { token: 'string.$1.delim', switchTo: '@qstring.$1.$2.$2' } ],
-
-			[/%r\(/,  { token: 'regexp.delim', switchTo: '@pregexp.(.)' } ],
-			[/%r\[/,  { token: 'regexp.delim', switchTo: '@pregexp.[.]' } ],
-			[/%r\{/,  { token: 'regexp.delim', switchTo: '@pregexp.{.}' } ],
-			[/%r</,   { token: 'regexp.delim', switchTo: '@pregexp.<.>' } ],
-			[/%r(@delim)/, { token: 'regexp.delim', switchTo: '@pregexp.$1.$1' } ],
-
-			[/%(x|W|Q?)\(/,  { token: 'string.$1.delim', switchTo: '@qqstring.$1.(.)' } ],
-			[/%(x|W|Q?)\[/,  { token: 'string.$1.delim', switchTo: '@qqstring.$1.[.]' } ],
-			[/%(x|W|Q?)\{/,  { token: 'string.$1.delim', switchTo: '@qqstring.$1.{.}' } ],
-			[/%(x|W|Q?)</,   { token: 'string.$1.delim', switchTo: '@qqstring.$1.<.>' } ],
-			[/%(x|W|Q?)(@delim)/, { token: 'string.$1.delim', switchTo: '@qqstring.$1.$2.$2' } ],
-
-			[/%([rqwsxW]|Q?)./, { token: 'invalid', next: '@pop' } ], // recover
-			[/./, { token: 'invalid', next: '@pop' } ], // recover
+			[/%([qws])\(/, { token: 'string.$1.delim', switchTo: '@qstring.$1.(.)' }],
+			[/%([qws])\[/, { token: 'string.$1.delim', switchTo: '@qstring.$1.[.]' }],
+			[/%([qws])\{/, { token: 'string.$1.delim', switchTo: '@qstring.$1.{.}' }],
+			[/%([qws])</, { token: 'string.$1.delim', switchTo: '@qstring.$1.<.>' }],
+			[/%([qws])(@delim)/, { token: 'string.$1.delim', switchTo: '@qstring.$1.$2.$2' }],
+
+			[/%r\(/, { token: 'regexp.delim', switchTo: '@pregexp.(.)' }],
+			[/%r\[/, { token: 'regexp.delim', switchTo: '@pregexp.[.]' }],
+			[/%r\{/, { token: 'regexp.delim', switchTo: '@pregexp.{.}' }],
+			[/%r</, { token: 'regexp.delim', switchTo: '@pregexp.<.>' }],
+			[/%r(@delim)/, { token: 'regexp.delim', switchTo: '@pregexp.$1.$1' }],
+
+			[/%(x|W|Q?)\(/, { token: 'string.$1.delim', switchTo: '@qqstring.$1.(.)' }],
+			[/%(x|W|Q?)\[/, { token: 'string.$1.delim', switchTo: '@qqstring.$1.[.]' }],
+			[/%(x|W|Q?)\{/, { token: 'string.$1.delim', switchTo: '@qqstring.$1.{.}' }],
+			[/%(x|W|Q?)</, { token: 'string.$1.delim', switchTo: '@qqstring.$1.<.>' }],
+			[/%(x|W|Q?)(@delim)/, { token: 'string.$1.delim', switchTo: '@qqstring.$1.$2.$2' }],
+
+			[/%([rqwsxW]|Q?)./, { token: 'invalid', next: '@pop' }], // recover
+			[/./, { token: 'invalid', next: '@pop' }], // recover
 		],
 
 		// non-expanded quoted string.
@@ -367,11 +403,15 @@ export var language = <ILanguage> {
 		//  open = open delimiter
 		//  close = close delimiter
 		qstring: [
-			[/\\$/, 'string.$S2.escape' ],
-			[/\\./, 'string.$S2.escape' ],
-			[/./,   { cases: { '$#==$S4' : { token: 'string.$S2.delim', next: '@pop' },
-								'$#==$S3' : { token: 'string.$S2.delim', next: '@push' }, // nested delimiters are allowed..
-								'@default': 'string.$S2' }}],
+			[/\\$/, 'string.$S2.escape'],
+			[/\\./, 'string.$S2.escape'],
+			[/./, {
+				cases: {
+					'$#==$S4': { token: 'string.$S2.delim', next: '@pop' },
+					'$#==$S3': { token: 'string.$S2.delim', next: '@push' }, // nested delimiters are allowed..
+					'@default': 'string.$S2'
+				}
+			}],
 		],
 
 		// expanded quoted string.
@@ -380,7 +420,7 @@ export var language = <ILanguage> {
 		//  open = open delimiter
 		//  close = close delimiter
 		qqstring: [
-			[/#/, 'string.$S2.escape', '@interpolated' ],
+			[/#/, 'string.$S2.escape', '@interpolated'],
 			{ include: '@qstring' }
 		],
 
@@ -388,15 +428,15 @@ export var language = <ILanguage> {
 		// whitespace & comments
 		whitespace: [
 			[/[ \t\r\n]+/, ''],
-			[/^\s*=begin\b/,       'comment', '@comment' ],
-			[/#.*$/,    'comment'],
+			[/^\s*=begin\b/, 'comment', '@comment'],
+			[/#.*$/, 'comment'],
 		],
 
 		comment: [
-			[/[^=]+/, 'comment' ],
-			[/^\s*=begin\b/, 'comment.invalid' ],    // nested comment
-			[/^\s*=end\b.*/, 'comment', '@pop'  ],
-			[/[=]/, 'comment' ]
+			[/[^=]+/, 'comment'],
+			[/^\s*=begin\b/, 'comment.invalid'],    // nested comment
+			[/^\s*=end\b.*/, 'comment', '@pop'],
+			[/[=]/, 'comment']
 		],
 	}
-};
+};

+ 268 - 268
src/scss.ts

@@ -9,30 +9,30 @@ import LanguageConfiguration = monaco.languages.LanguageConfiguration;
 import IMonarchLanguage = monaco.languages.IMonarchLanguage;
 
 export var conf: LanguageConfiguration = {
-    wordPattern: /(#?-?\d*\.\d\w*%?)|([@$#!.:]?[\w-?]+%?)|[@#!.]/g,
-    comments: {
-        blockComment: ['/*', '*/'],
-        lineComment: '//'
-    },
-    brackets: [
-        ['{', '}'],
-        ['[', ']'],
-        ['(', ')']
-    ],
-    autoClosingPairs: [
-        { open: '{', close: '}', notIn: ['string', 'comment'] },
-        { open: '[', close: ']', notIn: ['string', 'comment'] },
-        { open: '(', close: ')', notIn: ['string', 'comment'] },
-        { open: '"', close: '"', notIn: ['string', 'comment'] },
-        { open: '\'', close: '\'', notIn: ['string', 'comment'] },
-    ],
-    surroundingPairs: [
-        { open: '{', close: '}' },
-        { open: '[', close: ']' },
-        { open: '(', close: ')' },
-        { open: '"', close: '"' },
-        { open: '\'', close: '\'' },
-    ]
+	wordPattern: /(#?-?\d*\.\d\w*%?)|([@$#!.:]?[\w-?]+%?)|[@#!.]/g,
+	comments: {
+		blockComment: ['/*', '*/'],
+		lineComment: '//'
+	},
+	brackets: [
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
+	],
+	autoClosingPairs: [
+		{ open: '{', close: '}', notIn: ['string', 'comment'] },
+		{ open: '[', close: ']', notIn: ['string', 'comment'] },
+		{ open: '(', close: ')', notIn: ['string', 'comment'] },
+		{ open: '"', close: '"', notIn: ['string', 'comment'] },
+		{ open: '\'', close: '\'', notIn: ['string', 'comment'] },
+	],
+	surroundingPairs: [
+		{ open: '{', close: '}' },
+		{ open: '[', close: ']' },
+		{ open: '(', close: ')' },
+		{ open: '"', close: '"' },
+		{ open: '\'', close: '\'' },
+	]
 };
 
 const TOKEN_SELECTOR = 'tag';
@@ -41,247 +41,247 @@ const TOKEN_PROPERTY = 'attribute.name';
 const TOKEN_VALUE = 'attribute.value';
 const TOKEN_AT_KEYWORD = 'keyword';
 
-export var language = <IMonarchLanguage> {
-    defaultToken: '',
-    tokenPostfix: '.scss',
-
-    ws: '[ \t\n\r\f]*', // whitespaces (referenced in several rules)
-    identifier: '-?-?([a-zA-Z]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))([\\w\\-]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))*',
-
-    brackets: [
-        { open: '{', close: '}', token: 'delimiter.curly' },
-        { open: '[', close: ']', token: 'delimiter.bracket' },
-        { open: '(', close: ')', token: 'delimiter.parenthesis' },
-        { open: '<', close: '>', token: 'delimiter.angle' }
-    ],
-
-    tokenizer: {
-        root: [
-            { include: '@selector' },
-        ],
-
-        selector: [
-            { include: '@comments' },
-            { include: '@import' },
-            { include: '@variabledeclaration' },
-            { include: '@warndebug' }, // sass: log statements
-            ['[@](include)', { token: TOKEN_AT_KEYWORD, next: '@includedeclaration' }], // sass: include statement
-            ['[@](keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes)', { token: TOKEN_AT_KEYWORD, next: '@keyframedeclaration' }],
-            ['[@](page|content|font-face|-moz-document)', { token: TOKEN_AT_KEYWORD }], // sass: placeholder for includes
-            ['[@](charset|namespace)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }],
-            ['[@](function)', { token: TOKEN_AT_KEYWORD, next: '@functiondeclaration' }],
-            ['[@](mixin)', { token: TOKEN_AT_KEYWORD, next: '@mixindeclaration' }],
-            ['url(\\-prefix)?\\(', { token: 'meta', next: '@urldeclaration' }],
-            { include: '@controlstatement' }, // sass control statements
-            { include: '@selectorname' },
-            ['[&\\*]', TOKEN_SELECTOR_TAG], // selector symbols
-            ['[>\\+,]', 'delimiter'], // selector operators
-            ['\\[', { token: 'delimiter.bracket', next: '@selectorattribute' }],
-            ['{', { token: 'delimiter.curly', next: '@selectorbody' }],
-        ],
-
-        selectorbody: [
-            ['[*_]?@identifier@ws:(?=(\\s|\\d|[^{;}]*[;}]))', TOKEN_PROPERTY, '@rulevalue'], // rule definition: to distinguish from a nested selector check for whitespace, number or a semicolon
-            { include: '@selector' }, // sass: nested selectors
-            ['[@](extend)', { token: TOKEN_AT_KEYWORD, next: '@extendbody' }], // sass: extend other selectors
-            ['[@](return)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }],
-            ['}', { token: 'delimiter.curly', next: '@pop' }],
-        ],
-
-        selectorname: [
-            ['#{', { token: 'meta', next: '@variableinterpolation' }], // sass: interpolation
-            ['(\\.|#(?=[^{])|%|(@identifier)|:)+', TOKEN_SELECTOR], // selector (.foo, div, ...)
-        ],
-
-        selectorattribute: [
-            { include: '@term' },
-            [']', { token: 'delimiter.bracket', next: '@pop' }],
-        ],
-
-        term: [
-            { include: '@comments' },
-            ['url(\\-prefix)?\\(', { token: 'meta', next: '@urldeclaration' }],
-            { include: '@functioninvocation' },
-            { include: '@numbers' },
-            { include: '@strings' },
-            { include: '@variablereference' },
-            ['(and\\b|or\\b|not\\b)', 'operator'],
-            { include: '@name' },
-            ['([<>=\\+\\-\\*\\/\\^\\|\\~,])', 'operator'],
-            [',', 'delimiter'],
-            ['!default', 'literal'],
-            ['\\(', { token: 'delimiter.parenthesis', next: '@parenthizedterm' }],
-        ],
-
-        rulevalue: [
-            { include: '@term' },
-            ['!important', 'literal'],
-            [';', 'delimiter', '@pop'],
-            ['{', { token: 'delimiter.curly', switchTo: '@nestedproperty' }], // sass: nested properties
-            ['(?=})', { token: '', next: '@pop' }], // missing semicolon
-        ],
-
-        nestedproperty: [
-            ['[*_]?@identifier@ws:', TOKEN_PROPERTY, '@rulevalue'],
-            { include: '@comments' },
-            ['}', { token: 'delimiter.curly', next: '@pop' }],
-        ],
-
-        warndebug: [
-            ['[@](warn|debug)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }],
-        ],
-
-        import: [
-            ['[@](import)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }],
-        ],
-
-        variabledeclaration: [ // sass variables
-            ['\\$@identifier@ws:', 'variable.decl', '@declarationbody'],
-        ],
-
-        urldeclaration: [
-            { include: '@strings' },
-            ['[^)\r\n]+', 'string'],
-            ['\\)', { token: 'meta', next: '@pop' }],
-        ],
-
-        parenthizedterm: [
-            { include: '@term' },
-            ['\\)', { token: 'delimiter.parenthesis', next: '@pop' }],
-        ],
-
-        declarationbody: [
-            { include: '@term' },
-            [';', 'delimiter', '@pop'],
-            ['(?=})', { token: '', next: '@pop' }], // missing semicolon
-        ],
-
-        extendbody: [
-            { include: '@selectorname' },
-            ['!optional', 'literal'],
-            [';', 'delimiter', '@pop'],
-            ['(?=})', { token: '', next: '@pop' }], // missing semicolon
-        ],
-
-        variablereference: [ // sass variable reference
-            ['\\$@identifier', 'variable.ref'],
-            ['\\.\\.\\.', 'operator'], // var args in reference
-            ['#{', { token: 'meta', next: '@variableinterpolation' }], // sass var resolve
-        ],
-
-        variableinterpolation: [
-            { include: '@variablereference' },
-            ['}', { token: 'meta', next: '@pop' }],
-        ],
-
-        comments: [
-            ['\\/\\*', 'comment', '@comment'],
-            ['\\/\\/+.*', 'comment'],
-        ],
-
-        comment: [
-            ['\\*\\/', 'comment', '@pop'],
-            ['.', 'comment'],
-        ],
-
-        name: [
-            ['@identifier', TOKEN_VALUE],
-        ],
-
-        numbers: [
-            ['(\\d*\\.)?\\d+([eE][\\-+]?\\d+)?', { token: 'number', next: '@units' }],
-            ['#[0-9a-fA-F_]+(?!\\w)', 'number.hex'],
-        ],
-
-        units: [
-            ['(em|ex|ch|rem|vmin|vmax|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)?', 'number', '@pop']
-        ],
-
-        functiondeclaration: [
-            ['@identifier@ws\\(', { token: 'meta', next: '@parameterdeclaration' }],
-            ['{', { token: 'delimiter.curly', switchTo: '@functionbody' }],
-        ],
-
-        mixindeclaration: [
-            // mixin with parameters
-            ['@identifier@ws\\(', { token: 'meta', next: '@parameterdeclaration' }],
-            // mixin without parameters
-            ['@identifier', 'meta'],
-            ['{', { token: 'delimiter.curly', switchTo: '@selectorbody' }],
-        ],
-
-        parameterdeclaration: [
-            ['\\$@identifier@ws:', 'variable.decl'],
-            ['\\.\\.\\.', 'operator'], // var args in declaration
-            [',', 'delimiter'],
-            { include: '@term' },
-            ['\\)', { token: 'meta', next: '@pop' }],
-        ],
-
-        includedeclaration: [
-            { include: '@functioninvocation' },
-            ['@identifier', 'meta'],
-            [';', 'delimiter', '@pop'],
-            ['(?=})', { token: '', next: '@pop' }], // missing semicolon
-            ['{', { token: 'delimiter.curly', switchTo: '@selectorbody' }],
-        ],
-
-        keyframedeclaration: [
-            ['@identifier', 'meta'],
-            ['{', { token: 'delimiter.curly', switchTo: '@keyframebody' }],
-        ],
-
-        keyframebody: [
-            { include: '@term' },
-            ['{', { token: 'delimiter.curly', next: '@selectorbody' }],
-            ['}', { token: 'delimiter.curly', next: '@pop' }],
-        ],
-
-        controlstatement: [
-            ['[@](if|else|for|while|each|media)', { token: 'keyword.flow', next: '@controlstatementdeclaration' }],
-        ],
-
-        controlstatementdeclaration: [
-            ['(in|from|through|if|to)\\b', { token: 'keyword.flow' }],
-            { include: '@term' },
-            ['{', { token: 'delimiter.curly', switchTo: '@selectorbody' }],
-        ],
-
-        functionbody: [
-            ['[@](return)', { token: TOKEN_AT_KEYWORD }],
-            { include: '@variabledeclaration' },
-            { include: '@term' },
-            { include: '@controlstatement' },
-            [';', 'delimiter'],
-            ['}', { token: 'delimiter.curly', next: '@pop' }],
-        ],
-
-        functioninvocation: [
-            ['@identifier\\(', { token: 'meta', next: '@functionarguments' }],
-        ],
-
-        functionarguments: [
-            ['\\$@identifier@ws:', TOKEN_PROPERTY],
-            ['[,]', 'delimiter'],
-            { include: '@term' },
-            ['\\)', { token: 'meta', next: '@pop' }],
-        ],
-
-        strings: [
-            ['~?"', { token: 'string.delimiter', next: '@stringenddoublequote' }],
-            ['~?\'', { token: 'string.delimiter', next: '@stringendquote' }]
-        ],
-
-        stringenddoublequote: [
-            ['\\\\.', 'string'],
-            ['"', { token: 'string.delimiter', next: '@pop' }],
-            ['.', 'string']
-        ],
-
-        stringendquote: [
-            ['\\\\.', 'string'],
-            ['\'', { token: 'string.delimiter', next: '@pop' }],
-            ['.', 'string']
-        ]
-    }
-};
+export var language = <IMonarchLanguage>{
+	defaultToken: '',
+	tokenPostfix: '.scss',
+
+	ws: '[ \t\n\r\f]*', // whitespaces (referenced in several rules)
+	identifier: '-?-?([a-zA-Z]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))([\\w\\-]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))*',
+
+	brackets: [
+		{ open: '{', close: '}', token: 'delimiter.curly' },
+		{ open: '[', close: ']', token: 'delimiter.bracket' },
+		{ open: '(', close: ')', token: 'delimiter.parenthesis' },
+		{ open: '<', close: '>', token: 'delimiter.angle' }
+	],
+
+	tokenizer: {
+		root: [
+			{ include: '@selector' },
+		],
+
+		selector: [
+			{ include: '@comments' },
+			{ include: '@import' },
+			{ include: '@variabledeclaration' },
+			{ include: '@warndebug' }, // sass: log statements
+			['[@](include)', { token: TOKEN_AT_KEYWORD, next: '@includedeclaration' }], // sass: include statement
+			['[@](keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes)', { token: TOKEN_AT_KEYWORD, next: '@keyframedeclaration' }],
+			['[@](page|content|font-face|-moz-document)', { token: TOKEN_AT_KEYWORD }], // sass: placeholder for includes
+			['[@](charset|namespace)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }],
+			['[@](function)', { token: TOKEN_AT_KEYWORD, next: '@functiondeclaration' }],
+			['[@](mixin)', { token: TOKEN_AT_KEYWORD, next: '@mixindeclaration' }],
+			['url(\\-prefix)?\\(', { token: 'meta', next: '@urldeclaration' }],
+			{ include: '@controlstatement' }, // sass control statements
+			{ include: '@selectorname' },
+			['[&\\*]', TOKEN_SELECTOR_TAG], // selector symbols
+			['[>\\+,]', 'delimiter'], // selector operators
+			['\\[', { token: 'delimiter.bracket', next: '@selectorattribute' }],
+			['{', { token: 'delimiter.curly', next: '@selectorbody' }],
+		],
+
+		selectorbody: [
+			['[*_]?@identifier@ws:(?=(\\s|\\d|[^{;}]*[;}]))', TOKEN_PROPERTY, '@rulevalue'], // rule definition: to distinguish from a nested selector check for whitespace, number or a semicolon
+			{ include: '@selector' }, // sass: nested selectors
+			['[@](extend)', { token: TOKEN_AT_KEYWORD, next: '@extendbody' }], // sass: extend other selectors
+			['[@](return)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }],
+			['}', { token: 'delimiter.curly', next: '@pop' }],
+		],
+
+		selectorname: [
+			['#{', { token: 'meta', next: '@variableinterpolation' }], // sass: interpolation
+			['(\\.|#(?=[^{])|%|(@identifier)|:)+', TOKEN_SELECTOR], // selector (.foo, div, ...)
+		],
+
+		selectorattribute: [
+			{ include: '@term' },
+			[']', { token: 'delimiter.bracket', next: '@pop' }],
+		],
+
+		term: [
+			{ include: '@comments' },
+			['url(\\-prefix)?\\(', { token: 'meta', next: '@urldeclaration' }],
+			{ include: '@functioninvocation' },
+			{ include: '@numbers' },
+			{ include: '@strings' },
+			{ include: '@variablereference' },
+			['(and\\b|or\\b|not\\b)', 'operator'],
+			{ include: '@name' },
+			['([<>=\\+\\-\\*\\/\\^\\|\\~,])', 'operator'],
+			[',', 'delimiter'],
+			['!default', 'literal'],
+			['\\(', { token: 'delimiter.parenthesis', next: '@parenthizedterm' }],
+		],
+
+		rulevalue: [
+			{ include: '@term' },
+			['!important', 'literal'],
+			[';', 'delimiter', '@pop'],
+			['{', { token: 'delimiter.curly', switchTo: '@nestedproperty' }], // sass: nested properties
+			['(?=})', { token: '', next: '@pop' }], // missing semicolon
+		],
+
+		nestedproperty: [
+			['[*_]?@identifier@ws:', TOKEN_PROPERTY, '@rulevalue'],
+			{ include: '@comments' },
+			['}', { token: 'delimiter.curly', next: '@pop' }],
+		],
+
+		warndebug: [
+			['[@](warn|debug)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }],
+		],
+
+		import: [
+			['[@](import)', { token: TOKEN_AT_KEYWORD, next: '@declarationbody' }],
+		],
+
+		variabledeclaration: [ // sass variables
+			['\\$@identifier@ws:', 'variable.decl', '@declarationbody'],
+		],
+
+		urldeclaration: [
+			{ include: '@strings' },
+			['[^)\r\n]+', 'string'],
+			['\\)', { token: 'meta', next: '@pop' }],
+		],
+
+		parenthizedterm: [
+			{ include: '@term' },
+			['\\)', { token: 'delimiter.parenthesis', next: '@pop' }],
+		],
+
+		declarationbody: [
+			{ include: '@term' },
+			[';', 'delimiter', '@pop'],
+			['(?=})', { token: '', next: '@pop' }], // missing semicolon
+		],
+
+		extendbody: [
+			{ include: '@selectorname' },
+			['!optional', 'literal'],
+			[';', 'delimiter', '@pop'],
+			['(?=})', { token: '', next: '@pop' }], // missing semicolon
+		],
+
+		variablereference: [ // sass variable reference
+			['\\$@identifier', 'variable.ref'],
+			['\\.\\.\\.', 'operator'], // var args in reference
+			['#{', { token: 'meta', next: '@variableinterpolation' }], // sass var resolve
+		],
+
+		variableinterpolation: [
+			{ include: '@variablereference' },
+			['}', { token: 'meta', next: '@pop' }],
+		],
+
+		comments: [
+			['\\/\\*', 'comment', '@comment'],
+			['\\/\\/+.*', 'comment'],
+		],
+
+		comment: [
+			['\\*\\/', 'comment', '@pop'],
+			['.', 'comment'],
+		],
+
+		name: [
+			['@identifier', TOKEN_VALUE],
+		],
+
+		numbers: [
+			['(\\d*\\.)?\\d+([eE][\\-+]?\\d+)?', { token: 'number', next: '@units' }],
+			['#[0-9a-fA-F_]+(?!\\w)', 'number.hex'],
+		],
+
+		units: [
+			['(em|ex|ch|rem|vmin|vmax|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)?', 'number', '@pop']
+		],
+
+		functiondeclaration: [
+			['@identifier@ws\\(', { token: 'meta', next: '@parameterdeclaration' }],
+			['{', { token: 'delimiter.curly', switchTo: '@functionbody' }],
+		],
+
+		mixindeclaration: [
+			// mixin with parameters
+			['@identifier@ws\\(', { token: 'meta', next: '@parameterdeclaration' }],
+			// mixin without parameters
+			['@identifier', 'meta'],
+			['{', { token: 'delimiter.curly', switchTo: '@selectorbody' }],
+		],
+
+		parameterdeclaration: [
+			['\\$@identifier@ws:', 'variable.decl'],
+			['\\.\\.\\.', 'operator'], // var args in declaration
+			[',', 'delimiter'],
+			{ include: '@term' },
+			['\\)', { token: 'meta', next: '@pop' }],
+		],
+
+		includedeclaration: [
+			{ include: '@functioninvocation' },
+			['@identifier', 'meta'],
+			[';', 'delimiter', '@pop'],
+			['(?=})', { token: '', next: '@pop' }], // missing semicolon
+			['{', { token: 'delimiter.curly', switchTo: '@selectorbody' }],
+		],
+
+		keyframedeclaration: [
+			['@identifier', 'meta'],
+			['{', { token: 'delimiter.curly', switchTo: '@keyframebody' }],
+		],
+
+		keyframebody: [
+			{ include: '@term' },
+			['{', { token: 'delimiter.curly', next: '@selectorbody' }],
+			['}', { token: 'delimiter.curly', next: '@pop' }],
+		],
+
+		controlstatement: [
+			['[@](if|else|for|while|each|media)', { token: 'keyword.flow', next: '@controlstatementdeclaration' }],
+		],
+
+		controlstatementdeclaration: [
+			['(in|from|through|if|to)\\b', { token: 'keyword.flow' }],
+			{ include: '@term' },
+			['{', { token: 'delimiter.curly', switchTo: '@selectorbody' }],
+		],
+
+		functionbody: [
+			['[@](return)', { token: TOKEN_AT_KEYWORD }],
+			{ include: '@variabledeclaration' },
+			{ include: '@term' },
+			{ include: '@controlstatement' },
+			[';', 'delimiter'],
+			['}', { token: 'delimiter.curly', next: '@pop' }],
+		],
+
+		functioninvocation: [
+			['@identifier\\(', { token: 'meta', next: '@functionarguments' }],
+		],
+
+		functionarguments: [
+			['\\$@identifier@ws:', TOKEN_PROPERTY],
+			['[,]', 'delimiter'],
+			{ include: '@term' },
+			['\\)', { token: 'meta', next: '@pop' }],
+		],
+
+		strings: [
+			['~?"', { token: 'string.delimiter', next: '@stringenddoublequote' }],
+			['~?\'', { token: 'string.delimiter', next: '@stringendquote' }]
+		],
+
+		stringenddoublequote: [
+			['\\\\.', 'string'],
+			['"', { token: 'string.delimiter', next: '@pop' }],
+			['.', 'string']
+		],
+
+		stringendquote: [
+			['\\\\.', 'string'],
+			['\'', { token: 'string.delimiter', next: '@pop' }],
+			['.', 'string']
+		]
+	}
+};

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 7 - 7
src/solidity.ts


+ 68 - 64
src/sql.ts

@@ -8,15 +8,15 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '--',
 		blockComment: ['/*', '*/'],
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')']
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -34,7 +34,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.sql',
 	ignoreCase: true,
@@ -956,101 +956,101 @@ export var language = <ILanguage> {
 	],
 	operators: [
 		// Logical
-		'ALL','AND','ANY','BETWEEN','EXISTS','IN','LIKE','NOT','OR','SOME',
+		'ALL', 'AND', 'ANY', 'BETWEEN', 'EXISTS', 'IN', 'LIKE', 'NOT', 'OR', 'SOME',
 		// Set
-		'EXCEPT','INTERSECT','UNION',
+		'EXCEPT', 'INTERSECT', 'UNION',
 		// Join
-		'APPLY','CROSS','FULL','INNER','JOIN','LEFT','OUTER','RIGHT',
+		'APPLY', 'CROSS', 'FULL', 'INNER', 'JOIN', 'LEFT', 'OUTER', 'RIGHT',
 		// Predicates
-		'CONTAINS','FREETEXT','IS','NULL',
+		'CONTAINS', 'FREETEXT', 'IS', 'NULL',
 		// Pivoting
-		'PIVOT','UNPIVOT',
+		'PIVOT', 'UNPIVOT',
 		// Merging
 		'MATCHED'
 	],
 	builtinFunctions: [
 		// Aggregate
-		'AVG','CHECKSUM_AGG','COUNT','COUNT_BIG','GROUPING','GROUPING_ID','MAX','MIN','SUM','STDEV','STDEVP','VAR','VARP',
+		'AVG', 'CHECKSUM_AGG', 'COUNT', 'COUNT_BIG', 'GROUPING', 'GROUPING_ID', 'MAX', 'MIN', 'SUM', 'STDEV', 'STDEVP', 'VAR', 'VARP',
 		// Analytic
-		'CUME_DIST','FIRST_VALUE','LAG','LAST_VALUE','LEAD','PERCENTILE_CONT','PERCENTILE_DISC','PERCENT_RANK',
+		'CUME_DIST', 'FIRST_VALUE', 'LAG', 'LAST_VALUE', 'LEAD', 'PERCENTILE_CONT', 'PERCENTILE_DISC', 'PERCENT_RANK',
 		// Collation
-		'COLLATE','COLLATIONPROPERTY','TERTIARY_WEIGHTS',
+		'COLLATE', 'COLLATIONPROPERTY', 'TERTIARY_WEIGHTS',
 		// Azure
 		'FEDERATION_FILTERING_VALUE',
 		// Conversion
-		'CAST','CONVERT','PARSE','TRY_CAST','TRY_CONVERT','TRY_PARSE',
+		'CAST', 'CONVERT', 'PARSE', 'TRY_CAST', 'TRY_CONVERT', 'TRY_PARSE',
 		// Cryptographic
-		'ASYMKEY_ID','ASYMKEYPROPERTY','CERTPROPERTY','CERT_ID','CRYPT_GEN_RANDOM',
-		'DECRYPTBYASYMKEY','DECRYPTBYCERT','DECRYPTBYKEY','DECRYPTBYKEYAUTOASYMKEY','DECRYPTBYKEYAUTOCERT','DECRYPTBYPASSPHRASE',
-		'ENCRYPTBYASYMKEY','ENCRYPTBYCERT','ENCRYPTBYKEY','ENCRYPTBYPASSPHRASE','HASHBYTES','IS_OBJECTSIGNED',
-		'KEY_GUID','KEY_ID','KEY_NAME','SIGNBYASYMKEY','SIGNBYCERT','SYMKEYPROPERTY','VERIFYSIGNEDBYCERT','VERIFYSIGNEDBYASYMKEY',
+		'ASYMKEY_ID', 'ASYMKEYPROPERTY', 'CERTPROPERTY', 'CERT_ID', 'CRYPT_GEN_RANDOM',
+		'DECRYPTBYASYMKEY', 'DECRYPTBYCERT', 'DECRYPTBYKEY', 'DECRYPTBYKEYAUTOASYMKEY', 'DECRYPTBYKEYAUTOCERT', 'DECRYPTBYPASSPHRASE',
+		'ENCRYPTBYASYMKEY', 'ENCRYPTBYCERT', 'ENCRYPTBYKEY', 'ENCRYPTBYPASSPHRASE', 'HASHBYTES', 'IS_OBJECTSIGNED',
+		'KEY_GUID', 'KEY_ID', 'KEY_NAME', 'SIGNBYASYMKEY', 'SIGNBYCERT', 'SYMKEYPROPERTY', 'VERIFYSIGNEDBYCERT', 'VERIFYSIGNEDBYASYMKEY',
 		// Cursor
 		'CURSOR_STATUS',
 		// Datatype
-		'DATALENGTH','IDENT_CURRENT','IDENT_INCR','IDENT_SEED','IDENTITY','SQL_VARIANT_PROPERTY',
+		'DATALENGTH', 'IDENT_CURRENT', 'IDENT_INCR', 'IDENT_SEED', 'IDENTITY', 'SQL_VARIANT_PROPERTY',
 		// Datetime
-		'CURRENT_TIMESTAMP','DATEADD','DATEDIFF','DATEFROMPARTS','DATENAME','DATEPART','DATETIME2FROMPARTS','DATETIMEFROMPARTS',
-		'DATETIMEOFFSETFROMPARTS','DAY','EOMONTH','GETDATE','GETUTCDATE','ISDATE','MONTH','SMALLDATETIMEFROMPARTS','SWITCHOFFSET',
-		'SYSDATETIME','SYSDATETIMEOFFSET','SYSUTCDATETIME','TIMEFROMPARTS','TODATETIMEOFFSET','YEAR',
+		'CURRENT_TIMESTAMP', 'DATEADD', 'DATEDIFF', 'DATEFROMPARTS', 'DATENAME', 'DATEPART', 'DATETIME2FROMPARTS', 'DATETIMEFROMPARTS',
+		'DATETIMEOFFSETFROMPARTS', 'DAY', 'EOMONTH', 'GETDATE', 'GETUTCDATE', 'ISDATE', 'MONTH', 'SMALLDATETIMEFROMPARTS', 'SWITCHOFFSET',
+		'SYSDATETIME', 'SYSDATETIMEOFFSET', 'SYSUTCDATETIME', 'TIMEFROMPARTS', 'TODATETIMEOFFSET', 'YEAR',
 		// Logical
-		'CHOOSE','COALESCE','IIF','NULLIF',
+		'CHOOSE', 'COALESCE', 'IIF', 'NULLIF',
 		// Mathematical
-		'ABS','ACOS','ASIN','ATAN','ATN2','CEILING','COS','COT','DEGREES','EXP','FLOOR','LOG','LOG10',
-		'PI','POWER','RADIANS','RAND','ROUND','SIGN','SIN','SQRT','SQUARE','TAN',
+		'ABS', 'ACOS', 'ASIN', 'ATAN', 'ATN2', 'CEILING', 'COS', 'COT', 'DEGREES', 'EXP', 'FLOOR', 'LOG', 'LOG10',
+		'PI', 'POWER', 'RADIANS', 'RAND', 'ROUND', 'SIGN', 'SIN', 'SQRT', 'SQUARE', 'TAN',
 		// Metadata
-		'APP_NAME','APPLOCK_MODE','APPLOCK_TEST','ASSEMBLYPROPERTY','COL_LENGTH','COL_NAME','COLUMNPROPERTY',
-		'DATABASE_PRINCIPAL_ID','DATABASEPROPERTYEX','DB_ID','DB_NAME','FILE_ID','FILE_IDEX','FILE_NAME','FILEGROUP_ID',
-		'FILEGROUP_NAME','FILEGROUPPROPERTY','FILEPROPERTY','FULLTEXTCATALOGPROPERTY','FULLTEXTSERVICEPROPERTY',
-		'INDEX_COL','INDEXKEY_PROPERTY','INDEXPROPERTY','OBJECT_DEFINITION','OBJECT_ID',
-		'OBJECT_NAME','OBJECT_SCHEMA_NAME','OBJECTPROPERTY','OBJECTPROPERTYEX','ORIGINAL_DB_NAME','PARSENAME',
-		'SCHEMA_ID','SCHEMA_NAME','SCOPE_IDENTITY','SERVERPROPERTY','STATS_DATE','TYPE_ID','TYPE_NAME','TYPEPROPERTY',
+		'APP_NAME', 'APPLOCK_MODE', 'APPLOCK_TEST', 'ASSEMBLYPROPERTY', 'COL_LENGTH', 'COL_NAME', 'COLUMNPROPERTY',
+		'DATABASE_PRINCIPAL_ID', 'DATABASEPROPERTYEX', 'DB_ID', 'DB_NAME', 'FILE_ID', 'FILE_IDEX', 'FILE_NAME', 'FILEGROUP_ID',
+		'FILEGROUP_NAME', 'FILEGROUPPROPERTY', 'FILEPROPERTY', 'FULLTEXTCATALOGPROPERTY', 'FULLTEXTSERVICEPROPERTY',
+		'INDEX_COL', 'INDEXKEY_PROPERTY', 'INDEXPROPERTY', 'OBJECT_DEFINITION', 'OBJECT_ID',
+		'OBJECT_NAME', 'OBJECT_SCHEMA_NAME', 'OBJECTPROPERTY', 'OBJECTPROPERTYEX', 'ORIGINAL_DB_NAME', 'PARSENAME',
+		'SCHEMA_ID', 'SCHEMA_NAME', 'SCOPE_IDENTITY', 'SERVERPROPERTY', 'STATS_DATE', 'TYPE_ID', 'TYPE_NAME', 'TYPEPROPERTY',
 		// Ranking
-		'DENSE_RANK','NTILE','RANK','ROW_NUMBER',
+		'DENSE_RANK', 'NTILE', 'RANK', 'ROW_NUMBER',
 		// Replication
 		'PUBLISHINGSERVERNAME',
 		// Rowset
-		'OPENDATASOURCE','OPENQUERY','OPENROWSET','OPENXML',
+		'OPENDATASOURCE', 'OPENQUERY', 'OPENROWSET', 'OPENXML',
 		// Security
-		'CERTENCODED','CERTPRIVATEKEY','CURRENT_USER','HAS_DBACCESS','HAS_PERMS_BY_NAME','IS_MEMBER','IS_ROLEMEMBER','IS_SRVROLEMEMBER',
-		'LOGINPROPERTY','ORIGINAL_LOGIN','PERMISSIONS','PWDENCRYPT','PWDCOMPARE','SESSION_USER','SESSIONPROPERTY','SUSER_ID','SUSER_NAME',
-		'SUSER_SID','SUSER_SNAME','SYSTEM_USER','USER','USER_ID','USER_NAME',
+		'CERTENCODED', 'CERTPRIVATEKEY', 'CURRENT_USER', 'HAS_DBACCESS', 'HAS_PERMS_BY_NAME', 'IS_MEMBER', 'IS_ROLEMEMBER', 'IS_SRVROLEMEMBER',
+		'LOGINPROPERTY', 'ORIGINAL_LOGIN', 'PERMISSIONS', 'PWDENCRYPT', 'PWDCOMPARE', 'SESSION_USER', 'SESSIONPROPERTY', 'SUSER_ID', 'SUSER_NAME',
+		'SUSER_SID', 'SUSER_SNAME', 'SYSTEM_USER', 'USER', 'USER_ID', 'USER_NAME',
 		// String
-		'ASCII','CHAR','CHARINDEX','CONCAT','DIFFERENCE','FORMAT','LEFT','LEN','LOWER','LTRIM','NCHAR','PATINDEX',
-		'QUOTENAME','REPLACE','REPLICATE','REVERSE','RIGHT','RTRIM','SOUNDEX','SPACE','STR','STUFF','SUBSTRING','UNICODE','UPPER',
+		'ASCII', 'CHAR', 'CHARINDEX', 'CONCAT', 'DIFFERENCE', 'FORMAT', 'LEFT', 'LEN', 'LOWER', 'LTRIM', 'NCHAR', 'PATINDEX',
+		'QUOTENAME', 'REPLACE', 'REPLICATE', 'REVERSE', 'RIGHT', 'RTRIM', 'SOUNDEX', 'SPACE', 'STR', 'STUFF', 'SUBSTRING', 'UNICODE', 'UPPER',
 		// System
-		'BINARY_CHECKSUM','CHECKSUM','CONNECTIONPROPERTY','CONTEXT_INFO','CURRENT_REQUEST_ID','ERROR_LINE','ERROR_NUMBER','ERROR_MESSAGE',
-		'ERROR_PROCEDURE','ERROR_SEVERITY','ERROR_STATE','FORMATMESSAGE','GETANSINULL','GET_FILESTREAM_TRANSACTION_CONTEXT','HOST_ID',
-		'HOST_NAME','ISNULL','ISNUMERIC','MIN_ACTIVE_ROWVERSION','NEWID','NEWSEQUENTIALID','ROWCOUNT_BIG','XACT_STATE',
+		'BINARY_CHECKSUM', 'CHECKSUM', 'CONNECTIONPROPERTY', 'CONTEXT_INFO', 'CURRENT_REQUEST_ID', 'ERROR_LINE', 'ERROR_NUMBER', 'ERROR_MESSAGE',
+		'ERROR_PROCEDURE', 'ERROR_SEVERITY', 'ERROR_STATE', 'FORMATMESSAGE', 'GETANSINULL', 'GET_FILESTREAM_TRANSACTION_CONTEXT', 'HOST_ID',
+		'HOST_NAME', 'ISNULL', 'ISNUMERIC', 'MIN_ACTIVE_ROWVERSION', 'NEWID', 'NEWSEQUENTIALID', 'ROWCOUNT_BIG', 'XACT_STATE',
 		// TextImage
-		'TEXTPTR','TEXTVALID',
+		'TEXTPTR', 'TEXTVALID',
 		// Trigger
-		'COLUMNS_UPDATED','EVENTDATA','TRIGGER_NESTLEVEL','UPDATE',
+		'COLUMNS_UPDATED', 'EVENTDATA', 'TRIGGER_NESTLEVEL', 'UPDATE',
 		// ChangeTracking
-		'CHANGETABLE','CHANGE_TRACKING_CONTEXT','CHANGE_TRACKING_CURRENT_VERSION','CHANGE_TRACKING_IS_COLUMN_IN_MASK','CHANGE_TRACKING_MIN_VALID_VERSION',
+		'CHANGETABLE', 'CHANGE_TRACKING_CONTEXT', 'CHANGE_TRACKING_CURRENT_VERSION', 'CHANGE_TRACKING_IS_COLUMN_IN_MASK', 'CHANGE_TRACKING_MIN_VALID_VERSION',
 		// FullTextSearch
-		'CONTAINSTABLE','FREETEXTTABLE',
+		'CONTAINSTABLE', 'FREETEXTTABLE',
 		// SemanticTextSearch
-		'SEMANTICKEYPHRASETABLE','SEMANTICSIMILARITYDETAILSTABLE','SEMANTICSIMILARITYTABLE',
+		'SEMANTICKEYPHRASETABLE', 'SEMANTICSIMILARITYDETAILSTABLE', 'SEMANTICSIMILARITYTABLE',
 		// FileStream
-		'FILETABLEROOTPATH','GETFILENAMESPACEPATH','GETPATHLOCATOR','PATHNAME',
+		'FILETABLEROOTPATH', 'GETFILENAMESPACEPATH', 'GETPATHLOCATOR', 'PATHNAME',
 		// ServiceBroker
 		'GET_TRANSMISSION_STATUS'
 	],
 	builtinVariables: [
 		// Configuration
-		'@@DATEFIRST','@@DBTS','@@LANGID','@@LANGUAGE','@@LOCK_TIMEOUT','@@MAX_CONNECTIONS','@@MAX_PRECISION','@@NESTLEVEL',
-		'@@OPTIONS','@@REMSERVER','@@SERVERNAME','@@SERVICENAME','@@SPID','@@TEXTSIZE','@@VERSION',
+		'@@DATEFIRST', '@@DBTS', '@@LANGID', '@@LANGUAGE', '@@LOCK_TIMEOUT', '@@MAX_CONNECTIONS', '@@MAX_PRECISION', '@@NESTLEVEL',
+		'@@OPTIONS', '@@REMSERVER', '@@SERVERNAME', '@@SERVICENAME', '@@SPID', '@@TEXTSIZE', '@@VERSION',
 		// Cursor
-		'@@CURSOR_ROWS','@@FETCH_STATUS',
+		'@@CURSOR_ROWS', '@@FETCH_STATUS',
 		// Datetime
 		'@@DATEFIRST',
 		// Metadata
 		'@@PROCID',
 		// System
-		'@@ERROR','@@IDENTITY','@@ROWCOUNT','@@TRANCOUNT',
+		'@@ERROR', '@@IDENTITY', '@@ROWCOUNT', '@@TRANCOUNT',
 		// Stats
-		'@@CONNECTIONS','@@CPU_BUSY','@@IDLE','@@IO_BUSY','@@PACKET_ERRORS','@@PACK_RECEIVED','@@PACK_SENT',
-		'@@TIMETICKS','@@TOTAL_ERRORS','@@TOTAL_READ','@@TOTAL_WRITE'
+		'@@CONNECTIONS', '@@CPU_BUSY', '@@IDLE', '@@IO_BUSY', '@@PACKET_ERRORS', '@@PACK_RECEIVED', '@@PACK_SENT',
+		'@@TIMETICKS', '@@TOTAL_ERRORS', '@@TOTAL_READ', '@@TOTAL_WRITE'
 	],
 	pseudoColumns: [
 		'$ACTION', '$IDENTITY', '$ROWGUID', '$PARTITION'
@@ -1066,13 +1066,15 @@ export var language = <ILanguage> {
 			{ include: '@scopes' },
 			[/[;,.]/, 'delimiter'],
 			[/[()]/, '@brackets'],
-			[/[\w@#$]+/, { cases: {
-							'@keywords': 'keyword',
-							'@operators': 'operator',
-							'@builtinVariables': 'predefined',
-							'@builtinFunctions': 'predefined',
-							'@default': 'identifier' }
-						}],
+			[/[\w@#$]+/, {
+				cases: {
+					'@keywords': 'keyword',
+					'@operators': 'operator',
+					'@builtinVariables': 'predefined',
+					'@builtinFunctions': 'predefined',
+					'@default': 'identifier'
+				}
+			}],
 			[/[<>=!%&+\-*/|~^]/, 'operator'],
 		],
 		whitespace: [
@@ -1091,10 +1093,12 @@ export var language = <ILanguage> {
 			[/./, 'comment']
 		],
 		pseudoColumns: [
-			[/[$][A-Za-z_][\w@#$]*/, { cases: {
-				'@pseudoColumns': 'predefined',
-				'@default': 'identifier'
-			}}],
+			[/[$][A-Za-z_][\w@#$]*/, {
+				cases: {
+					'@pseudoColumns': 'predefined',
+					'@default': 'identifier'
+				}
+			}],
 		],
 		numbers: [
 			[/0[xX][0-9a-fA-F]*/, 'number'],

+ 55 - 40
src/swift.ts

@@ -7,15 +7,15 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '//',
 		blockComment: ['/*', '*/'],
 	},
 	brackets: [
-		['{','}'],
-		['[',']'],
-		['(',')']
+		['{', '}'],
+		['[', ']'],
+		['(', ')']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}' },
@@ -35,7 +35,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.swift',
 
@@ -46,7 +46,7 @@ export var language = <ILanguage> {
 		'@autoclosure', '@noescape', '@noreturn', '@NSApplicationMain', '@NSCopying', '@NSManaged',
 		'@objc', '@UIApplicationMain', '@noreturn', '@availability', '@IBAction', '@IBDesignable', '@IBInspectable', '@IBOutlet'
 	],
-	accessmodifiers: [ 'public', 'private', 'internal' ],
+	accessmodifiers: ['public', 'private', 'internal'],
 	keywords: [
 		'__COLUMN__', '__FILE__', '__FUNCTION__', '__LINE__', 'as', 'as!', 'as?', 'associativity', 'break', 'case', 'catch',
 		'class', 'continue', 'convenience', 'default', 'deinit', 'didSet', 'do', 'dynamic', 'dynamicType',
@@ -87,69 +87,84 @@ export var language = <ILanguage> {
 
 
 		comment: [
-			[ /\/\/\/.*$/, 'comment.doc' ],
-			[ /\/\*\*/, 'comment.doc', '@commentdocbody' ],
-			[ /\/\/.*$/, 'comment' ],
-			[ /\/\*/, 'comment', '@commentbody' ]
+			[/\/\/\/.*$/, 'comment.doc'],
+			[/\/\*\*/, 'comment.doc', '@commentdocbody'],
+			[/\/\/.*$/, 'comment'],
+			[/\/\*/, 'comment', '@commentbody']
 		],
 		commentdocbody: [
-			[ /\/\*/, 'comment', '@commentbody' ],
-			[ /\*\//, 'comment.doc', '@pop' ],
-			[ /\:[a-zA-Z]+\:/, 'comment.doc.param' ],
-			[ /./, 'comment.doc' ]
+			[/\/\*/, 'comment', '@commentbody'],
+			[/\*\//, 'comment.doc', '@pop'],
+			[/\:[a-zA-Z]+\:/, 'comment.doc.param'],
+			[/./, 'comment.doc']
 		],
 		commentbody: [
-			[ /\/\*/, 'comment', '@commentbody' ],
-			[ /\*\//, 'comment', '@pop' ],
-			[ /./, 'comment' ]
+			[/\/\*/, 'comment', '@commentbody'],
+			[/\*\//, 'comment', '@pop'],
+			[/./, 'comment']
 		],
 
 		attribute: [
-			[ /\@@identifier/, { cases: { '@attributes': 'keyword.control', '@default': '' } } ]
+			[/\@@identifier/, {
+				cases: {
+					'@attributes': 'keyword.control',
+					'@default': ''
+				}
+			}]
 		],
 
 		literal: [
-			[ /"/, { token: 'string.quote', next: '@stringlit' } ],
-			[ /0[b]([01]_?)+/, 'number.binary' ],
-			[ /0[o]([0-7]_?)+/, 'number.octal' ],
-			[ /0[x]([0-9a-fA-F]_?)+([pP][\-+](\d_?)+)?/, 'number.hex' ],
-			[ /(\d_?)*\.(\d_?)+([eE][\-+]?(\d_?)+)?/, 'number.float'],
-			[ /(\d_?)+/, 'number' ]
+			[/"/, { token: 'string.quote', next: '@stringlit' }],
+			[/0[b]([01]_?)+/, 'number.binary'],
+			[/0[o]([0-7]_?)+/, 'number.octal'],
+			[/0[x]([0-9a-fA-F]_?)+([pP][\-+](\d_?)+)?/, 'number.hex'],
+			[/(\d_?)*\.(\d_?)+([eE][\-+]?(\d_?)+)?/, 'number.float'],
+			[/(\d_?)+/, 'number']
 		],
 
 		stringlit: [
-			[ /\\\(/, { token: 'operator', next: '@interpolatedexpression' } ],
-			[ /@escapes/, 'string' ],
-			[ /\\./, 'string.escape.invalid' ],
-			[ /"/, { token: 'string.quote', next: '@pop' } ],
-			[ /./, 'string' ]
+			[/\\\(/, { token: 'operator', next: '@interpolatedexpression' }],
+			[/@escapes/, 'string'],
+			[/\\./, 'string.escape.invalid'],
+			[/"/, { token: 'string.quote', next: '@pop' }],
+			[/./, 'string']
 		],
 
 		interpolatedexpression: [
-			[ /\(/, { token: 'operator', next: '@interpolatedexpression' } ],
-			[ /\)/, { token: 'operator', next: '@pop' } ],
+			[/\(/, { token: 'operator', next: '@interpolatedexpression' }],
+			[/\)/, { token: 'operator', next: '@pop' }],
 			{ include: '@literal' },
 			{ include: '@keyword' },
 			{ include: '@symbol' }
 		],
 
 		keyword: [
-			[ /`/, { token: 'operator', next: '@escapedkeyword' } ],
-			[ /@identifier/, { cases: { '@keywords': 'keyword', '[A-Z][\a-zA-Z0-9$]*': 'type.identifier', '@default': 'identifier' } }]
+			[/`/, { token: 'operator', next: '@escapedkeyword' }],
+			[/@identifier/, {
+				cases: {
+					'@keywords': 'keyword', '[A-Z][\a-zA-Z0-9$]*': 'type.identifier',
+					'@default': 'identifier'
+				}
+			}]
 		],
 
 		escapedkeyword: [
-			[ /`/, { token: 'operator', next: '@pop' } ],
-			[ /./, 'identifier' ]
+			[/`/, { token: 'operator', next: '@pop' }],
+			[/./, 'identifier']
 		],
 
-//		symbol: [
-//			[ /@symbols/, 'operator' ],
-//			[ /@operators/, 'operator' ]
-//		],
+		//		symbol: [
+		//			[ /@symbols/, 'operator' ],
+		//			[ /@operators/, 'operator' ]
+		//		],
 
 		invokedmethod: [
-			[/([.])(@identifier)/, { cases: { '$2': ['delimeter', 'type.identifier'], '@default': '' } }],
+			[/([.])(@identifier)/, {
+				cases: {
+					'$2': ['delimeter', 'type.identifier'],
+					'@default': ''
+				}
+			}],
 		]
 	}
 };

+ 71 - 67
src/vb.ts

@@ -8,38 +8,38 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		lineComment: '\'',
 		blockComment: ['/*', '*/'],
 	},
 	brackets: [
-		['{','}'],['[',']'],['(',')'],['<','>'],
-		['addhandler','end addhandler'],
-		['class','end class'],
-		['enum','end enum'],
-		['event','end event'],
-		['function','end function'],
-		['get','end get'],
-		['if','end if'],
-		['interface','end interface'],
-		['module','end module'],
-		['namespace','end namespace'],
-		['operator','end operator'],
-		['property','end property'],
-		['raiseevent','end raiseevent'],
-		['removehandler','end removehandler'],
-		['select','end select'],
-		['set','end set'],
-		['structure','end structure'],
-		['sub','end sub'],
-		['synclock','end synclock'],
-		['try','end try'],
-		['while','end while'],
-		['with','end with'],
-		['using','end using'],
-		['do','loop'],
-		['for','next']
+		['{', '}'], ['[', ']'], ['(', ')'], ['<', '>'],
+		['addhandler', 'end addhandler'],
+		['class', 'end class'],
+		['enum', 'end enum'],
+		['event', 'end event'],
+		['function', 'end function'],
+		['get', 'end get'],
+		['if', 'end if'],
+		['interface', 'end interface'],
+		['module', 'end module'],
+		['namespace', 'end namespace'],
+		['operator', 'end operator'],
+		['property', 'end property'],
+		['raiseevent', 'end raiseevent'],
+		['removehandler', 'end removehandler'],
+		['select', 'end select'],
+		['set', 'end set'],
+		['structure', 'end structure'],
+		['sub', 'end sub'],
+		['synclock', 'end synclock'],
+		['try', 'end try'],
+		['while', 'end while'],
+		['with', 'end with'],
+		['using', 'end using'],
+		['do', 'loop'],
+		['for', 'next']
 	],
 	autoClosingPairs: [
 		{ open: '{', close: '}', notIn: ['string', 'comment'] },
@@ -50,41 +50,41 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.vb',
 	ignoreCase: true,
 
 	brackets: [
-		{ token:'delimiter.bracket', open: '{', close: '}'},
-		{ token:'delimiter.array', open: '[', close: ']'},
-		{ token:'delimiter.parenthesis', open: '(', close: ')'},
-		{ token:'delimiter.angle', open: '<', close: '>'},
+		{ token: 'delimiter.bracket', open: '{', close: '}' },
+		{ token: 'delimiter.array', open: '[', close: ']' },
+		{ token: 'delimiter.parenthesis', open: '(', close: ')' },
+		{ token: 'delimiter.angle', open: '<', close: '>' },
 
 		// Special bracket statement pairs
 		// according to https://msdn.microsoft.com/en-us/library/tsw2a11z.aspx
-		{ token: 'keyword.tag-addhandler', open: 'addhandler', close: 'end addhandler'},
-		{ token: 'keyword.tag-class', open: 'class', close: 'end class'},
-		{ token: 'keyword.tag-enum', open: 'enum', close: 'end enum'},
-		{ token: 'keyword.tag-event', open: 'event', close: 'end event'},
-		{ token: 'keyword.tag-function', open: 'function', close: 'end function'},
-		{ token: 'keyword.tag-get', open: 'get', close: 'end get'},
-		{ token: 'keyword.tag-if', open: 'if', close: 'end if'},
-		{ token: 'keyword.tag-interface', open: 'interface', close: 'end interface'},
-		{ token: 'keyword.tag-module', open: 'module', close: 'end module'},
-		{ token: 'keyword.tag-namespace', open: 'namespace', close: 'end namespace'},
-		{ token: 'keyword.tag-operator', open: 'operator', close: 'end operator'},
-		{ token: 'keyword.tag-property', open: 'property', close: 'end property'},
-		{ token: 'keyword.tag-raiseevent', open: 'raiseevent', close: 'end raiseevent'},
-		{ token: 'keyword.tag-removehandler', open: 'removehandler', close: 'end removehandler'},
-		{ token: 'keyword.tag-select', open: 'select', close: 'end select'},
-		{ token: 'keyword.tag-set', open: 'set', close: 'end set'},
-		{ token: 'keyword.tag-structure', open: 'structure', close: 'end structure'},
-		{ token: 'keyword.tag-sub', open: 'sub', close: 'end sub'},
-		{ token: 'keyword.tag-synclock', open: 'synclock', close: 'end synclock'},
-		{ token: 'keyword.tag-try', open: 'try', close: 'end try'},
-		{ token: 'keyword.tag-while', open: 'while', close: 'end while'},
-		{ token: 'keyword.tag-with', open: 'with', close: 'end with'},
+		{ token: 'keyword.tag-addhandler', open: 'addhandler', close: 'end addhandler' },
+		{ token: 'keyword.tag-class', open: 'class', close: 'end class' },
+		{ token: 'keyword.tag-enum', open: 'enum', close: 'end enum' },
+		{ token: 'keyword.tag-event', open: 'event', close: 'end event' },
+		{ token: 'keyword.tag-function', open: 'function', close: 'end function' },
+		{ token: 'keyword.tag-get', open: 'get', close: 'end get' },
+		{ token: 'keyword.tag-if', open: 'if', close: 'end if' },
+		{ token: 'keyword.tag-interface', open: 'interface', close: 'end interface' },
+		{ token: 'keyword.tag-module', open: 'module', close: 'end module' },
+		{ token: 'keyword.tag-namespace', open: 'namespace', close: 'end namespace' },
+		{ token: 'keyword.tag-operator', open: 'operator', close: 'end operator' },
+		{ token: 'keyword.tag-property', open: 'property', close: 'end property' },
+		{ token: 'keyword.tag-raiseevent', open: 'raiseevent', close: 'end raiseevent' },
+		{ token: 'keyword.tag-removehandler', open: 'removehandler', close: 'end removehandler' },
+		{ token: 'keyword.tag-select', open: 'select', close: 'end select' },
+		{ token: 'keyword.tag-set', open: 'set', close: 'end set' },
+		{ token: 'keyword.tag-structure', open: 'structure', close: 'end structure' },
+		{ token: 'keyword.tag-sub', open: 'sub', close: 'end sub' },
+		{ token: 'keyword.tag-synclock', open: 'synclock', close: 'end synclock' },
+		{ token: 'keyword.tag-try', open: 'try', close: 'end try' },
+		{ token: 'keyword.tag-while', open: 'while', close: 'end while' },
+		{ token: 'keyword.tag-with', open: 'with', close: 'end with' },
 
 		// Other pairs
 		{ token: 'keyword.tag-using', open: 'using', close: 'end using' },
@@ -117,8 +117,8 @@ export var language = <ILanguage> {
 	],
 
 	// 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})/,
+	symbols: /[=><!~?;\.,:&|+\-*\/\^%]+/,
+	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
 	integersuffix: /U?[DI%L&S@]?/,
 	floatsuffix: /[R#F!]?/,
 
@@ -130,16 +130,20 @@ export var language = <ILanguage> {
 			{ include: '@whitespace' },
 
 			// special ending tag-words
-			[/next(?!\w)/, { token: 'keyword.tag-for'}],
+			[/next(?!\w)/, { token: 'keyword.tag-for' }],
 			[/loop(?!\w)/, { token: 'keyword.tag-do' }],
 
 			// usual ending tags
 			[/end\s+(?!for|do)([a-zA-Z_]\w*)/, { token: 'keyword.tag-$1' }],
 
 			// identifiers, tagwords, and keywords
-			[/[a-zA-Z_]\w*/, { cases: { '@tagwords': {token:'keyword.tag-$0'},
-										'@keywords': {token:'keyword.$0'},
-										'@default': 'identifier' } }],
+			[/[a-zA-Z_]\w*/, {
+				cases: {
+					'@tagwords': { token: 'keyword.tag-$0' },
+					'@keywords': { token: 'keyword.$0' },
+					'@default': 'identifier'
+				}
+			}],
 
 			// Preprocessor directive
 			[/^\s*#\w+/, 'keyword'],
@@ -159,21 +163,21 @@ export var language = <ILanguage> {
 			[/@symbols/, 'delimiter'],
 
 			// strings
-			[/"([^"\\]|\\.)*$/, 'string.invalid' ],  // non-teminated string
-			[/"/,  'string', '@string' ],
+			[/"([^"\\]|\\.)*$/, 'string.invalid'],  // non-teminated string
+			[/"/, 'string', '@string'],
 
 		],
 
 		whitespace: [
 			[/[ \t\r\n]+/, ''],
-			[/(\'|REM(?!\w)).*$/,        'comment'],
+			[/(\'|REM(?!\w)).*$/, 'comment'],
 		],
 
 		string: [
-			[/[^\\"]+/,  'string'],
+			[/[^\\"]+/, 'string'],
 			[/@escapes/, 'string.escape'],
-			[/\\./,      'string.escape.invalid'],
-			[/"C?/,        'string', '@pop' ]
+			[/\\./, 'string.escape.invalid'],
+			[/"C?/, 'string', '@pop']
 		],
 	},
-};
+};

+ 8 - 8
src/xml.ts

@@ -8,12 +8,12 @@
 import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
 import ILanguage = monaco.languages.IMonarchLanguage;
 
-export var conf:IRichLanguageConfiguration = {
+export var conf: IRichLanguageConfiguration = {
 	comments: {
 		blockComment: ['<!--', '-->'],
 	},
 	brackets: [
-		['<','>']
+		['<', '>']
 	],
 	autoClosingPairs: [
 		{ open: '<', close: '>' },
@@ -27,7 +27,7 @@ export var conf:IRichLanguageConfiguration = {
 	]
 };
 
-export var language = <ILanguage> {
+export var language = <ILanguage>{
 	defaultToken: '',
 	tokenPostfix: '.xml',
 
@@ -77,7 +77,7 @@ export var language = <ILanguage> {
 		],
 
 		tag: [
-			[/[ \t\r\n]+/, '' ],
+			[/[ \t\r\n]+/, ''],
 			[/(@qualifiedName)(\s*=\s*)("[^"]*"|'[^']*')/, ['attribute.name', '', 'attribute.value']],
 			[/(@qualifiedName)(\s*=\s*)("[^">?\/]*|'[^'>?\/]*)(?=[\?\/]\>)/, ['attribute.name', '', 'attribute.value']],
 			[/(@qualifiedName)(\s*=\s*)("[^">]*|'[^'>]*)/, ['attribute.name', '', 'attribute.value']],
@@ -95,10 +95,10 @@ export var language = <ILanguage> {
 		],
 
 		comment: [
-			[/[^<\-]+/, 'comment.content' ],
-			[/-->/,  { token: 'comment', next: '@pop' } ],
+			[/[^<\-]+/, 'comment.content'],
+			[/-->/, { token: 'comment', next: '@pop' }],
 			[/<!--/, 'comment.content.invalid'],
-			[/[<\-]/, 'comment.content' ]
+			[/[<\-]/, 'comment.content']
 		],
 	},
-};
+};

+ 67 - 42
src/yaml.ts

@@ -26,7 +26,7 @@ export const conf: IRichLanguageConfiguration = {
 	],
 };
 
-export const language = <ILanguage> {
+export const language = <ILanguage>{
 	tokenPostfix: '.yaml',
 
 	brackets: [
@@ -48,8 +48,8 @@ export const language = <ILanguage> {
 
 	tokenizer: {
 		root: [
-			{include: '@whitespace'},
-			{include: '@comment'},
+			{ include: '@whitespace' },
+			{ include: '@comment' },
 
 			// Directive
 			[/%[^ ]+.*$/, 'meta.directive'],
@@ -61,33 +61,38 @@ export const language = <ILanguage> {
 			// Block Structure Indicators
 			[/[-?:](?= )/, 'operators'],
 
-			{include: '@anchor'},
-			{include: '@tagHandle'},
-			{include: '@flowCollections'},
-			{include: '@blockStyle'},
+			{ include: '@anchor' },
+			{ include: '@tagHandle' },
+			{ include: '@flowCollections' },
+			{ include: '@blockStyle' },
 
 			// Numbers
-			[/@numberInteger(?![ \t]*\S+)/,  'number'],
-			[/@numberFloat(?![ \t]*\S+)/,    'number.float'],
-			[/@numberOctal(?![ \t]*\S+)/,    'number.octal'],
-			[/@numberHex(?![ \t]*\S+)/,      'number.hex'],
+			[/@numberInteger(?![ \t]*\S+)/, 'number'],
+			[/@numberFloat(?![ \t]*\S+)/, 'number.float'],
+			[/@numberOctal(?![ \t]*\S+)/, 'number.octal'],
+			[/@numberHex(?![ \t]*\S+)/, 'number.hex'],
 			[/@numberInfinity(?![ \t]*\S+)/, 'number.infinity'],
-			[/@numberNaN(?![ \t]*\S+)/,      'number.nan'],
-			[/@numberDate(?![ \t]*\S+)/,     'number.date'],
+			[/@numberNaN(?![ \t]*\S+)/, 'number.nan'],
+			[/@numberDate(?![ \t]*\S+)/, 'number.date'],
 
 			// Key:Value pair
 			[/(".*?"|'.*?'|.*?)([ \t]*)(:)( |$)/, ['type', 'white', 'operators', 'white']],
 
-			{include: '@flowScalars'},
+			{ include: '@flowScalars' },
 
 			// String nodes
-			[/.+$/, {cases: {'@keywords': 'keyword', '@default': 'string'}}]
+			[/.+$/, {
+				cases: {
+					'@keywords': 'keyword',
+					'@default': 'string'
+				}
+			}]
 		],
 
 		// Flow Collection: Flow Mapping
 		object: [
-			{include: '@whitespace'},
-			{include: '@comment'},
+			{ include: '@whitespace' },
+			{ include: '@comment' },
 
 			// Flow Mapping termination
 			[/\}/, '@brackets', '@pop'],
@@ -102,22 +107,27 @@ export const language = <ILanguage> {
 			[/(?:".*?"|'.*?'|[^,\{\[]+?)(?=: )/, 'type'],
 
 			// Start Flow Style
-			{include: '@flowCollections'},
-			{include: '@flowScalars'},
+			{ include: '@flowCollections' },
+			{ include: '@flowScalars' },
 
 			// Scalar Data types
-			{include: '@tagHandle'},
-			{include: '@anchor'},
-			{include: '@flowNumber'},
+			{ include: '@tagHandle' },
+			{ include: '@anchor' },
+			{ include: '@flowNumber' },
 
 			// Other value (keyword or string)
-			[/[^\},]+/, {cases: {'@keywords': 'keyword', '@default': 'string'}}]
+			[/[^\},]+/, {
+				cases: {
+					'@keywords': 'keyword',
+					'@default': 'string'
+				}
+			}]
 		],
 
 		// Flow Collection: Flow Sequence
 		array: [
-			{include: '@whitespace'},
-			{include: '@comment'},
+			{ include: '@whitespace' },
+			{ include: '@comment' },
 
 			// Flow Sequence termination
 			[/\]/, '@brackets', '@pop'],
@@ -126,24 +136,34 @@ export const language = <ILanguage> {
 			[/,/, 'delimiter.comma'],
 
 			// Start Flow Style
-			{include: '@flowCollections'},
-			{include: '@flowScalars'},
+			{ include: '@flowCollections' },
+			{ include: '@flowScalars' },
 
 			// Scalar Data types
-			{include: '@tagHandle'},
-			{include: '@anchor'},
-			{include: '@flowNumber'},
+			{ include: '@tagHandle' },
+			{ include: '@anchor' },
+			{ include: '@flowNumber' },
 
 			// Other value (keyword or string)
-			[/[^\],]+/, {cases: {'@keywords': 'keyword', '@default': 'string'}}]
+			[/[^\],]+/, {
+				cases: {
+					'@keywords': 'keyword',
+					'@default': 'string'
+				}
+			}]
 		],
 
 		// Flow Scalars (quoted strings)
 		string: [
 			[/[^\\"']+/, 'string'],
 			[/@escapes/, 'string.escape'],
-			[/\\./,      'string.escape.invalid'],
-			[/["']/,     {cases: {'$#==$S2': {token: 'string', next: '@pop'}, '@default': 'string'}}]
+			[/\\./, 'string.escape.invalid'],
+			[/["']/, {
+				cases: {
+					'$#==$S2': { token: 'string', next: '@pop' },
+					'@default': 'string'
+				}
+			}]
 		],
 
 		// First line of a Block Style
@@ -154,7 +174,12 @@ export const language = <ILanguage> {
 		// Further lines of a Block Style
 		//   Workaround for indentation detection
 		multiStringContinued: [
-			[/^( *).+$/, {cases: {'$1==$S2': 'string', '@default': {token: '@rematch', next: '@popall'}}}]
+			[/^( *).+$/, {
+				cases: {
+					'$1==$S2': 'string',
+					'@default': { token: '@rematch', next: '@popall' }
+				}
+			}]
 		],
 
 		whitespace: [
@@ -174,8 +199,8 @@ export const language = <ILanguage> {
 
 		// Start Flow Scalars (quoted strings)
 		flowScalars: [
-			[/"/,  'string', '@string."'],
-			[/'/,  'string', '@string.\'']
+			[/"/, 'string', '@string."'],
+			[/'/, 'string', '@string.\'']
 		],
 
 		// Start Block Scalar
@@ -185,13 +210,13 @@ export const language = <ILanguage> {
 
 		// Numbers in Flow Collections (terminate with ,]})
 		flowNumber: [
-			[/@numberInteger(?=[ \t]*[,\]\}])/,  'number'],
-			[/@numberFloat(?=[ \t]*[,\]\}])/,    'number.float'],
-			[/@numberOctal(?=[ \t]*[,\]\}])/,    'number.octal'],
-			[/@numberHex(?=[ \t]*[,\]\}])/,      'number.hex'],
+			[/@numberInteger(?=[ \t]*[,\]\}])/, 'number'],
+			[/@numberFloat(?=[ \t]*[,\]\}])/, 'number.float'],
+			[/@numberOctal(?=[ \t]*[,\]\}])/, 'number.octal'],
+			[/@numberHex(?=[ \t]*[,\]\}])/, 'number.hex'],
 			[/@numberInfinity(?=[ \t]*[,\]\}])/, 'number.infinity'],
-			[/@numberNaN(?=[ \t]*[,\]\}])/,      'number.nan'],
-			[/@numberDate(?=[ \t]*[,\]\}])/,     'number.date']
+			[/@numberNaN(?=[ \t]*[,\]\}])/, 'number.nan'],
+			[/@numberDate(?=[ \t]*[,\]\}])/, 'number.date']
 		],
 
 		tagHandle: [

+ 327 - 275
test/bat.test.ts

@@ -4,329 +4,381 @@
  *--------------------------------------------------------------------------------------------*/
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('bat', [
 	// Keywords
 	[{
-	line: '@echo off title Selfhost',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.bat' },
-		{ startIndex: 1, type: 'keyword.echo.bat' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 10, type: 'keyword.title.bat' },
-		{ startIndex: 15, type: '' }
-	]}],
+		line: '@echo off title Selfhost',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.bat' },
+			{ startIndex: 1, type: 'keyword.echo.bat' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 10, type: 'keyword.title.bat' },
+			{ startIndex: 15, type: '' }
+		]
+	}],
 
 	// Comments - single line
 	[{
-	line: 'REM',
-	tokens: [
-		{ startIndex: 0, type: 'comment.bat' }
-	]}],
+		line: 'REM',
+		tokens: [
+			{ startIndex: 0, type: 'comment.bat' }
+		]
+	}],
 
 	[{
-	line: '    REM a comment',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'comment.bat' }
-	]}],
+		line: '    REM a comment',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'comment.bat' }
+		]
+	}],
 
 	[{
-	line: 'REM a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.bat' }
-	]}],
+		line: 'REM a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.bat' }
+		]
+	}],
 
 	[{
-	line: 'REMnot a comment',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}],
+		line: 'REMnot a comment',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}],
 
 	// number
 	[{
-	line: '0',
-	tokens: [
-		{ startIndex: 0, type: 'number.bat' }
-	]}],
+		line: '0',
+		tokens: [
+			{ startIndex: 0, type: 'number.bat' }
+		]
+	}],
 
 	[{
-	line: '0.0',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.bat' }
-	]}],
+		line: '0.0',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.bat' }
+		]
+	}],
 
 	[{
-	line: '0x123',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.bat' }
-	]}],
+		line: '0x123',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.bat' }
+		]
+	}],
 
 	[{
-	line: '23.5',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.bat' }
-	]}],
+		line: '23.5',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.bat' }
+		]
+	}],
 
 	[{
-	line: '23.5e3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.bat' }
-	]}],
+		line: '23.5e3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.bat' }
+		]
+	}],
 
 	[{
-	line: '23.5E3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.bat' }
-	]}],
+		line: '23.5E3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.bat' }
+		]
+	}],
 
 	[{
-	line: '1.72e-3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.bat' }
-	]}],
+		line: '1.72e-3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.bat' }
+		]
+	}],
 
 	[{
-	line: '0+0',
-	tokens: [
-		{ startIndex: 0, type: 'number.bat' },
-		{ startIndex: 1, type: 'delimiter.bat' },
-		{ startIndex: 2, type: 'number.bat' }
-	]}],
+		line: '0+0',
+		tokens: [
+			{ startIndex: 0, type: 'number.bat' },
+			{ startIndex: 1, type: 'delimiter.bat' },
+			{ startIndex: 2, type: 'number.bat' }
+		]
+	}],
 
 	[{
-	line: '100+10',
-	tokens: [
-		{ startIndex: 0, type: 'number.bat' },
-		{ startIndex: 3, type: 'delimiter.bat' },
-		{ startIndex: 4, type: 'number.bat' }
-	]}],
+		line: '100+10',
+		tokens: [
+			{ startIndex: 0, type: 'number.bat' },
+			{ startIndex: 3, type: 'delimiter.bat' },
+			{ startIndex: 4, type: 'number.bat' }
+		]
+	}],
 
 	[{
-	line: '0 + 0',
-	tokens: [
-		{ startIndex: 0, type: 'number.bat' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.bat' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.bat' }
-	]}],
+		line: '0 + 0',
+		tokens: [
+			{ startIndex: 0, type: 'number.bat' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.bat' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.bat' }
+		]
+	}],
 
 	// Strings
 	[{
-	line: 'set s = "string"',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.set.bat' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 6, type: 'delimiter.bat' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'string.bat' }
-	]}],
+		line: 'set s = "string"',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.set.bat' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 6, type: 'delimiter.bat' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'string.bat' }
+		]
+	}],
 
 	[{
-	line: '"use strict";',
-	tokens: [
-		{ startIndex: 0, type: 'string.bat' },
-		{ startIndex: 12, type: 'delimiter.bat' }
-	]}],
+		line: '"use strict";',
+		tokens: [
+			{ startIndex: 0, type: 'string.bat' },
+			{ startIndex: 12, type: 'delimiter.bat' }
+		]
+	}],
 
 	// Tags
 	[{
-	line: 'setlocal endlocal',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.tag-setlocal.bat' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'keyword.tag-setlocal.bat' }
-	]}],
+		line: 'setlocal endlocal',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.tag-setlocal.bat' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'keyword.tag-setlocal.bat' }
+		]
+	}],
 
 	[{
-	line: 'setlocal ENDLOCAL',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.tag-setlocal.bat' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'keyword.tag-setlocal.bat' }
-	]}],
+		line: 'setlocal ENDLOCAL',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.tag-setlocal.bat' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'keyword.tag-setlocal.bat' }
+		]
+	}],
 
 	[{
-	line: 'SETLOCAL endlocal',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.tag-setlocal.bat' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'keyword.tag-setlocal.bat' }
-	]}],
+		line: 'SETLOCAL endlocal',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.tag-setlocal.bat' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'keyword.tag-setlocal.bat' }
+		]
+	}],
 
 	[{
-	line: 'setlocal setlocal endlocal',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.tag-setlocal.bat' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'keyword.tag-setlocal.bat' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: 'keyword.tag-setlocal.bat' }
-	]}],
+		line: 'setlocal setlocal endlocal',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.tag-setlocal.bat' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'keyword.tag-setlocal.bat' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'keyword.tag-setlocal.bat' }
+		]
+	}],
 
 	// Monarch generated
 	[{
-	line: 'rem asdf',
-	tokens: [
-		{ startIndex: 0, type: 'comment.bat' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'REM',
-	tokens: [
-		{ startIndex: 0, type: 'comment.bat' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'REMOVED not a comment really',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'keyword.not.bat' },
-		{ startIndex: 11, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'echo cool',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.echo.bat' },
-		{ startIndex: 4, type: '' }
-	]}, {
-	line: '@echo off',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.bat' },
-		{ startIndex: 1, type: 'keyword.echo.bat' },
-		{ startIndex: 5, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'setlocAL',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.tag-setlocal.bat' }
-	]}, {
-	line: '	asdf',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '	asdf',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: 'endLocaL',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.tag-setlocal.bat' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'call',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.call.bat' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: ':MyLabel',
-	tokens: [
-		{ startIndex: 0, type: 'metatag.bat' }
-	]}, {
-	line: 'some command',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '%sdfsdf% ',
-	tokens: [
-		{ startIndex: 0, type: 'variable.bat' },
-		{ startIndex: 8, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'this is "a string %sdf% asdf"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'string.bat' },
-		{ startIndex: 18, type: 'variable.bat' },
-		{ startIndex: 23, type: 'string.bat' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'FOR %%A IN (1 2 3) DO (',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.for.bat' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'variable.bat' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 11, type: 'delimiter.parenthesis.bat' },
-		{ startIndex: 12, type: 'number.bat' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'number.bat' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'number.bat' },
-		{ startIndex: 17, type: 'delimiter.parenthesis.bat' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 22, type: 'delimiter.parenthesis.bat' }
-	]}, {
-	line: '	SET VAR1=%VAR1%%%A',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'keyword.set.bat' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 9, type: 'delimiter.bat' },
-		{ startIndex: 10, type: 'variable.bat' }
-	]}, {
-	line: '	SET VAR2=%VAR2%%%A',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'keyword.set.bat' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 9, type: 'delimiter.bat' },
-		{ startIndex: 10, type: 'variable.bat' }
-	]}, {
-	line: '	use \'string %%a asdf asdf\'',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: 'string.bat' },
-		{ startIndex: 13, type: 'variable.bat' },
-		{ startIndex: 16, type: 'string.bat' }
-	]}, {
-	line: '	non terminated "string %%aaa sdf',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 16, type: 'string.bat' },
-		{ startIndex: 24, type: 'variable.bat' },
-		{ startIndex: 29, type: 'string.bat' }
-	]}, {
-	line: '	this shold NOT BE red',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 12, type: 'keyword.not.bat' },
-		{ startIndex: 15, type: '' }
-	]}, {
-	line: ')',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.parenthesis.bat' }
-	]}]
-]);
+		line: 'rem asdf',
+		tokens: [
+			{ startIndex: 0, type: 'comment.bat' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'REM',
+		tokens: [
+			{ startIndex: 0, type: 'comment.bat' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'REMOVED not a comment really',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'keyword.not.bat' },
+			{ startIndex: 11, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'echo cool',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.echo.bat' },
+			{ startIndex: 4, type: '' }
+		]
+	}, {
+		line: '@echo off',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.bat' },
+			{ startIndex: 1, type: 'keyword.echo.bat' },
+			{ startIndex: 5, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'setlocAL',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.tag-setlocal.bat' }
+		]
+	}, {
+		line: '	asdf',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '	asdf',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: 'endLocaL',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.tag-setlocal.bat' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'call',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.call.bat' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: ':MyLabel',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.bat' }
+		]
+	}, {
+		line: 'some command',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '%sdfsdf% ',
+		tokens: [
+			{ startIndex: 0, type: 'variable.bat' },
+			{ startIndex: 8, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'this is "a string %sdf% asdf"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'string.bat' },
+			{ startIndex: 18, type: 'variable.bat' },
+			{ startIndex: 23, type: 'string.bat' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'FOR %%A IN (1 2 3) DO (',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.for.bat' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'variable.bat' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 11, type: 'delimiter.parenthesis.bat' },
+			{ startIndex: 12, type: 'number.bat' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'number.bat' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'number.bat' },
+			{ startIndex: 17, type: 'delimiter.parenthesis.bat' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 22, type: 'delimiter.parenthesis.bat' }
+		]
+	}, {
+		line: '	SET VAR1=%VAR1%%%A',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'keyword.set.bat' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 9, type: 'delimiter.bat' },
+			{ startIndex: 10, type: 'variable.bat' }
+		]
+	}, {
+		line: '	SET VAR2=%VAR2%%%A',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'keyword.set.bat' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 9, type: 'delimiter.bat' },
+			{ startIndex: 10, type: 'variable.bat' }
+		]
+	}, {
+		line: '	use \'string %%a asdf asdf\'',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'string.bat' },
+			{ startIndex: 13, type: 'variable.bat' },
+			{ startIndex: 16, type: 'string.bat' }
+		]
+	}, {
+		line: '	non terminated "string %%aaa sdf',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 16, type: 'string.bat' },
+			{ startIndex: 24, type: 'variable.bat' },
+			{ startIndex: 29, type: 'string.bat' }
+		]
+	}, {
+		line: '	this shold NOT BE red',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 12, type: 'keyword.not.bat' },
+			{ startIndex: 15, type: '' }
+		]
+	}, {
+		line: ')',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.parenthesis.bat' }
+		]
+	}]
+]);

+ 2188 - 1929
test/coffee.test.ts

@@ -5,1979 +5,2238 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('coffeescript', [
 	// Comments
 	[{
-	line: '#',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}],
-
-	[{
-	line: '    # a comment',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'comment.coffee' }
-	]}],
-
-	[{
-	line: '# a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}],
-
-	[{
-	line: '#sticky comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}],
-
-	[{
-	line: 'x = 1 # my comment # is a nice one',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.coffee' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'comment.coffee' }
-	]}],
-
-	[{
-	line: 'x = 1e #is a exponent number',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.float.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'comment.coffee' }
-	]}],
-
-	[{
-	line: 'x = 0x1F #is a hex number',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.hex.coffee' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'comment.coffee' }
-	]}],
+		line: '#',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}],
+
+	[{
+		line: '    # a comment',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'comment.coffee' }
+		]
+	}],
+
+	[{
+		line: '# a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}],
+
+	[{
+		line: '#sticky comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}],
+
+	[{
+		line: 'x = 1 # my comment # is a nice one',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.coffee' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.coffee' }
+		]
+	}],
+
+	[{
+		line: 'x = 1e #is a exponent number',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.float.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'comment.coffee' }
+		]
+	}],
+
+	[{
+		line: 'x = 0x1F #is a hex number',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.hex.coffee' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'comment.coffee' }
+		]
+	}],
 
 	// Keywords
 	[{
-	line: 'new x = switch()',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.new.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'keyword.switch.coffee' },
-		{ startIndex: 14, type: 'delimiter.parenthesis.coffee' }
-	]}],
-
-	[{
-	line: '@test [do]',
-	tokens: [
-		{ startIndex: 0, type: 'variable.predefined.coffee' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.square.coffee' },
-		{ startIndex: 7, type: 'keyword.do.coffee' },
-		{ startIndex: 9, type: 'delimiter.square.coffee' }
-	]}],
-
-	[{
-	line: 'this do',
-	tokens: [
-		{ startIndex: 0, type: 'variable.predefined.coffee' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'keyword.do.coffee' }
-	]}],
-
-	[{
-	line: '    new    ',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.new.coffee' },
-		{ startIndex: 7, type: '' }
-	]}],
+		line: 'new x = switch()',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.new.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'keyword.switch.coffee' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.coffee' }
+		]
+	}],
+
+	[{
+		line: '@test [do]',
+		tokens: [
+			{ startIndex: 0, type: 'variable.predefined.coffee' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.square.coffee' },
+			{ startIndex: 7, type: 'keyword.do.coffee' },
+			{ startIndex: 9, type: 'delimiter.square.coffee' }
+		]
+	}],
+
+	[{
+		line: 'this do',
+		tokens: [
+			{ startIndex: 0, type: 'variable.predefined.coffee' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'keyword.do.coffee' }
+		]
+	}],
+
+	[{
+		line: '    new    ',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.new.coffee' },
+			{ startIndex: 7, type: '' }
+		]
+	}],
 
 	// Comments - range comment, single line
 	[{
-	line: '### a simple comment ###',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}],
-
-	[{
-	line: 'new x = ### a simple comment ### 1',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.new.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.coffee' },
-		{ startIndex: 32, type: '' },
-		{ startIndex: 33, type: 'number.coffee' }
-	]}],
-
-	[{
-	line: 'new x = ### comment ### 1 ###',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.new.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.coffee' },
-		{ startIndex: 23, type: '' },
-		{ startIndex: 24, type: 'number.coffee' },
-		{ startIndex: 25, type: '' },
-		{ startIndex: 26, type: 'comment.coffee' }
-	]}],
-
-	[{
-	line: 'x = ######s',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.coffee' },
-		{ startIndex: 10, type: '' }
-	]}],
-
-	[{
-	line: 'x = ###/',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.coffee' }
-	]}],
+		line: '### a simple comment ###',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}],
+
+	[{
+		line: 'new x = ### a simple comment ### 1',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.new.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.coffee' },
+			{ startIndex: 32, type: '' },
+			{ startIndex: 33, type: 'number.coffee' }
+		]
+	}],
+
+	[{
+		line: 'new x = ### comment ### 1 ###',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.new.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.coffee' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'number.coffee' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'comment.coffee' }
+		]
+	}],
+
+	[{
+		line: 'x = ######s',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.coffee' },
+			{ startIndex: 10, type: '' }
+		]
+	}],
+
+	[{
+		line: 'x = ###/',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.coffee' }
+		]
+	}],
 
 	// Comments - range comment, multi lines
 	[{
-	line: '### a multiline comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'can actually span',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'multiple lines ###',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}],
-
-	[{
-	line: 'new x = ### start a comment',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.new.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.coffee' }
-	]}, {
-	line: ' a ',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'and end it ### new a = 2;',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'keyword.new.coffee' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 21, type: 'delimiter.coffee' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'number.coffee' },
-		{ startIndex: 24, type: '' }
-	]}],
+		line: '### a multiline comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'can actually span',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'multiple lines ###',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}],
+
+	[{
+		line: 'new x = ### start a comment',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.new.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.coffee' }
+		]
+	}, {
+		line: ' a ',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'and end it ### new a = 2;',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'keyword.new.coffee' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 21, type: 'delimiter.coffee' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'number.coffee' },
+			{ startIndex: 24, type: '' }
+		]
+	}],
 
 	// Block Strings
 	[{
-	line: 'b(\'\'\'asdads\'\'\')',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 2, type: 'string.coffee' },
-		{ startIndex: 14, type: 'delimiter.parenthesis.coffee' }
-	]}],
-
-	[{
-	line: 'foo(""" var i = \'foo\'; """)',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 4, type: 'string.coffee' },
-		{ startIndex: 26, type: 'delimiter.parenthesis.coffee' }
-	]}],
+		line: 'b(\'\'\'asdads\'\'\')',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 2, type: 'string.coffee' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.coffee' }
+		]
+	}],
+
+	[{
+		line: 'foo(""" var i = \'foo\'; """)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 4, type: 'string.coffee' },
+			{ startIndex: 26, type: 'delimiter.parenthesis.coffee' }
+		]
+	}],
 
 	// Strings
 	[{
-	line: 'for a = \'a\';',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.for.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'string.coffee' },
-		{ startIndex: 11, type: '' }
-	]}],
-
-	[{
-	line: '"use strict";',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' },
-		{ startIndex: 12, type: '' }
-	]}],
-
-	[{
-	line: 'b = a + " \'cool\'  "',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'string.coffee' }
-	]}],
-
-	[{
-	line: '"escaping \\"quotes\\" is cool"',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' },
-		{ startIndex: 10, type: 'string.escape.coffee' },
-		{ startIndex: 12, type: 'string.coffee' },
-		{ startIndex: 18, type: 'string.escape.coffee' },
-		{ startIndex: 20, type: 'string.coffee' }
-	]}],
-
-	[{
-	line: '\'\'\'',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' }
-	]}],
-
-	[{
-	line: '\'\\\'\'',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' },
-		{ startIndex: 1, type: 'string.escape.coffee' },
-		{ startIndex: 3, type: 'string.coffee' }
-	]}],
-
-	[{
-	line: '\'be careful \\not to escape\'',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' },
-		{ startIndex: 12, type: 'string.escape.coffee' },
-		{ startIndex: 14, type: 'string.coffee' }
-	]}],
+		line: 'for a = \'a\';',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.for.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'string.coffee' },
+			{ startIndex: 11, type: '' }
+		]
+	}],
+
+	[{
+		line: '"use strict";',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' },
+			{ startIndex: 12, type: '' }
+		]
+	}],
+
+	[{
+		line: 'b = a + " \'cool\'  "',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'string.coffee' }
+		]
+	}],
+
+	[{
+		line: '"escaping \\"quotes\\" is cool"',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' },
+			{ startIndex: 10, type: 'string.escape.coffee' },
+			{ startIndex: 12, type: 'string.coffee' },
+			{ startIndex: 18, type: 'string.escape.coffee' },
+			{ startIndex: 20, type: 'string.coffee' }
+		]
+	}],
+
+	[{
+		line: '\'\'\'',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' }
+		]
+	}],
+
+	[{
+		line: '\'\\\'\'',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' },
+			{ startIndex: 1, type: 'string.escape.coffee' },
+			{ startIndex: 3, type: 'string.coffee' }
+		]
+	}],
+
+	[{
+		line: '\'be careful \\not to escape\'',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' },
+			{ startIndex: 12, type: 'string.escape.coffee' },
+			{ startIndex: 14, type: 'string.coffee' }
+		]
+	}],
 
 	// Strings - multiline
 	[{
-	line: '\'a multiline string',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' }
-	]}, {
-	line: 'second line',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' }
-	]}],
+		line: '\'a multiline string',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' }
+		]
+	}, {
+		line: 'second line',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' }
+		]
+	}],
 
 	// Strings - with nested code
 	[{
-	line: '"for a = \'a\'; #{ new } works"',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'keyword.new.coffee' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'string.coffee' }
-	]}],
-
-	[{
-	line: '"a comment with nested code #{ 2 / 3 } works"',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' },
-		{ startIndex: 30, type: '' },
-		{ startIndex: 31, type: 'number.coffee' },
-		{ startIndex: 32, type: '' },
-		{ startIndex: 33, type: 'delimiter.coffee' },
-		{ startIndex: 34, type: '' },
-		{ startIndex: 35, type: 'number.coffee' },
-		{ startIndex: 36, type: '' },
-		{ startIndex: 37, type: 'string.coffee' }
-	]}],
+		line: '"for a = \'a\'; #{ new } works"',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'keyword.new.coffee' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'string.coffee' }
+		]
+	}],
+
+	[{
+		line: '"a comment with nested code #{ 2 / 3 } works"',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'number.coffee' },
+			{ startIndex: 32, type: '' },
+			{ startIndex: 33, type: 'delimiter.coffee' },
+			{ startIndex: 34, type: '' },
+			{ startIndex: 35, type: 'number.coffee' },
+			{ startIndex: 36, type: '' },
+			{ startIndex: 37, type: 'string.coffee' }
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '0',
-	tokens: [
-		{ startIndex: 0, type: 'number.coffee' }
-	]}],
-
-	[{
-	line: ' 0',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'number.coffee' }
-	]}],
-
-	[{
-	line: ' 0 ',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'number.coffee' },
-		{ startIndex: 2, type: '' }
-	]}],
-
-	[{
-	line: '0 ',
-	tokens: [
-		{ startIndex: 0, type: 'number.coffee' },
-		{ startIndex: 1, type: '' }
-	]}],
-
-	[{
-	line: '0+0',
-	tokens: [
-		{ startIndex: 0, type: 'number.coffee' },
-		{ startIndex: 1, type: 'delimiter.coffee' },
-		{ startIndex: 2, type: 'number.coffee' }
-	]}],
-
-	[{
-	line: '100+10',
-	tokens: [
-		{ startIndex: 0, type: 'number.coffee' },
-		{ startIndex: 3, type: 'delimiter.coffee' },
-		{ startIndex: 4, type: 'number.coffee' }
-	]}],
-
-	[{
-	line: '0 + 0',
-	tokens: [
-		{ startIndex: 0, type: 'number.coffee' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.coffee' }
-	]}],
-
-	[{
-	line: '0123',
-	tokens: [
-		{ startIndex: 0, type: 'number.octal.coffee' }
-	]}],
-
-	[{
-	line: '01239',
-	tokens: [
-		{ startIndex: 0, type: 'number.coffee' }
-	]}],
-
-	[{
-	line: '0x123',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.coffee' }
-	]}],
-
-	[{
-	line: '[1,2,3]',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.square.coffee' },
-		{ startIndex: 1, type: 'number.coffee' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: 'number.coffee' },
-		{ startIndex: 4, type: 'delimiter.coffee' },
-		{ startIndex: 5, type: 'number.coffee' },
-		{ startIndex: 6, type: 'delimiter.square.coffee' }
-	]}],
-
-	[{
-	line: 'foo(123);',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 4, type: 'number.coffee' },
-		{ startIndex: 7, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 8, type: '' }
-	]}],
-
-	[{
-	line: '(a:(b:[]))',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'delimiter.coffee' },
-		{ startIndex: 6, type: 'delimiter.square.coffee' },
-		{ startIndex: 8, type: 'delimiter.parenthesis.coffee' }
-	]}],
-
-	[{
-	line: 'x = \'[{()}]\'',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'string.coffee' }
-	]}],
+		line: '0',
+		tokens: [
+			{ startIndex: 0, type: 'number.coffee' }
+		]
+	}],
+
+	[{
+		line: ' 0',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'number.coffee' }
+		]
+	}],
+
+	[{
+		line: ' 0 ',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'number.coffee' },
+			{ startIndex: 2, type: '' }
+		]
+	}],
+
+	[{
+		line: '0 ',
+		tokens: [
+			{ startIndex: 0, type: 'number.coffee' },
+			{ startIndex: 1, type: '' }
+		]
+	}],
+
+	[{
+		line: '0+0',
+		tokens: [
+			{ startIndex: 0, type: 'number.coffee' },
+			{ startIndex: 1, type: 'delimiter.coffee' },
+			{ startIndex: 2, type: 'number.coffee' }
+		]
+	}],
+
+	[{
+		line: '100+10',
+		tokens: [
+			{ startIndex: 0, type: 'number.coffee' },
+			{ startIndex: 3, type: 'delimiter.coffee' },
+			{ startIndex: 4, type: 'number.coffee' }
+		]
+	}],
+
+	[{
+		line: '0 + 0',
+		tokens: [
+			{ startIndex: 0, type: 'number.coffee' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.coffee' }
+		]
+	}],
+
+	[{
+		line: '0123',
+		tokens: [
+			{ startIndex: 0, type: 'number.octal.coffee' }
+		]
+	}],
+
+	[{
+		line: '01239',
+		tokens: [
+			{ startIndex: 0, type: 'number.coffee' }
+		]
+	}],
+
+	[{
+		line: '0x123',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.coffee' }
+		]
+	}],
+
+	[{
+		line: '[1,2,3]',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.square.coffee' },
+			{ startIndex: 1, type: 'number.coffee' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: 'number.coffee' },
+			{ startIndex: 4, type: 'delimiter.coffee' },
+			{ startIndex: 5, type: 'number.coffee' },
+			{ startIndex: 6, type: 'delimiter.square.coffee' }
+		]
+	}],
+
+	[{
+		line: 'foo(123);',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 4, type: 'number.coffee' },
+			{ startIndex: 7, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 8, type: '' }
+		]
+	}],
+
+	[{
+		line: '(a:(b:[]))',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'delimiter.coffee' },
+			{ startIndex: 6, type: 'delimiter.square.coffee' },
+			{ startIndex: 8, type: 'delimiter.parenthesis.coffee' }
+		]
+	}],
+
+	[{
+		line: 'x = \'[{()}]\'',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'string.coffee' }
+		]
+	}],
 
 	// Regular Expressions
 	[{
-	line: '#',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}],
-
-	[{
-	line: '/ /',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' }
-	]}],
-
-	[{
-	line: '/abc\\/asd/',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' }
-	]}],
-
-	[{
-	line: 'new r = /sweet"regular exp" \\/ cool/;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.new.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'regexp.coffee' },
-		{ startIndex: 36, type: '' }
-	]}],
-
-	[{
-	line: '5 / 3;',
-	tokens: [
-		{ startIndex: 0, type: 'number.coffee' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.coffee' },
-		{ startIndex: 5, type: '' }
-	]}],
+		line: '#',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}],
+
+	[{
+		line: '/ /',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' }
+		]
+	}],
+
+	[{
+		line: '/abc\\/asd/',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' }
+		]
+	}],
+
+	[{
+		line: 'new r = /sweet"regular exp" \\/ cool/;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.new.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'regexp.coffee' },
+			{ startIndex: 36, type: '' }
+		]
+	}],
+
+	[{
+		line: '5 / 3;',
+		tokens: [
+			{ startIndex: 0, type: 'number.coffee' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.coffee' },
+			{ startIndex: 5, type: '' }
+		]
+	}],
 
 	// Regex - range regex, multi lines
 	[{
-	line: '/// a multiline regex',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' }
-	]}, {
-	line: 'can actually span',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' }
-	]}, {
-	line: 'multiplelines with # comments',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' },
-		{ startIndex: 19, type: 'comment.coffee' }
-	]}, {
-	line: 'multiple lines ///',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' }
-	]}],
+		line: '/// a multiline regex',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' }
+		]
+	}, {
+		line: 'can actually span',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' }
+		]
+	}, {
+		line: 'multiplelines with # comments',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' },
+			{ startIndex: 19, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'multiple lines ///',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' }
+		]
+	}],
 
 	// Regex - multi lines followed by #comment
 	[{
-	line: '///',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' }
-	]}, {
-	line: '#comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}],
+		line: '///',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' }
+		]
+	}, {
+		line: '#comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}],
 
 	// Advanced regular expressions
 	[{
-	line: '1 / 2; # comment',
-	tokens: [
-		{ startIndex: 0, type: 'number.coffee' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.coffee' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 7, type: 'comment.coffee' }
-	]}],
-
-	[{
-	line: '1 / 2 / x / b;',
-	tokens: [
-		{ startIndex: 0, type: 'number.coffee' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.coffee' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 10, type: 'delimiter.coffee' },
-		{ startIndex: 11, type: '' }
-	]}],
-
-	[{
-	line: 'a /ads/ b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' }
-	]}],
-
-	[{
-	line: 'x = /foo/.test(\'\')',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'regexp.coffee' },
-		{ startIndex: 9, type: 'delimiter.coffee' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 14, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 15, type: 'string.coffee' },
-		{ startIndex: 17, type: 'delimiter.parenthesis.coffee' }
-	]}],
-
-	[{
-	line: 'x = 1 + f(2 / 3, /foo/)',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.coffee' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 9, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 10, type: 'number.coffee' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'delimiter.coffee' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'number.coffee' },
-		{ startIndex: 15, type: 'delimiter.coffee' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'regexp.coffee' },
-		{ startIndex: 22, type: 'delimiter.parenthesis.coffee' }
-	]}],
-
-	[{
-	line: '1/(2/3)/2/3;',
-	tokens: [
-		{ startIndex: 0, type: 'number.coffee' },
-		{ startIndex: 1, type: 'delimiter.coffee' },
-		{ startIndex: 2, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 3, type: 'number.coffee' },
-		{ startIndex: 4, type: 'delimiter.coffee' },
-		{ startIndex: 5, type: 'number.coffee' },
-		{ startIndex: 6, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 7, type: 'delimiter.coffee' },
-		{ startIndex: 8, type: 'number.coffee' },
-		{ startIndex: 9, type: 'delimiter.coffee' },
-		{ startIndex: 10, type: 'number.coffee' },
-		{ startIndex: 11, type: '' }
-	]}],
-
-	[{
-	line: '{ key: 123 }',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.coffee' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 5, type: 'delimiter.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'number.coffee' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'delimiter.curly.coffee' }
-	]}],
-
-	[{
-	line: '[1,2,3]',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.square.coffee' },
-		{ startIndex: 1, type: 'number.coffee' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: 'number.coffee' },
-		{ startIndex: 4, type: 'delimiter.coffee' },
-		{ startIndex: 5, type: 'number.coffee' },
-		{ startIndex: 6, type: 'delimiter.square.coffee' }
-	]}],
-
-	[{
-	line: 'foo(123);',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 4, type: 'number.coffee' },
-		{ startIndex: 7, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 8, type: '' }
-	]}],
-
-	[{
-	line: '{a:{b:[]}}',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.coffee' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: 'delimiter.curly.coffee' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'delimiter.coffee' },
-		{ startIndex: 6, type: 'delimiter.square.coffee' },
-		{ startIndex: 8, type: 'delimiter.curly.coffee' }
-	]}],
-
-	[{
-	line: 'x = \'[{()}]\'',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.coffee' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'string.coffee' }
-	]}],
+		line: '1 / 2; # comment',
+		tokens: [
+			{ startIndex: 0, type: 'number.coffee' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.coffee' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 7, type: 'comment.coffee' }
+		]
+	}],
+
+	[{
+		line: '1 / 2 / x / b;',
+		tokens: [
+			{ startIndex: 0, type: 'number.coffee' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.coffee' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 10, type: 'delimiter.coffee' },
+			{ startIndex: 11, type: '' }
+		]
+	}],
+
+	[{
+		line: 'a /ads/ b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' }
+		]
+	}],
+
+	[{
+		line: 'x = /foo/.test(\'\')',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'regexp.coffee' },
+			{ startIndex: 9, type: 'delimiter.coffee' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 15, type: 'string.coffee' },
+			{ startIndex: 17, type: 'delimiter.parenthesis.coffee' }
+		]
+	}],
+
+	[{
+		line: 'x = 1 + f(2 / 3, /foo/)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.coffee' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 9, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 10, type: 'number.coffee' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'delimiter.coffee' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'number.coffee' },
+			{ startIndex: 15, type: 'delimiter.coffee' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'regexp.coffee' },
+			{ startIndex: 22, type: 'delimiter.parenthesis.coffee' }
+		]
+	}],
+
+	[{
+		line: '1/(2/3)/2/3;',
+		tokens: [
+			{ startIndex: 0, type: 'number.coffee' },
+			{ startIndex: 1, type: 'delimiter.coffee' },
+			{ startIndex: 2, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 3, type: 'number.coffee' },
+			{ startIndex: 4, type: 'delimiter.coffee' },
+			{ startIndex: 5, type: 'number.coffee' },
+			{ startIndex: 6, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 7, type: 'delimiter.coffee' },
+			{ startIndex: 8, type: 'number.coffee' },
+			{ startIndex: 9, type: 'delimiter.coffee' },
+			{ startIndex: 10, type: 'number.coffee' },
+			{ startIndex: 11, type: '' }
+		]
+	}],
+
+	[{
+		line: '{ key: 123 }',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.coffee' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 5, type: 'delimiter.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'number.coffee' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'delimiter.curly.coffee' }
+		]
+	}],
+
+	[{
+		line: '[1,2,3]',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.square.coffee' },
+			{ startIndex: 1, type: 'number.coffee' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: 'number.coffee' },
+			{ startIndex: 4, type: 'delimiter.coffee' },
+			{ startIndex: 5, type: 'number.coffee' },
+			{ startIndex: 6, type: 'delimiter.square.coffee' }
+		]
+	}],
+
+	[{
+		line: 'foo(123);',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 4, type: 'number.coffee' },
+			{ startIndex: 7, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 8, type: '' }
+		]
+	}],
+
+	[{
+		line: '{a:{b:[]}}',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.coffee' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: 'delimiter.curly.coffee' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'delimiter.coffee' },
+			{ startIndex: 6, type: 'delimiter.square.coffee' },
+			{ startIndex: 8, type: 'delimiter.curly.coffee' }
+		]
+	}],
+
+	[{
+		line: 'x = \'[{()}]\'',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.coffee' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'string.coffee' }
+		]
+	}],
 
 	// syntax highligting issue with {} - bug 16176
 	[{
-	line: '"/api/v2/course/#{ $stateParams.courseId }/grading/student/#{$stateParams.studentId}",',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 31, type: 'delimiter.coffee' },
-		{ startIndex: 32, type: '' },
-		{ startIndex: 41, type: 'string.coffee' },
-		{ startIndex: 61, type: '' },
-		{ startIndex: 73, type: 'delimiter.coffee' },
-		{ startIndex: 74, type: '' },
-		{ startIndex: 83, type: 'string.coffee' },
-		{ startIndex: 85, type: 'delimiter.coffee' }
-	]}],
+		line: '"/api/v2/course/#{ $stateParams.courseId }/grading/student/#{$stateParams.studentId}",',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 31, type: 'delimiter.coffee' },
+			{ startIndex: 32, type: '' },
+			{ startIndex: 41, type: 'string.coffee' },
+			{ startIndex: 61, type: '' },
+			{ startIndex: 73, type: 'delimiter.coffee' },
+			{ startIndex: 74, type: '' },
+			{ startIndex: 83, type: 'string.coffee' },
+			{ startIndex: 85, type: 'delimiter.coffee' }
+		]
+	}],
 
 	// Generated from sample
 	[{
-	line: '# Assignment:',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'number   = 42',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 9, type: 'delimiter.coffee' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'number.coffee' }
-	]}, {
-	line: 'opposite = true',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 9, type: 'delimiter.coffee' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'keyword.true.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '# Conditions:',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'number = -42 if opposite',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 7, type: 'delimiter.coffee' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'delimiter.coffee' },
-		{ startIndex: 10, type: 'number.coffee' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'keyword.if.coffee' },
-		{ startIndex: 15, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '# Functions:',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'square = (x) -> x * x',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 7, type: 'delimiter.coffee' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'delimiter.coffee' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 18, type: 'delimiter.coffee' },
-		{ startIndex: 19, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '# Arrays:',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'list = [1, 2, 3, 4, 5]',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: 'delimiter.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'delimiter.square.coffee' },
-		{ startIndex: 8, type: 'number.coffee' },
-		{ startIndex: 9, type: 'delimiter.coffee' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'number.coffee' },
-		{ startIndex: 12, type: 'delimiter.coffee' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'number.coffee' },
-		{ startIndex: 15, type: 'delimiter.coffee' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'number.coffee' },
-		{ startIndex: 18, type: 'delimiter.coffee' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'number.coffee' },
-		{ startIndex: 21, type: 'delimiter.square.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '# Objects:',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'math =',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: 'delimiter.coffee' }
-	]}, {
-	line: '  root:   Math.sqrt',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 14, type: 'delimiter.coffee' },
-		{ startIndex: 15, type: '' }
-	]}, {
-	line: '  square: square',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'delimiter.coffee' },
-		{ startIndex: 9, type: '' }
-	]}, {
-	line: '  cube:   (x) -> x * square x',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 10, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'delimiter.coffee' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 19, type: 'delimiter.coffee' },
-		{ startIndex: 20, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '# Splats:',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'race = (winner, runners...) ->',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: 'delimiter.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 14, type: 'delimiter.coffee' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 23, type: 'delimiter.coffee' },
-		{ startIndex: 26, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 27, type: '' },
-		{ startIndex: 28, type: 'delimiter.coffee' }
-	]}, {
-	line: '  print winner, runners',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 14, type: 'delimiter.coffee' },
-		{ startIndex: 15, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '# Existence:',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'alert "I knew it!" if elvis?',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'string.coffee' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'keyword.if.coffee' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 27, type: 'delimiter.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '# Array comprehensions:',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'cubes = (math.cube num for num in list)',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 13, type: 'delimiter.coffee' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 23, type: 'keyword.for.coffee' },
-		{ startIndex: 26, type: '' },
-		{ startIndex: 31, type: 'keyword.in.coffee' },
-		{ startIndex: 33, type: '' },
-		{ startIndex: 38, type: 'delimiter.parenthesis.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'fill = (container, liquid = "coffee") ->',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: 'delimiter.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 17, type: 'delimiter.coffee' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 26, type: 'delimiter.coffee' },
-		{ startIndex: 27, type: '' },
-		{ startIndex: 28, type: 'string.coffee' },
-		{ startIndex: 36, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 37, type: '' },
-		{ startIndex: 38, type: 'delimiter.coffee' }
-	]}, {
-	line: '  "Filling the #{container} with #{liquid}..."',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'string.coffee' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 26, type: 'string.coffee' },
-		{ startIndex: 35, type: '' },
-		{ startIndex: 41, type: 'string.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'ong = ["do", "re", "mi", "fa", "so"]',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'delimiter.coffee' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.square.coffee' },
-		{ startIndex: 7, type: 'string.coffee' },
-		{ startIndex: 11, type: 'delimiter.coffee' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'string.coffee' },
-		{ startIndex: 17, type: 'delimiter.coffee' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'string.coffee' },
-		{ startIndex: 23, type: 'delimiter.coffee' },
-		{ startIndex: 24, type: '' },
-		{ startIndex: 25, type: 'string.coffee' },
-		{ startIndex: 29, type: 'delimiter.coffee' },
-		{ startIndex: 30, type: '' },
-		{ startIndex: 31, type: 'string.coffee' },
-		{ startIndex: 35, type: 'delimiter.square.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'singers = {Jagger: "Rock", Elvis: "Roll"}',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'delimiter.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'delimiter.curly.coffee' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 17, type: 'delimiter.coffee' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'string.coffee' },
-		{ startIndex: 25, type: 'delimiter.coffee' },
-		{ startIndex: 26, type: '' },
-		{ startIndex: 32, type: 'delimiter.coffee' },
-		{ startIndex: 33, type: '' },
-		{ startIndex: 34, type: 'string.coffee' },
-		{ startIndex: 40, type: 'delimiter.curly.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'bitlist = [',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'delimiter.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'delimiter.square.coffee' }
-	]}, {
-	line: '  1, 0, 1',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'number.coffee' },
-		{ startIndex: 3, type: 'delimiter.coffee' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'number.coffee' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.coffee' }
-	]}, {
-	line: '  0, 0, 1',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'number.coffee' },
-		{ startIndex: 3, type: 'delimiter.coffee' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'number.coffee' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.coffee' }
-	]}, {
-	line: '  1, 1, 0',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'number.coffee' },
-		{ startIndex: 3, type: 'delimiter.coffee' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'number.coffee' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.coffee' }
-	]}, {
-	line: ']',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.square.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'kids =',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: 'delimiter.coffee' }
-	]}, {
-	line: '  brother:',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 9, type: 'delimiter.coffee' }
-	]}, {
-	line: '    name: "Max"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'delimiter.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'string.coffee' }
-	]}, {
-	line: '    age:  11',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 7, type: 'delimiter.coffee' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 10, type: 'number.coffee' }
-	]}, {
-	line: '  sister:',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'delimiter.coffee' }
-	]}, {
-	line: '    name: "Ida"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'delimiter.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'string.coffee' }
-	]}, {
-	line: '    age:  9',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 7, type: 'delimiter.coffee' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 10, type: 'number.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '$(\'.account\').attr class: \'active\'',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 2, type: 'string.coffee' },
-		{ startIndex: 12, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 13, type: 'delimiter.coffee' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 19, type: 'keyword.class.coffee' },
-		{ startIndex: 24, type: 'delimiter.coffee' },
-		{ startIndex: 25, type: '' },
-		{ startIndex: 26, type: 'string.coffee' }
-	]}, {
-	line: 'log object.class',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 10, type: 'delimiter.coffee' },
-		{ startIndex: 11, type: 'keyword.class.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'outer = 1',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.coffee' }
-	]}, {
-	line: 'changeNumbers = ->',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 14, type: 'delimiter.coffee' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'delimiter.coffee' }
-	]}, {
-	line: 'inner = -1',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'delimiter.coffee' },
-		{ startIndex: 9, type: 'number.coffee' }
-	]}, {
-	line: 'outer = 10',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.coffee' }
-	]}, {
-	line: 'inner = changeNumbers()',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 21, type: 'delimiter.parenthesis.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'mood = greatlyImproved if singing',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: 'delimiter.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 23, type: 'keyword.if.coffee' },
-		{ startIndex: 25, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'if happy and knowsIt',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.if.coffee' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 9, type: 'keyword.and.coffee' },
-		{ startIndex: 12, type: '' }
-	]}, {
-	line: '  clapsHands()',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 12, type: 'delimiter.parenthesis.coffee' }
-	]}, {
-	line: '  chaChaCha()',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 11, type: 'delimiter.parenthesis.coffee' }
-	]}, {
-	line: 'else',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.else.coffee' }
-	]}, {
-	line: '  showIt()',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'delimiter.parenthesis.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'date = if friday then sue else jill',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: 'delimiter.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'keyword.if.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 17, type: 'keyword.then.coffee' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 26, type: 'keyword.else.coffee' },
-		{ startIndex: 30, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'options or= defaults',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'keyword.or.coffee' },
-		{ startIndex: 10, type: 'delimiter.coffee' },
-		{ startIndex: 11, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '# Eat lunch.',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'eat food for food in [\'toast\', \'cheese\', \'wine\']',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 9, type: 'keyword.for.coffee' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 18, type: 'keyword.in.coffee' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'delimiter.square.coffee' },
-		{ startIndex: 22, type: 'string.coffee' },
-		{ startIndex: 29, type: 'delimiter.coffee' },
-		{ startIndex: 30, type: '' },
-		{ startIndex: 31, type: 'string.coffee' },
-		{ startIndex: 39, type: 'delimiter.coffee' },
-		{ startIndex: 40, type: '' },
-		{ startIndex: 41, type: 'string.coffee' },
-		{ startIndex: 47, type: 'delimiter.square.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '# Fine five course dining.',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'courses = [\'greens\', \'caviar\', \'truffles\', \'roast\', \'cake\']',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'delimiter.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'delimiter.square.coffee' },
-		{ startIndex: 11, type: 'string.coffee' },
-		{ startIndex: 19, type: 'delimiter.coffee' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'string.coffee' },
-		{ startIndex: 29, type: 'delimiter.coffee' },
-		{ startIndex: 30, type: '' },
-		{ startIndex: 31, type: 'string.coffee' },
-		{ startIndex: 41, type: 'delimiter.coffee' },
-		{ startIndex: 42, type: '' },
-		{ startIndex: 43, type: 'string.coffee' },
-		{ startIndex: 50, type: 'delimiter.coffee' },
-		{ startIndex: 51, type: '' },
-		{ startIndex: 52, type: 'string.coffee' },
-		{ startIndex: 58, type: 'delimiter.square.coffee' }
-	]}, {
-	line: 'menu i + 1, dish for dish, i in courses',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 7, type: 'delimiter.coffee' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'number.coffee' },
-		{ startIndex: 10, type: 'delimiter.coffee' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 17, type: 'keyword.for.coffee' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 25, type: 'delimiter.coffee' },
-		{ startIndex: 26, type: '' },
-		{ startIndex: 29, type: 'keyword.in.coffee' },
-		{ startIndex: 31, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '# Health conscious meal.',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'foods = [\'broccoli\', \'spinach\', \'chocolate\']',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'delimiter.square.coffee' },
-		{ startIndex: 9, type: 'string.coffee' },
-		{ startIndex: 19, type: 'delimiter.coffee' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'string.coffee' },
-		{ startIndex: 30, type: 'delimiter.coffee' },
-		{ startIndex: 31, type: '' },
-		{ startIndex: 32, type: 'string.coffee' },
-		{ startIndex: 43, type: 'delimiter.square.coffee' }
-	]}, {
-	line: 'eat food for food in foods when food isnt \'chocolate\'',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 9, type: 'keyword.for.coffee' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 18, type: 'keyword.in.coffee' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 27, type: 'keyword.when.coffee' },
-		{ startIndex: 31, type: '' },
-		{ startIndex: 37, type: 'keyword.isnt.coffee' },
-		{ startIndex: 41, type: '' },
-		{ startIndex: 42, type: 'string.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'countdown = (num for num in [10..1])',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 10, type: 'delimiter.coffee' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 17, type: 'keyword.for.coffee' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 25, type: 'keyword.in.coffee' },
-		{ startIndex: 27, type: '' },
-		{ startIndex: 28, type: 'delimiter.square.coffee' },
-		{ startIndex: 29, type: 'number.coffee' },
-		{ startIndex: 31, type: 'delimiter.coffee' },
-		{ startIndex: 33, type: 'number.coffee' },
-		{ startIndex: 34, type: 'delimiter.square.coffee' },
-		{ startIndex: 35, type: 'delimiter.parenthesis.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'yearsOld = max: 10, ida: 9, tim: 11',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 9, type: 'delimiter.coffee' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 14, type: 'delimiter.coffee' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'number.coffee' },
-		{ startIndex: 18, type: 'delimiter.coffee' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 23, type: 'delimiter.coffee' },
-		{ startIndex: 24, type: '' },
-		{ startIndex: 25, type: 'number.coffee' },
-		{ startIndex: 26, type: 'delimiter.coffee' },
-		{ startIndex: 27, type: '' },
-		{ startIndex: 31, type: 'delimiter.coffee' },
-		{ startIndex: 32, type: '' },
-		{ startIndex: 33, type: 'number.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'ages = for child, age of yearsOld',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: 'delimiter.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'keyword.for.coffee' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 16, type: 'delimiter.coffee' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 22, type: 'keyword.of.coffee' },
-		{ startIndex: 24, type: '' }
-	]}, {
-	line: '  "#{child} is #{age}"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'string.coffee' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 10, type: 'string.coffee' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 20, type: 'string.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '# Econ 101',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'if this.studyingEconomics',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.if.coffee' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'variable.predefined.coffee' },
-		{ startIndex: 7, type: 'delimiter.coffee' },
-		{ startIndex: 8, type: '' }
-	]}, {
-	line: '  buy()  while supply > demand',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 9, type: 'keyword.while.coffee' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 22, type: 'delimiter.coffee' },
-		{ startIndex: 23, type: '' }
-	]}, {
-	line: '  sell() until supply > demand',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'keyword.until.coffee' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 22, type: 'delimiter.coffee' },
-		{ startIndex: 23, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '# Nursery Rhyme',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'num = 6',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'delimiter.coffee' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'number.coffee' }
-	]}, {
-	line: 'lyrics = while num -= 1',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 7, type: 'delimiter.coffee' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'keyword.while.coffee' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 19, type: 'delimiter.coffee' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'number.coffee' }
-	]}, {
-	line: '  "#{num} little monkeys, jumping on the bed.',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'string.coffee' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 8, type: 'string.coffee' }
-	]}, {
-	line: '    One fell out and bumped his head."',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' }
-	]}, {
-	line: '	',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '# Everything is an Expression (at least, as much as possible)',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'grade = (student) ->',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 16, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: 'delimiter.coffee' }
-	]}, {
-	line: '  if student.excellentWork',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.if.coffee' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 12, type: 'delimiter.coffee' },
-		{ startIndex: 13, type: '' }
-	]}, {
-	line: '    "A+"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'string.coffee' }
-	]}, {
-	line: '  else if student.okayStuff',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.else.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'keyword.if.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 17, type: 'delimiter.coffee' },
-		{ startIndex: 18, type: '' }
-	]}, {
-	line: '    if student.triedHard then "B" else "B-"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.if.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 14, type: 'delimiter.coffee' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 25, type: 'keyword.then.coffee' },
-		{ startIndex: 29, type: '' },
-		{ startIndex: 30, type: 'string.coffee' },
-		{ startIndex: 33, type: '' },
-		{ startIndex: 34, type: 'keyword.else.coffee' },
-		{ startIndex: 38, type: '' },
-		{ startIndex: 39, type: 'string.coffee' }
-	]}, {
-	line: '  else',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.else.coffee' }
-	]}, {
-	line: '    "C"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'string.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'eldest = if 24 > 21 then "Liz" else "Ike"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 7, type: 'delimiter.coffee' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'keyword.if.coffee' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'number.coffee' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'delimiter.coffee' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'number.coffee' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'keyword.then.coffee' },
-		{ startIndex: 24, type: '' },
-		{ startIndex: 25, type: 'string.coffee' },
-		{ startIndex: 30, type: '' },
-		{ startIndex: 31, type: 'keyword.else.coffee' },
-		{ startIndex: 35, type: '' },
-		{ startIndex: 36, type: 'string.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '#Classes, Inheritance and Super',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'class Animal',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.class.coffee' },
-		{ startIndex: 5, type: '' }
-	]}, {
-	line: '  constructor: (@name) ->',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 13, type: 'delimiter.coffee' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 16, type: 'variable.predefined.coffee' },
-		{ startIndex: 21, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'delimiter.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '  move: (meters) ->',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 15, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'delimiter.coffee' }
-	]}, {
-	line: '    alert @name + " moved #{meters}m."',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 10, type: 'variable.predefined.coffee' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'delimiter.coffee' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: 'string.coffee' },
-		{ startIndex: 28, type: '' },
-		{ startIndex: 34, type: 'string.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'class Snake extends Animal',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.class.coffee' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 12, type: 'keyword.extends.coffee' },
-		{ startIndex: 19, type: '' }
-	]}, {
-	line: '  move: ->',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'delimiter.coffee' }
-	]}, {
-	line: '    alert "Slithering..."',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 10, type: 'string.coffee' }
-	]}, {
-	line: '    super 5',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.super.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'number.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'class Horse extends Animal',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.class.coffee' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 12, type: 'keyword.extends.coffee' },
-		{ startIndex: 19, type: '' }
-	]}, {
-	line: '  move: ->',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'delimiter.coffee' }
-	]}, {
-	line: '    alert "Galloping..."',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 10, type: 'string.coffee' }
-	]}, {
-	line: '    super 45',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.super.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'number.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'sam = new Snake "Sammy the Python"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'delimiter.coffee' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'keyword.new.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 16, type: 'string.coffee' }
-	]}, {
-	line: 'tom = new Horse "Tommy the Palomino"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'delimiter.coffee' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'keyword.new.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 16, type: 'string.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'sam.move()',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'delimiter.coffee' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 8, type: 'delimiter.parenthesis.coffee' }
-	]}, {
-	line: 'tom.move()',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'delimiter.coffee' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 8, type: 'delimiter.parenthesis.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '#Function binding',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'Account = (customer, cart) ->',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'delimiter.coffee' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 19, type: 'delimiter.coffee' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 25, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 26, type: '' },
-		{ startIndex: 27, type: 'delimiter.coffee' }
-	]}, {
-	line: '  @customer = customer',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'variable.predefined.coffee' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'delimiter.coffee' },
-		{ startIndex: 13, type: '' }
-	]}, {
-	line: '  @cart = cart',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'variable.predefined.coffee' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'delimiter.coffee' },
-		{ startIndex: 9, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '  $(\'.shopping_cart\').bind \'click\', (event) =>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 4, type: 'string.coffee' },
-		{ startIndex: 20, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 21, type: 'delimiter.coffee' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 27, type: 'string.coffee' },
-		{ startIndex: 34, type: 'delimiter.coffee' },
-		{ startIndex: 35, type: '' },
-		{ startIndex: 36, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 37, type: '' },
-		{ startIndex: 42, type: 'delimiter.parenthesis.coffee' },
-		{ startIndex: 43, type: '' },
-		{ startIndex: 44, type: 'delimiter.coffee' }
-	]}, {
-	line: '    @customer.purchase @cart',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'variable.predefined.coffee' },
-		{ startIndex: 13, type: 'delimiter.coffee' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 23, type: 'variable.predefined.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '#Switch/When/Else	',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'switch day',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.switch.coffee' },
-		{ startIndex: 6, type: '' }
-	]}, {
-	line: '  when "Mon" then go work',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.when.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'string.coffee' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'keyword.then.coffee' },
-		{ startIndex: 17, type: '' }
-	]}, {
-	line: '  when "Tue" then go relax',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.when.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'string.coffee' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'keyword.then.coffee' },
-		{ startIndex: 17, type: '' }
-	]}, {
-	line: '  when "Thu" then go iceFishing',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.when.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'string.coffee' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'keyword.then.coffee' },
-		{ startIndex: 17, type: '' }
-	]}, {
-	line: '  when "Fri", "Sat"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.when.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'string.coffee' },
-		{ startIndex: 12, type: 'delimiter.coffee' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'string.coffee' }
-	]}, {
-	line: '    if day is bingoDay',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.if.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 11, type: 'keyword.is.coffee' },
-		{ startIndex: 13, type: '' }
-	]}, {
-	line: '      go bingo',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '      go dancing',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '  when "Sun" then go church',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.when.coffee' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'string.coffee' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'keyword.then.coffee' },
-		{ startIndex: 17, type: '' }
-	]}, {
-	line: '  else go work',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.else.coffee' },
-		{ startIndex: 6, type: '' }
-	]}, {
-	line: ' ',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '#Try/Catch/Finally',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'try',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.try.coffee' }
-	]}, {
-	line: '  allHellBreaksLoose()',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 20, type: 'delimiter.parenthesis.coffee' }
-	]}, {
-	line: '  catsAndDogsLivingTogether()',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 27, type: 'delimiter.parenthesis.coffee' }
-	]}, {
-	line: 'catch error',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.catch.coffee' },
-		{ startIndex: 5, type: '' }
-	]}, {
-	line: '  print error',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: 'finally',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.finally.coffee' }
-	]}, {
-	line: '  cleanUp()',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 9, type: 'delimiter.parenthesis.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '#String Interpolation and Block Comments',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'author = "Wittgenstein"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 7, type: 'delimiter.coffee' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'string.coffee' }
-	]}, {
-	line: 'quote  = "A picture is a fact. -- #{ author }"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 7, type: 'delimiter.coffee' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'string.coffee' },
-		{ startIndex: 36, type: '' },
-		{ startIndex: 44, type: 'string.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'sentence = "#{ 22 / 7 } is a decent approximation of p"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 9, type: 'delimiter.coffee' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'string.coffee' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'number.coffee' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: 'delimiter.coffee' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'number.coffee' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'string.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'mobyDick = "Call me Ishmael. Some years ago --',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 9, type: 'delimiter.coffee' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'string.coffee' }
-	]}, {
-	line: ' never mind how long precisely -- having little',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' }
-	]}, {
-	line: ' or no money in my purse, and nothing particular',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' }
-	]}, {
-	line: ' to interest me on shore, I thought I would sail',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' }
-	]}, {
-	line: ' about a little and see the watery part of the',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' }
-	]}, {
-	line: ' world..."',
-	tokens: [
-		{ startIndex: 0, type: 'string.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '#Extended Regular Expressions',
-	tokens: [
-		{ startIndex: 0, type: 'comment.coffee' }
-	]}, {
-	line: 'OPERATOR = /// ^ (',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 9, type: 'delimiter.coffee' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'regexp.coffee' }
-	]}, {
-	line: '  ?: [-=]>             # function',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' },
-		{ startIndex: 23, type: 'comment.coffee' }
-	]}, {
-	line: '   | [-+*/%<>&|^!?=]=  # compound assign / compare',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' },
-		{ startIndex: 23, type: 'comment.coffee' }
-	]}, {
-	line: '   | >>>=?             # zero-fill right shift',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' },
-		{ startIndex: 23, type: 'comment.coffee' }
-	]}, {
-	line: '   | ([-+:])\\1         # doubles',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' },
-		{ startIndex: 23, type: 'comment.coffee' }
-	]}, {
-	line: '   | ([&|<>])\\2=?      # logic / shift',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' },
-		{ startIndex: 23, type: 'comment.coffee' }
-	]}, {
-	line: '   | \\?\\.              # soak access',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' },
-		{ startIndex: 23, type: 'comment.coffee' }
-	]}, {
-	line: '   | \\.{2,3}           # range or splat',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' },
-		{ startIndex: 23, type: 'comment.coffee' }
-	]}, {
-	line: ') ///',
-	tokens: [
-		{ startIndex: 0, type: 'regexp.coffee' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}]
+		line: '# Assignment:',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'number   = 42',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 9, type: 'delimiter.coffee' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'number.coffee' }
+		]
+	}, {
+		line: 'opposite = true',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 9, type: 'delimiter.coffee' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'keyword.true.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '# Conditions:',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'number = -42 if opposite',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 7, type: 'delimiter.coffee' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.coffee' },
+			{ startIndex: 10, type: 'number.coffee' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'keyword.if.coffee' },
+			{ startIndex: 15, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '# Functions:',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'square = (x) -> x * x',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 7, type: 'delimiter.coffee' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'delimiter.coffee' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 18, type: 'delimiter.coffee' },
+			{ startIndex: 19, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '# Arrays:',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'list = [1, 2, 3, 4, 5]',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'delimiter.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'delimiter.square.coffee' },
+			{ startIndex: 8, type: 'number.coffee' },
+			{ startIndex: 9, type: 'delimiter.coffee' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'number.coffee' },
+			{ startIndex: 12, type: 'delimiter.coffee' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'number.coffee' },
+			{ startIndex: 15, type: 'delimiter.coffee' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'number.coffee' },
+			{ startIndex: 18, type: 'delimiter.coffee' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'number.coffee' },
+			{ startIndex: 21, type: 'delimiter.square.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '# Objects:',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'math =',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '  root:   Math.sqrt',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 14, type: 'delimiter.coffee' },
+			{ startIndex: 15, type: '' }
+		]
+	}, {
+		line: '  square: square',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'delimiter.coffee' },
+			{ startIndex: 9, type: '' }
+		]
+	}, {
+		line: '  cube:   (x) -> x * square x',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 10, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'delimiter.coffee' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 19, type: 'delimiter.coffee' },
+			{ startIndex: 20, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '# Splats:',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'race = (winner, runners...) ->',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'delimiter.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 14, type: 'delimiter.coffee' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 23, type: 'delimiter.coffee' },
+			{ startIndex: 26, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '  print winner, runners',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 14, type: 'delimiter.coffee' },
+			{ startIndex: 15, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '# Existence:',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'alert "I knew it!" if elvis?',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'string.coffee' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'keyword.if.coffee' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 27, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '# Array comprehensions:',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'cubes = (math.cube num for num in list)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 13, type: 'delimiter.coffee' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 23, type: 'keyword.for.coffee' },
+			{ startIndex: 26, type: '' },
+			{ startIndex: 31, type: 'keyword.in.coffee' },
+			{ startIndex: 33, type: '' },
+			{ startIndex: 38, type: 'delimiter.parenthesis.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'fill = (container, liquid = "coffee") ->',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'delimiter.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 17, type: 'delimiter.coffee' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 26, type: 'delimiter.coffee' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'string.coffee' },
+			{ startIndex: 36, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 37, type: '' },
+			{ startIndex: 38, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '  "Filling the #{container} with #{liquid}..."',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'string.coffee' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 26, type: 'string.coffee' },
+			{ startIndex: 35, type: '' },
+			{ startIndex: 41, type: 'string.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'ong = ["do", "re", "mi", "fa", "so"]',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'delimiter.coffee' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.square.coffee' },
+			{ startIndex: 7, type: 'string.coffee' },
+			{ startIndex: 11, type: 'delimiter.coffee' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'string.coffee' },
+			{ startIndex: 17, type: 'delimiter.coffee' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'string.coffee' },
+			{ startIndex: 23, type: 'delimiter.coffee' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'string.coffee' },
+			{ startIndex: 29, type: 'delimiter.coffee' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'string.coffee' },
+			{ startIndex: 35, type: 'delimiter.square.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'singers = {Jagger: "Rock", Elvis: "Roll"}',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'delimiter.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'delimiter.curly.coffee' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 17, type: 'delimiter.coffee' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'string.coffee' },
+			{ startIndex: 25, type: 'delimiter.coffee' },
+			{ startIndex: 26, type: '' },
+			{ startIndex: 32, type: 'delimiter.coffee' },
+			{ startIndex: 33, type: '' },
+			{ startIndex: 34, type: 'string.coffee' },
+			{ startIndex: 40, type: 'delimiter.curly.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'bitlist = [',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'delimiter.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'delimiter.square.coffee' }
+		]
+	}, {
+		line: '  1, 0, 1',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'number.coffee' },
+			{ startIndex: 3, type: 'delimiter.coffee' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'number.coffee' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.coffee' }
+		]
+	}, {
+		line: '  0, 0, 1',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'number.coffee' },
+			{ startIndex: 3, type: 'delimiter.coffee' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'number.coffee' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.coffee' }
+		]
+	}, {
+		line: '  1, 1, 0',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'number.coffee' },
+			{ startIndex: 3, type: 'delimiter.coffee' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'number.coffee' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.coffee' }
+		]
+	}, {
+		line: ']',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.square.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'kids =',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '  brother:',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 9, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '    name: "Max"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'delimiter.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'string.coffee' }
+		]
+	}, {
+		line: '    age:  11',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 7, type: 'delimiter.coffee' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 10, type: 'number.coffee' }
+		]
+	}, {
+		line: '  sister:',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '    name: "Ida"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'delimiter.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'string.coffee' }
+		]
+	}, {
+		line: '    age:  9',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 7, type: 'delimiter.coffee' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 10, type: 'number.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '$(\'.account\').attr class: \'active\'',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 2, type: 'string.coffee' },
+			{ startIndex: 12, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 13, type: 'delimiter.coffee' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 19, type: 'keyword.class.coffee' },
+			{ startIndex: 24, type: 'delimiter.coffee' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'string.coffee' }
+		]
+	}, {
+		line: 'log object.class',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 10, type: 'delimiter.coffee' },
+			{ startIndex: 11, type: 'keyword.class.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'outer = 1',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.coffee' }
+		]
+	}, {
+		line: 'changeNumbers = ->',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 14, type: 'delimiter.coffee' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: 'inner = -1',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.coffee' },
+			{ startIndex: 9, type: 'number.coffee' }
+		]
+	}, {
+		line: 'outer = 10',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.coffee' }
+		]
+	}, {
+		line: 'inner = changeNumbers()',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 21, type: 'delimiter.parenthesis.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'mood = greatlyImproved if singing',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'delimiter.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 23, type: 'keyword.if.coffee' },
+			{ startIndex: 25, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'if happy and knowsIt',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.if.coffee' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 9, type: 'keyword.and.coffee' },
+			{ startIndex: 12, type: '' }
+		]
+	}, {
+		line: '  clapsHands()',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 12, type: 'delimiter.parenthesis.coffee' }
+		]
+	}, {
+		line: '  chaChaCha()',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 11, type: 'delimiter.parenthesis.coffee' }
+		]
+	}, {
+		line: 'else',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.else.coffee' }
+		]
+	}, {
+		line: '  showIt()',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'delimiter.parenthesis.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'date = if friday then sue else jill',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'delimiter.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'keyword.if.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 17, type: 'keyword.then.coffee' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 26, type: 'keyword.else.coffee' },
+			{ startIndex: 30, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'options or= defaults',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'keyword.or.coffee' },
+			{ startIndex: 10, type: 'delimiter.coffee' },
+			{ startIndex: 11, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '# Eat lunch.',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'eat food for food in [\'toast\', \'cheese\', \'wine\']',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 9, type: 'keyword.for.coffee' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 18, type: 'keyword.in.coffee' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'delimiter.square.coffee' },
+			{ startIndex: 22, type: 'string.coffee' },
+			{ startIndex: 29, type: 'delimiter.coffee' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'string.coffee' },
+			{ startIndex: 39, type: 'delimiter.coffee' },
+			{ startIndex: 40, type: '' },
+			{ startIndex: 41, type: 'string.coffee' },
+			{ startIndex: 47, type: 'delimiter.square.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '# Fine five course dining.',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'courses = [\'greens\', \'caviar\', \'truffles\', \'roast\', \'cake\']',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'delimiter.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'delimiter.square.coffee' },
+			{ startIndex: 11, type: 'string.coffee' },
+			{ startIndex: 19, type: 'delimiter.coffee' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'string.coffee' },
+			{ startIndex: 29, type: 'delimiter.coffee' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'string.coffee' },
+			{ startIndex: 41, type: 'delimiter.coffee' },
+			{ startIndex: 42, type: '' },
+			{ startIndex: 43, type: 'string.coffee' },
+			{ startIndex: 50, type: 'delimiter.coffee' },
+			{ startIndex: 51, type: '' },
+			{ startIndex: 52, type: 'string.coffee' },
+			{ startIndex: 58, type: 'delimiter.square.coffee' }
+		]
+	}, {
+		line: 'menu i + 1, dish for dish, i in courses',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 7, type: 'delimiter.coffee' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'number.coffee' },
+			{ startIndex: 10, type: 'delimiter.coffee' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 17, type: 'keyword.for.coffee' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 25, type: 'delimiter.coffee' },
+			{ startIndex: 26, type: '' },
+			{ startIndex: 29, type: 'keyword.in.coffee' },
+			{ startIndex: 31, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '# Health conscious meal.',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'foods = [\'broccoli\', \'spinach\', \'chocolate\']',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.square.coffee' },
+			{ startIndex: 9, type: 'string.coffee' },
+			{ startIndex: 19, type: 'delimiter.coffee' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'string.coffee' },
+			{ startIndex: 30, type: 'delimiter.coffee' },
+			{ startIndex: 31, type: '' },
+			{ startIndex: 32, type: 'string.coffee' },
+			{ startIndex: 43, type: 'delimiter.square.coffee' }
+		]
+	}, {
+		line: 'eat food for food in foods when food isnt \'chocolate\'',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 9, type: 'keyword.for.coffee' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 18, type: 'keyword.in.coffee' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 27, type: 'keyword.when.coffee' },
+			{ startIndex: 31, type: '' },
+			{ startIndex: 37, type: 'keyword.isnt.coffee' },
+			{ startIndex: 41, type: '' },
+			{ startIndex: 42, type: 'string.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'countdown = (num for num in [10..1])',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 10, type: 'delimiter.coffee' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 17, type: 'keyword.for.coffee' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 25, type: 'keyword.in.coffee' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'delimiter.square.coffee' },
+			{ startIndex: 29, type: 'number.coffee' },
+			{ startIndex: 31, type: 'delimiter.coffee' },
+			{ startIndex: 33, type: 'number.coffee' },
+			{ startIndex: 34, type: 'delimiter.square.coffee' },
+			{ startIndex: 35, type: 'delimiter.parenthesis.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'yearsOld = max: 10, ida: 9, tim: 11',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 9, type: 'delimiter.coffee' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 14, type: 'delimiter.coffee' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'number.coffee' },
+			{ startIndex: 18, type: 'delimiter.coffee' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 23, type: 'delimiter.coffee' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'number.coffee' },
+			{ startIndex: 26, type: 'delimiter.coffee' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 31, type: 'delimiter.coffee' },
+			{ startIndex: 32, type: '' },
+			{ startIndex: 33, type: 'number.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'ages = for child, age of yearsOld',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'delimiter.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'keyword.for.coffee' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 16, type: 'delimiter.coffee' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 22, type: 'keyword.of.coffee' },
+			{ startIndex: 24, type: '' }
+		]
+	}, {
+		line: '  "#{child} is #{age}"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'string.coffee' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 10, type: 'string.coffee' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 20, type: 'string.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '# Econ 101',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'if this.studyingEconomics',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.if.coffee' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'variable.predefined.coffee' },
+			{ startIndex: 7, type: 'delimiter.coffee' },
+			{ startIndex: 8, type: '' }
+		]
+	}, {
+		line: '  buy()  while supply > demand',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 9, type: 'keyword.while.coffee' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 22, type: 'delimiter.coffee' },
+			{ startIndex: 23, type: '' }
+		]
+	}, {
+		line: '  sell() until supply > demand',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'keyword.until.coffee' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 22, type: 'delimiter.coffee' },
+			{ startIndex: 23, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '# Nursery Rhyme',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'num = 6',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'delimiter.coffee' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'number.coffee' }
+		]
+	}, {
+		line: 'lyrics = while num -= 1',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 7, type: 'delimiter.coffee' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'keyword.while.coffee' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 19, type: 'delimiter.coffee' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'number.coffee' }
+		]
+	}, {
+		line: '  "#{num} little monkeys, jumping on the bed.',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'string.coffee' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 8, type: 'string.coffee' }
+		]
+	}, {
+		line: '    One fell out and bumped his head."',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' }
+		]
+	}, {
+		line: '	',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '# Everything is an Expression (at least, as much as possible)',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'grade = (student) ->',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 16, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '  if student.excellentWork',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.if.coffee' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 12, type: 'delimiter.coffee' },
+			{ startIndex: 13, type: '' }
+		]
+	}, {
+		line: '    "A+"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'string.coffee' }
+		]
+	}, {
+		line: '  else if student.okayStuff',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.else.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'keyword.if.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 17, type: 'delimiter.coffee' },
+			{ startIndex: 18, type: '' }
+		]
+	}, {
+		line: '    if student.triedHard then "B" else "B-"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.if.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 14, type: 'delimiter.coffee' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 25, type: 'keyword.then.coffee' },
+			{ startIndex: 29, type: '' },
+			{ startIndex: 30, type: 'string.coffee' },
+			{ startIndex: 33, type: '' },
+			{ startIndex: 34, type: 'keyword.else.coffee' },
+			{ startIndex: 38, type: '' },
+			{ startIndex: 39, type: 'string.coffee' }
+		]
+	}, {
+		line: '  else',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.else.coffee' }
+		]
+	}, {
+		line: '    "C"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'string.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'eldest = if 24 > 21 then "Liz" else "Ike"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 7, type: 'delimiter.coffee' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'keyword.if.coffee' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'number.coffee' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'delimiter.coffee' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'number.coffee' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'keyword.then.coffee' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'string.coffee' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'keyword.else.coffee' },
+			{ startIndex: 35, type: '' },
+			{ startIndex: 36, type: 'string.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '#Classes, Inheritance and Super',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'class Animal',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.class.coffee' },
+			{ startIndex: 5, type: '' }
+		]
+	}, {
+		line: '  constructor: (@name) ->',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 13, type: 'delimiter.coffee' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 16, type: 'variable.predefined.coffee' },
+			{ startIndex: 21, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '  move: (meters) ->',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 15, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '    alert @name + " moved #{meters}m."',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 10, type: 'variable.predefined.coffee' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'delimiter.coffee' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'string.coffee' },
+			{ startIndex: 28, type: '' },
+			{ startIndex: 34, type: 'string.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'class Snake extends Animal',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.class.coffee' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 12, type: 'keyword.extends.coffee' },
+			{ startIndex: 19, type: '' }
+		]
+	}, {
+		line: '  move: ->',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '    alert "Slithering..."',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 10, type: 'string.coffee' }
+		]
+	}, {
+		line: '    super 5',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.super.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'number.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'class Horse extends Animal',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.class.coffee' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 12, type: 'keyword.extends.coffee' },
+			{ startIndex: 19, type: '' }
+		]
+	}, {
+		line: '  move: ->',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '    alert "Galloping..."',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 10, type: 'string.coffee' }
+		]
+	}, {
+		line: '    super 45',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.super.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'number.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'sam = new Snake "Sammy the Python"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'delimiter.coffee' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.new.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 16, type: 'string.coffee' }
+		]
+	}, {
+		line: 'tom = new Horse "Tommy the Palomino"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'delimiter.coffee' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.new.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 16, type: 'string.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'sam.move()',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'delimiter.coffee' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 8, type: 'delimiter.parenthesis.coffee' }
+		]
+	}, {
+		line: 'tom.move()',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'delimiter.coffee' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 8, type: 'delimiter.parenthesis.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '#Function binding',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'Account = (customer, cart) ->',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'delimiter.coffee' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 19, type: 'delimiter.coffee' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 25, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 26, type: '' },
+			{ startIndex: 27, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '  @customer = customer',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'variable.predefined.coffee' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'delimiter.coffee' },
+			{ startIndex: 13, type: '' }
+		]
+	}, {
+		line: '  @cart = cart',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'variable.predefined.coffee' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.coffee' },
+			{ startIndex: 9, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '  $(\'.shopping_cart\').bind \'click\', (event) =>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 4, type: 'string.coffee' },
+			{ startIndex: 20, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 21, type: 'delimiter.coffee' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 27, type: 'string.coffee' },
+			{ startIndex: 34, type: 'delimiter.coffee' },
+			{ startIndex: 35, type: '' },
+			{ startIndex: 36, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 37, type: '' },
+			{ startIndex: 42, type: 'delimiter.parenthesis.coffee' },
+			{ startIndex: 43, type: '' },
+			{ startIndex: 44, type: 'delimiter.coffee' }
+		]
+	}, {
+		line: '    @customer.purchase @cart',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'variable.predefined.coffee' },
+			{ startIndex: 13, type: 'delimiter.coffee' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 23, type: 'variable.predefined.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '#Switch/When/Else	',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'switch day',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.switch.coffee' },
+			{ startIndex: 6, type: '' }
+		]
+	}, {
+		line: '  when "Mon" then go work',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.when.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'string.coffee' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'keyword.then.coffee' },
+			{ startIndex: 17, type: '' }
+		]
+	}, {
+		line: '  when "Tue" then go relax',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.when.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'string.coffee' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'keyword.then.coffee' },
+			{ startIndex: 17, type: '' }
+		]
+	}, {
+		line: '  when "Thu" then go iceFishing',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.when.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'string.coffee' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'keyword.then.coffee' },
+			{ startIndex: 17, type: '' }
+		]
+	}, {
+		line: '  when "Fri", "Sat"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.when.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'string.coffee' },
+			{ startIndex: 12, type: 'delimiter.coffee' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'string.coffee' }
+		]
+	}, {
+		line: '    if day is bingoDay',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.if.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 11, type: 'keyword.is.coffee' },
+			{ startIndex: 13, type: '' }
+		]
+	}, {
+		line: '      go bingo',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '      go dancing',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '  when "Sun" then go church',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.when.coffee' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'string.coffee' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'keyword.then.coffee' },
+			{ startIndex: 17, type: '' }
+		]
+	}, {
+		line: '  else go work',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.else.coffee' },
+			{ startIndex: 6, type: '' }
+		]
+	}, {
+		line: ' ',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '#Try/Catch/Finally',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'try',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.try.coffee' }
+		]
+	}, {
+		line: '  allHellBreaksLoose()',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 20, type: 'delimiter.parenthesis.coffee' }
+		]
+	}, {
+		line: '  catsAndDogsLivingTogether()',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 27, type: 'delimiter.parenthesis.coffee' }
+		]
+	}, {
+		line: 'catch error',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.catch.coffee' },
+			{ startIndex: 5, type: '' }
+		]
+	}, {
+		line: '  print error',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: 'finally',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.finally.coffee' }
+		]
+	}, {
+		line: '  cleanUp()',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 9, type: 'delimiter.parenthesis.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '#String Interpolation and Block Comments',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'author = "Wittgenstein"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 7, type: 'delimiter.coffee' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'string.coffee' }
+		]
+	}, {
+		line: 'quote  = "A picture is a fact. -- #{ author }"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 7, type: 'delimiter.coffee' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'string.coffee' },
+			{ startIndex: 36, type: '' },
+			{ startIndex: 44, type: 'string.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'sentence = "#{ 22 / 7 } is a decent approximation of p"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 9, type: 'delimiter.coffee' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'string.coffee' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'number.coffee' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'delimiter.coffee' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'number.coffee' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'string.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'mobyDick = "Call me Ishmael. Some years ago --',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 9, type: 'delimiter.coffee' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'string.coffee' }
+		]
+	}, {
+		line: ' never mind how long precisely -- having little',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' }
+		]
+	}, {
+		line: ' or no money in my purse, and nothing particular',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' }
+		]
+	}, {
+		line: ' to interest me on shore, I thought I would sail',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' }
+		]
+	}, {
+		line: ' about a little and see the watery part of the',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' }
+		]
+	}, {
+		line: ' world..."',
+		tokens: [
+			{ startIndex: 0, type: 'string.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '#Extended Regular Expressions',
+		tokens: [
+			{ startIndex: 0, type: 'comment.coffee' }
+		]
+	}, {
+		line: 'OPERATOR = /// ^ (',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 9, type: 'delimiter.coffee' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'regexp.coffee' }
+		]
+	}, {
+		line: '  ?: [-=]>             # function',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' },
+			{ startIndex: 23, type: 'comment.coffee' }
+		]
+	}, {
+		line: '   | [-+*/%<>&|^!?=]=  # compound assign / compare',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' },
+			{ startIndex: 23, type: 'comment.coffee' }
+		]
+	}, {
+		line: '   | >>>=?             # zero-fill right shift',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' },
+			{ startIndex: 23, type: 'comment.coffee' }
+		]
+	}, {
+		line: '   | ([-+:])\\1         # doubles',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' },
+			{ startIndex: 23, type: 'comment.coffee' }
+		]
+	}, {
+		line: '   | ([&|<>])\\2=?      # logic / shift',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' },
+			{ startIndex: 23, type: 'comment.coffee' }
+		]
+	}, {
+		line: '   | \\?\\.              # soak access',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' },
+			{ startIndex: 23, type: 'comment.coffee' }
+		]
+	}, {
+		line: '   | \\.{2,3}           # range or splat',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' },
+			{ startIndex: 23, type: 'comment.coffee' }
+		]
+	}, {
+		line: ') ///',
+		tokens: [
+			{ startIndex: 0, type: 'regexp.coffee' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}]
 ]);

+ 671 - 586
test/cpp.test.ts

@@ -5,662 +5,747 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('cpp', [
 	// Keywords
 	[{
-	line: 'int _tmain(int argc, _TCHAR* argv[])',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.int.cpp' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.cpp' },
-		{ startIndex: 10, type: 'delimiter.parenthesis.cpp' },
-		{ startIndex: 11, type: 'keyword.int.cpp' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'identifier.cpp' },
-		{ startIndex: 19, type: 'delimiter.cpp' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'identifier.cpp' },
-		{ startIndex: 27, type: 'delimiter.cpp' },
-		{ startIndex: 28, type: '' },
-		{ startIndex: 29, type: 'identifier.cpp' },
-		{ startIndex: 33, type: 'delimiter.square.cpp' },
-		{ startIndex: 35, type: 'delimiter.parenthesis.cpp' }
-	]}],
+		line: 'int _tmain(int argc, _TCHAR* argv[])',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.int.cpp' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.cpp' },
+			{ startIndex: 10, type: 'delimiter.parenthesis.cpp' },
+			{ startIndex: 11, type: 'keyword.int.cpp' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'identifier.cpp' },
+			{ startIndex: 19, type: 'delimiter.cpp' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'identifier.cpp' },
+			{ startIndex: 27, type: 'delimiter.cpp' },
+			{ startIndex: 28, type: '' },
+			{ startIndex: 29, type: 'identifier.cpp' },
+			{ startIndex: 33, type: 'delimiter.square.cpp' },
+			{ startIndex: 35, type: 'delimiter.parenthesis.cpp' }
+		]
+	}],
 
 	// Comments - single line
 	[{
-	line: '//',
-	tokens: [
-		{ startIndex: 0, type: 'comment.cpp' }
-	]}],
-
-	[{
-	line: '    // a comment',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'comment.cpp' }
-	]}],
-
-	[{
-	line: '// a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.cpp' }
-	]}],
-
-	[{
-	line: '//sticky comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.cpp' }
-	]}],
-
-	[{
-	line: '/almost a comment',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.cpp' },
-		{ startIndex: 1, type: 'identifier.cpp' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.cpp' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'identifier.cpp' }
-	]}],
-
-	[{
-	line: '/* //*/ a',
-	tokens: [
-		{ startIndex: 0, type: 'comment.cpp' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.cpp' }
-	]}],
-
-	[{
-	line: '1 / 2; /* comment',
-	tokens: [
-		{ startIndex: 0, type: 'number.cpp' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cpp' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.cpp' },
-		{ startIndex: 5, type: 'delimiter.cpp' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'comment.cpp' }
-	]}],
-
-	[{
-	line: 'int x = 1; // my comment // is a nice one',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.int.cpp' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.cpp' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.cpp' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.cpp' },
-		{ startIndex: 9, type: 'delimiter.cpp' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'comment.cpp' }
-	]}],
+		line: '//',
+		tokens: [
+			{ startIndex: 0, type: 'comment.cpp' }
+		]
+	}],
+
+	[{
+		line: '    // a comment',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'comment.cpp' }
+		]
+	}],
+
+	[{
+		line: '// a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.cpp' }
+		]
+	}],
+
+	[{
+		line: '//sticky comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.cpp' }
+		]
+	}],
+
+	[{
+		line: '/almost a comment',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.cpp' },
+			{ startIndex: 1, type: 'identifier.cpp' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.cpp' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.cpp' }
+		]
+	}],
+
+	[{
+		line: '/* //*/ a',
+		tokens: [
+			{ startIndex: 0, type: 'comment.cpp' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.cpp' }
+		]
+	}],
+
+	[{
+		line: '1 / 2; /* comment',
+		tokens: [
+			{ startIndex: 0, type: 'number.cpp' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cpp' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.cpp' },
+			{ startIndex: 5, type: 'delimiter.cpp' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'comment.cpp' }
+		]
+	}],
+
+	[{
+		line: 'int x = 1; // my comment // is a nice one',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.int.cpp' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.cpp' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.cpp' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.cpp' },
+			{ startIndex: 9, type: 'delimiter.cpp' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'comment.cpp' }
+		]
+	}],
 
 	// Comments - range comment, single line
 	[{
-	line: '/* a simple comment */',
-	tokens: [
-		{ startIndex: 0, type: 'comment.cpp' }
-	]}],
-
-	[{
-	line: 'int x = /* a simple comment */ 1;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.int.cpp' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.cpp' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.cpp' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.cpp' },
-		{ startIndex: 30, type: '' },
-		{ startIndex: 31, type: 'number.cpp' },
-		{ startIndex: 32, type: 'delimiter.cpp' }
-	]}],
-
-	[{
-	line: 'int x = /* comment */ 1; */',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.int.cpp' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.cpp' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.cpp' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.cpp' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'number.cpp' },
-		{ startIndex: 23, type: 'delimiter.cpp' },
-		{ startIndex: 24, type: '' }
-	]}],
-
-	[{
-	line: 'x = /**/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.cpp' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cpp' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.cpp' },
-		{ startIndex: 8, type: 'delimiter.cpp' }
-	]}],
-
-	[{
-	line: 'x = /*/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.cpp' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cpp' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.cpp' }
-	]}],
+		line: '/* a simple comment */',
+		tokens: [
+			{ startIndex: 0, type: 'comment.cpp' }
+		]
+	}],
+
+	[{
+		line: 'int x = /* a simple comment */ 1;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.int.cpp' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.cpp' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.cpp' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.cpp' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'number.cpp' },
+			{ startIndex: 32, type: 'delimiter.cpp' }
+		]
+	}],
+
+	[{
+		line: 'int x = /* comment */ 1; */',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.int.cpp' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.cpp' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.cpp' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.cpp' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'number.cpp' },
+			{ startIndex: 23, type: 'delimiter.cpp' },
+			{ startIndex: 24, type: '' }
+		]
+	}],
+
+	[{
+		line: 'x = /**/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.cpp' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cpp' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.cpp' },
+			{ startIndex: 8, type: 'delimiter.cpp' }
+		]
+	}],
+
+	[{
+		line: 'x = /*/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.cpp' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cpp' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.cpp' }
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '0',
-	tokens: [
-		{ startIndex: 0, type: 'number.cpp' }
-	]}],
+		line: '0',
+		tokens: [
+			{ startIndex: 0, type: 'number.cpp' }
+		]
+	}],
 
 	[{
-	line: '12l',
-	tokens: [
-		{ startIndex: 0, type: 'number.cpp' }
-	]}],
+		line: '12l',
+		tokens: [
+			{ startIndex: 0, type: 'number.cpp' }
+		]
+	}],
 
 	[{
-	line: '34U',
-	tokens: [
-		{ startIndex: 0, type: 'number.cpp' }
-	]}],
+		line: '34U',
+		tokens: [
+			{ startIndex: 0, type: 'number.cpp' }
+		]
+	}],
 
 	[{
-	line: '55LL',
-	tokens: [
-		{ startIndex: 0, type: 'number.cpp' }
-	]}],
+		line: '55LL',
+		tokens: [
+			{ startIndex: 0, type: 'number.cpp' }
+		]
+	}],
 
 	[{
-	line: '34ul',
-	tokens: [
-		{ startIndex: 0, type: 'number.cpp' }
-	]}],
+		line: '34ul',
+		tokens: [
+			{ startIndex: 0, type: 'number.cpp' }
+		]
+	}],
 
 	[{
-	line: '55llU',
-	tokens: [
-		{ startIndex: 0, type: 'number.cpp' }
-	]}],
+		line: '55llU',
+		tokens: [
+			{ startIndex: 0, type: 'number.cpp' }
+		]
+	}],
 
 	[{
-	line: '5\'5llU',
-	tokens: [
-		{ startIndex: 0, type: 'number.cpp' }
-	]}],
+		line: '5\'5llU',
+		tokens: [
+			{ startIndex: 0, type: 'number.cpp' }
+		]
+	}],
 
 	[{
-	line: '100\'000\'000',
-	tokens: [
-		{ startIndex: 0, type: 'number.cpp' }
-	]}],
+		line: '100\'000\'000',
+		tokens: [
+			{ startIndex: 0, type: 'number.cpp' }
+		]
+	}],
 
 	[{
-	line: '0x100\'aafllU',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.cpp' }
-	]}],
+		line: '0x100\'aafllU',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.cpp' }
+		]
+	}],
 
 	[{
-	line: '0342\'325',
-	tokens: [
-		{ startIndex: 0, type: 'number.octal.cpp' }
-	]}],
+		line: '0342\'325',
+		tokens: [
+			{ startIndex: 0, type: 'number.octal.cpp' }
+		]
+	}],
 
 	[{
-	line: '0x123',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.cpp' }
-	]}],
+		line: '0x123',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.cpp' }
+		]
+	}],
 
 	[{
-	line: '23.5',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '23.5',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '23.5e3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '23.5e3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '23.5E3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '23.5E3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '23.5F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '23.5F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '23.5f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '23.5f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '1.72E3F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '1.72E3F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '1.72E3f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '1.72E3f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '1.72e3F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '1.72e3F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '1.72e3f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '1.72e3f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '23.5L',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '23.5L',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '23.5l',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '23.5l',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '1.72E3L',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '1.72E3L',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '1.72E3l',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '1.72E3l',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '1.72e3L',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '1.72e3L',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '1.72e3l',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cpp' }
-	]}],
+		line: '1.72e3l',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cpp' }
+		]
+	}],
 
 	[{
-	line: '0+0',
-	tokens: [
-		{ startIndex: 0, type: 'number.cpp' },
-		{ startIndex: 1, type: 'delimiter.cpp' },
-		{ startIndex: 2, type: 'number.cpp' }
-	]}],
+		line: '0+0',
+		tokens: [
+			{ startIndex: 0, type: 'number.cpp' },
+			{ startIndex: 1, type: 'delimiter.cpp' },
+			{ startIndex: 2, type: 'number.cpp' }
+		]
+	}],
 
 	[{
-	line: '100+10',
-	tokens: [
-		{ startIndex: 0, type: 'number.cpp' },
-		{ startIndex: 3, type: 'delimiter.cpp' },
-		{ startIndex: 4, type: 'number.cpp' }
-	]}],
+		line: '100+10',
+		tokens: [
+			{ startIndex: 0, type: 'number.cpp' },
+			{ startIndex: 3, type: 'delimiter.cpp' },
+			{ startIndex: 4, type: 'number.cpp' }
+		]
+	}],
 
 	[{
-	line: '0 + 0',
-	tokens: [
-		{ startIndex: 0, type: 'number.cpp' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cpp' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.cpp' }
-	]}],
+		line: '0 + 0',
+		tokens: [
+			{ startIndex: 0, type: 'number.cpp' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cpp' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.cpp' }
+		]
+	}],
 
 	// Monarch Generated
 	[{
-	line: '#include<iostream>',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.cpp' },
-		{ startIndex: 8, type: 'delimiter.angle.cpp' },
-		{ startIndex: 9, type: 'identifier.cpp' },
-		{ startIndex: 17, type: 'delimiter.angle.cpp' }
-	]}, {
-	line: '#include "/path/to/my/file.h"',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.cpp' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'string.cpp' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '#ifdef VAR',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.cpp' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.cpp' }
-	]}, {
-	line: '#define SUM(A,B) (A) + (B)',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.cpp' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.cpp' },
-		{ startIndex: 11, type: 'delimiter.parenthesis.cpp' },
-		{ startIndex: 12, type: 'identifier.cpp' },
-		{ startIndex: 13, type: 'delimiter.cpp' },
-		{ startIndex: 14, type: 'identifier.cpp' },
-		{ startIndex: 15, type: 'delimiter.parenthesis.cpp' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'delimiter.parenthesis.cpp' },
-		{ startIndex: 18, type: 'identifier.cpp' },
-		{ startIndex: 19, type: 'delimiter.parenthesis.cpp' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'delimiter.cpp' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'delimiter.parenthesis.cpp' },
-		{ startIndex: 24, type: 'identifier.cpp' },
-		{ startIndex: 25, type: 'delimiter.parenthesis.cpp' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'int main(int argc, char** argv)',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.int.cpp' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.cpp' },
-		{ startIndex: 8, type: 'delimiter.parenthesis.cpp' },
-		{ startIndex: 9, type: 'keyword.int.cpp' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'identifier.cpp' },
-		{ startIndex: 17, type: 'delimiter.cpp' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'keyword.char.cpp' },
-		{ startIndex: 23, type: '' },
-		{ startIndex: 26, type: 'identifier.cpp' },
-		{ startIndex: 30, type: 'delimiter.parenthesis.cpp' }
-	]}, {
-	line: '{',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.cpp' }
-	]}, {
-	line: '	return 0;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'keyword.return.cpp' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.cpp' },
-		{ startIndex: 9, type: 'delimiter.cpp' }
-	]}, {
-	line: '}',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.cpp' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'namespace TestSpace',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.namespace.cpp' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'identifier.cpp' }
-	]}, {
-	line: '{',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.cpp' }
-	]}, {
-	line: '	using Asdf.CDE;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'keyword.using.cpp' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.cpp' },
-		{ startIndex: 11, type: 'delimiter.cpp' },
-		{ startIndex: 12, type: 'identifier.cpp' },
-		{ startIndex: 15, type: 'delimiter.cpp' }
-	]}, {
-	line: '	template <typename T>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'keyword.template.cpp' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'delimiter.angle.cpp' },
-		{ startIndex: 11, type: 'keyword.typename.cpp' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'identifier.cpp' },
-		{ startIndex: 21, type: 'delimiter.angle.cpp' }
-	]}, {
-	line: '	class CoolClass : protected BaseClass',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'keyword.class.cpp' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.cpp' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'delimiter.cpp' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'keyword.protected.cpp' },
-		{ startIndex: 28, type: '' },
-		{ startIndex: 29, type: 'identifier.cpp' }
-	]}, {
-	line: '	{',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.curly.cpp' }
-	]}, {
-	line: '		private:',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.private.cpp' },
-		{ startIndex: 9, type: 'delimiter.cpp' }
-	]}, {
-	line: '		',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '		static T field;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.static.cpp' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'identifier.cpp' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'identifier.cpp' },
-		{ startIndex: 16, type: 'delimiter.cpp' }
-	]}, {
-	line: '		',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '		public:',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.public.cpp' },
-		{ startIndex: 8, type: 'delimiter.cpp' }
-	]}, {
-	line: '		',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '		[[deprecated]]',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'annotation.cpp' }
-	]}, {
-	line: '		foo method() const override',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.cpp' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.cpp' },
-		{ startIndex: 12, type: 'delimiter.parenthesis.cpp' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'keyword.const.cpp' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'keyword.override.cpp' }
-	]}, {
-	line: '		{',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.curly.cpp' }
-	]}, {
-	line: '			auto s = new Bar();',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.auto.cpp' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.cpp' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'delimiter.cpp' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'keyword.new.cpp' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'identifier.cpp' },
-		{ startIndex: 19, type: 'delimiter.parenthesis.cpp' },
-		{ startIndex: 21, type: 'delimiter.cpp' }
-	]}, {
-	line: '			',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '			if (s.field) {',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.if.cpp' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.parenthesis.cpp' },
-		{ startIndex: 7, type: 'identifier.cpp' },
-		{ startIndex: 8, type: 'delimiter.cpp' },
-		{ startIndex: 9, type: 'identifier.cpp' },
-		{ startIndex: 14, type: 'delimiter.parenthesis.cpp' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'delimiter.curly.cpp' }
-	]}, {
-	line: '				for(const auto & b : s.field) {',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.for.cpp' },
-		{ startIndex: 7, type: 'delimiter.parenthesis.cpp' },
-		{ startIndex: 8, type: 'keyword.const.cpp' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'keyword.auto.cpp' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'delimiter.cpp' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'identifier.cpp' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'delimiter.cpp' },
-		{ startIndex: 24, type: '' },
-		{ startIndex: 25, type: 'identifier.cpp' },
-		{ startIndex: 26, type: 'delimiter.cpp' },
-		{ startIndex: 27, type: 'identifier.cpp' },
-		{ startIndex: 32, type: 'delimiter.parenthesis.cpp' },
-		{ startIndex: 33, type: '' },
-		{ startIndex: 34, type: 'delimiter.curly.cpp' }
-	]}, {
-	line: '					break;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: 'keyword.break.cpp' },
-		{ startIndex: 10, type: 'delimiter.cpp' }
-	]}, {
-	line: '				}',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'delimiter.curly.cpp' }
-	]}, {
-	line: '			}',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'delimiter.curly.cpp' }
-	]}, {
-	line: '		}',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.curly.cpp' }
-	]}, {
-	line: '		',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '		std::string s = "hello wordld\\n";',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.cpp' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 7, type: 'identifier.cpp' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'identifier.cpp' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'delimiter.cpp' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: 'string.cpp' },
-		{ startIndex: 31, type: 'string.escape.cpp' },
-		{ startIndex: 33, type: 'string.cpp' },
-		{ startIndex: 34, type: 'delimiter.cpp' }
-	]}, {
-	line: '		',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '		int number = 123\'123\'123Ull;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.int.cpp' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.cpp' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'delimiter.cpp' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'number.cpp' },
-		{ startIndex: 29, type: 'delimiter.cpp' }
-	]}, {
-	line: '	}',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.curly.cpp' }
-	]}, {
-	line: '}',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.cpp' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '#endif',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.cpp' }
-	]}]
+		line: '#include<iostream>',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.cpp' },
+			{ startIndex: 8, type: 'delimiter.angle.cpp' },
+			{ startIndex: 9, type: 'identifier.cpp' },
+			{ startIndex: 17, type: 'delimiter.angle.cpp' }
+		]
+	}, {
+		line: '#include "/path/to/my/file.h"',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.cpp' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'string.cpp' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '#ifdef VAR',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.cpp' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.cpp' }
+		]
+	}, {
+		line: '#define SUM(A,B) (A) + (B)',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.cpp' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.cpp' },
+			{ startIndex: 11, type: 'delimiter.parenthesis.cpp' },
+			{ startIndex: 12, type: 'identifier.cpp' },
+			{ startIndex: 13, type: 'delimiter.cpp' },
+			{ startIndex: 14, type: 'identifier.cpp' },
+			{ startIndex: 15, type: 'delimiter.parenthesis.cpp' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'delimiter.parenthesis.cpp' },
+			{ startIndex: 18, type: 'identifier.cpp' },
+			{ startIndex: 19, type: 'delimiter.parenthesis.cpp' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'delimiter.cpp' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'delimiter.parenthesis.cpp' },
+			{ startIndex: 24, type: 'identifier.cpp' },
+			{ startIndex: 25, type: 'delimiter.parenthesis.cpp' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'int main(int argc, char** argv)',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.int.cpp' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.cpp' },
+			{ startIndex: 8, type: 'delimiter.parenthesis.cpp' },
+			{ startIndex: 9, type: 'keyword.int.cpp' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'identifier.cpp' },
+			{ startIndex: 17, type: 'delimiter.cpp' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'keyword.char.cpp' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 26, type: 'identifier.cpp' },
+			{ startIndex: 30, type: 'delimiter.parenthesis.cpp' }
+		]
+	}, {
+		line: '{',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.cpp' }
+		]
+	}, {
+		line: '	return 0;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'keyword.return.cpp' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.cpp' },
+			{ startIndex: 9, type: 'delimiter.cpp' }
+		]
+	}, {
+		line: '}',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.cpp' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'namespace TestSpace',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.namespace.cpp' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.cpp' }
+		]
+	}, {
+		line: '{',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.cpp' }
+		]
+	}, {
+		line: '	using Asdf.CDE;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'keyword.using.cpp' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.cpp' },
+			{ startIndex: 11, type: 'delimiter.cpp' },
+			{ startIndex: 12, type: 'identifier.cpp' },
+			{ startIndex: 15, type: 'delimiter.cpp' }
+		]
+	}, {
+		line: '	template <typename T>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'keyword.template.cpp' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'delimiter.angle.cpp' },
+			{ startIndex: 11, type: 'keyword.typename.cpp' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'identifier.cpp' },
+			{ startIndex: 21, type: 'delimiter.angle.cpp' }
+		]
+	}, {
+		line: '	class CoolClass : protected BaseClass',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'keyword.class.cpp' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.cpp' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'delimiter.cpp' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'keyword.protected.cpp' },
+			{ startIndex: 28, type: '' },
+			{ startIndex: 29, type: 'identifier.cpp' }
+		]
+	}, {
+		line: '	{',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.curly.cpp' }
+		]
+	}, {
+		line: '		private:',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.private.cpp' },
+			{ startIndex: 9, type: 'delimiter.cpp' }
+		]
+	}, {
+		line: '		',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '		static T field;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.static.cpp' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'identifier.cpp' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'identifier.cpp' },
+			{ startIndex: 16, type: 'delimiter.cpp' }
+		]
+	}, {
+		line: '		',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '		public:',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.public.cpp' },
+			{ startIndex: 8, type: 'delimiter.cpp' }
+		]
+	}, {
+		line: '		',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '		[[deprecated]]',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'annotation.cpp' }
+		]
+	}, {
+		line: '		foo method() const override',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.cpp' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.cpp' },
+			{ startIndex: 12, type: 'delimiter.parenthesis.cpp' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'keyword.const.cpp' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'keyword.override.cpp' }
+		]
+	}, {
+		line: '		{',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.curly.cpp' }
+		]
+	}, {
+		line: '			auto s = new Bar();',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.auto.cpp' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.cpp' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'delimiter.cpp' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'keyword.new.cpp' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'identifier.cpp' },
+			{ startIndex: 19, type: 'delimiter.parenthesis.cpp' },
+			{ startIndex: 21, type: 'delimiter.cpp' }
+		]
+	}, {
+		line: '			',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '			if (s.field) {',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.if.cpp' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.parenthesis.cpp' },
+			{ startIndex: 7, type: 'identifier.cpp' },
+			{ startIndex: 8, type: 'delimiter.cpp' },
+			{ startIndex: 9, type: 'identifier.cpp' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.cpp' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'delimiter.curly.cpp' }
+		]
+	}, {
+		line: '				for(const auto & b : s.field) {',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.for.cpp' },
+			{ startIndex: 7, type: 'delimiter.parenthesis.cpp' },
+			{ startIndex: 8, type: 'keyword.const.cpp' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'keyword.auto.cpp' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'delimiter.cpp' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'identifier.cpp' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'delimiter.cpp' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'identifier.cpp' },
+			{ startIndex: 26, type: 'delimiter.cpp' },
+			{ startIndex: 27, type: 'identifier.cpp' },
+			{ startIndex: 32, type: 'delimiter.parenthesis.cpp' },
+			{ startIndex: 33, type: '' },
+			{ startIndex: 34, type: 'delimiter.curly.cpp' }
+		]
+	}, {
+		line: '					break;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'keyword.break.cpp' },
+			{ startIndex: 10, type: 'delimiter.cpp' }
+		]
+	}, {
+		line: '				}',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'delimiter.curly.cpp' }
+		]
+	}, {
+		line: '			}',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'delimiter.curly.cpp' }
+		]
+	}, {
+		line: '		}',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.curly.cpp' }
+		]
+	}, {
+		line: '		',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '		std::string s = "hello wordld\\n";',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.cpp' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 7, type: 'identifier.cpp' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'identifier.cpp' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'delimiter.cpp' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'string.cpp' },
+			{ startIndex: 31, type: 'string.escape.cpp' },
+			{ startIndex: 33, type: 'string.cpp' },
+			{ startIndex: 34, type: 'delimiter.cpp' }
+		]
+	}, {
+		line: '		',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '		int number = 123\'123\'123Ull;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.int.cpp' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.cpp' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'delimiter.cpp' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'number.cpp' },
+			{ startIndex: 29, type: 'delimiter.cpp' }
+		]
+	}, {
+		line: '	}',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.curly.cpp' }
+		]
+	}, {
+		line: '}',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.cpp' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '#endif',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.cpp' }
+		]
+	}]
 ]);

+ 825 - 731
test/csharp.test.ts

@@ -5,816 +5,910 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('csharp', [
 
 	// Generated from sample
 	[{
-	line: 'using System;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.using.cs' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'namespace.cs' },
-		{ startIndex: 12, type: 'delimiter.cs' }
-	]}, {
-	line: 'using System.Collections.Generic;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.using.cs' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'namespace.cs' },
-		{ startIndex: 12, type: 'delimiter.cs' },
-		{ startIndex: 13, type: 'namespace.cs' },
-		{ startIndex: 24, type: 'delimiter.cs' },
-		{ startIndex: 25, type: 'namespace.cs' },
-		{ startIndex: 32, type: 'delimiter.cs' }
-	]}, {
-	line: 'using System.Diagnostics;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.using.cs' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'namespace.cs' },
-		{ startIndex: 12, type: 'delimiter.cs' },
-		{ startIndex: 13, type: 'namespace.cs' },
-		{ startIndex: 24, type: 'delimiter.cs' }
-	]}, {
-	line: 'using System.Linq;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.using.cs' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'namespace.cs' },
-		{ startIndex: 12, type: 'delimiter.cs' },
-		{ startIndex: 13, type: 'namespace.cs' },
-		{ startIndex: 17, type: 'delimiter.cs' }
-	]}, {
-	line: 'using System.Text;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.using.cs' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'namespace.cs' },
-		{ startIndex: 12, type: 'delimiter.cs' },
-		{ startIndex: 13, type: 'namespace.cs' },
-		{ startIndex: 17, type: 'delimiter.cs' }
-	]}, {
-	line: 'using System.Threading.Tasks;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.using.cs' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'namespace.cs' },
-		{ startIndex: 12, type: 'delimiter.cs' },
-		{ startIndex: 13, type: 'namespace.cs' },
-		{ startIndex: 22, type: 'delimiter.cs' },
-		{ startIndex: 23, type: 'namespace.cs' },
-		{ startIndex: 28, type: 'delimiter.cs' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'namespace VS',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.namespace.cs' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'namespace.cs' }
-	]}, {
-	line: '{',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.cs' }
-	]}, {
-	line: '	class Program',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'keyword.class.cs' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.cs' }
-	]}, {
-	line: '	{',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.curly.cs' }
-	]}, {
-	line: '		static void Main(string[] args)',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.static.cs' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'keyword.void.cs' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'identifier.cs' },
-		{ startIndex: 18, type: 'delimiter.parenthesis.cs' },
-		{ startIndex: 19, type: 'keyword.string.cs' },
-		{ startIndex: 25, type: 'delimiter.square.cs' },
-		{ startIndex: 27, type: '' },
-		{ startIndex: 28, type: 'identifier.cs' },
-		{ startIndex: 32, type: 'delimiter.parenthesis.cs' }
-	]}, {
-	line: '		{',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.curly.cs' }
-	]}, {
-	line: '			ProcessStartInfo si = new ProcessStartInfo();',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'identifier.cs' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'identifier.cs' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'delimiter.cs' },
-		{ startIndex: 24, type: '' },
-		{ startIndex: 25, type: 'keyword.new.cs' },
-		{ startIndex: 28, type: '' },
-		{ startIndex: 29, type: 'identifier.cs' },
-		{ startIndex: 45, type: 'delimiter.parenthesis.cs' },
-		{ startIndex: 47, type: 'delimiter.cs' }
-	]}, {
-	line: '			float load= 3.2e02f;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.float.cs' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'identifier.cs' },
-		{ startIndex: 13, type: 'delimiter.cs' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'number.float.cs' },
-		{ startIndex: 22, type: 'delimiter.cs' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '			si.FileName = @"tools\\\\node.exe";',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'identifier.cs' },
-		{ startIndex: 5, type: 'delimiter.cs' },
-		{ startIndex: 6, type: 'identifier.cs' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'delimiter.cs' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'string.quote.cs' },
-		{ startIndex: 19, type: 'string.cs' },
-		{ startIndex: 34, type: 'string.quote.cs' },
-		{ startIndex: 35, type: 'delimiter.cs' }
-	]}, {
-	line: '			si.Arguments = "tools\\\\simpl3server.js";',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'identifier.cs' },
-		{ startIndex: 5, type: 'delimiter.cs' },
-		{ startIndex: 6, type: 'identifier.cs' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'delimiter.cs' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: 'string.quote.cs' },
-		{ startIndex: 19, type: 'string.cs' },
-		{ startIndex: 24, type: 'string.escape.cs' },
-		{ startIndex: 26, type: 'string.cs' },
-		{ startIndex: 41, type: 'string.quote.cs' },
-		{ startIndex: 42, type: 'delimiter.cs' }
-	]}, {
-	line: '			',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '			string someString = $"hello{outside+variable}the string again {{ escaped";',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.string.cs' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'identifier.cs' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'delimiter.cs' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'string.quote.cs' },
-		{ startIndex: 25, type: 'string.cs' },
-		{ startIndex: 30, type: 'string.quote.cs' },
-		{ startIndex: 31, type: 'identifier.cs' },
-		{ startIndex: 38, type: 'delimiter.cs' },
-		{ startIndex: 39, type: 'identifier.cs' },
-		{ startIndex: 47, type: 'string.quote.cs' },
-		{ startIndex: 48, type: 'string.cs' },
-		{ startIndex: 65, type: 'string.escape.cs' },
-		{ startIndex: 67, type: 'string.cs' },
-		{ startIndex: 75, type: 'string.quote.cs' },
-		{ startIndex: 76, type: 'delimiter.cs' }
-	]}, {
-	line: '			var @string = 5;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.var.cs' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.cs' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'delimiter.cs' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'number.cs' },
-		{ startIndex: 18, type: 'delimiter.cs' }
-	]}, {
-	line: '			',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '			if (x == 4)',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.if.cs' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.parenthesis.cs' },
-		{ startIndex: 7, type: 'identifier.cs' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'delimiter.cs' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'number.cs' },
-		{ startIndex: 13, type: 'delimiter.parenthesis.cs' }
-	]}, {
-	line: '			{',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'delimiter.curly.cs' }
-	]}, {
-	line: '				for (int i = 4; i<10; i++)',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.for.cs' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'delimiter.parenthesis.cs' },
-		{ startIndex: 9, type: 'keyword.int.cs' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'identifier.cs' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'delimiter.cs' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'number.cs' },
-		{ startIndex: 18, type: 'delimiter.cs' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'identifier.cs' },
-		{ startIndex: 21, type: 'delimiter.angle.cs' },
-		{ startIndex: 22, type: 'number.cs' },
-		{ startIndex: 24, type: 'delimiter.cs' },
-		{ startIndex: 25, type: '' },
-		{ startIndex: 26, type: 'identifier.cs' },
-		{ startIndex: 27, type: 'delimiter.cs' },
-		{ startIndex: 29, type: 'delimiter.parenthesis.cs' }
-	]}, {
-	line: '				{',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'delimiter.curly.cs' }
-	]}, {
-	line: '					var d = i;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: 'keyword.var.cs' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'identifier.cs' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'delimiter.cs' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'identifier.cs' },
-		{ startIndex: 14, type: 'delimiter.cs' }
-	]}, {
-	line: '				}',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'delimiter.curly.cs' }
-	]}, {
-	line: '			}',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'delimiter.curly.cs' }
-	]}, {
-	line: '			else',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.else.cs' }
-	]}, {
-	line: '			{',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'delimiter.curly.cs' }
-	]}, {
-	line: '				return;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.return.cs' },
-		{ startIndex: 10, type: 'delimiter.cs' }
-	]}, {
-	line: '			}',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'delimiter.curly.cs' }
-	]}, {
-	line: '			',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '			Process.Start(si);',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'identifier.cs' },
-		{ startIndex: 10, type: 'delimiter.cs' },
-		{ startIndex: 11, type: 'identifier.cs' },
-		{ startIndex: 16, type: 'delimiter.parenthesis.cs' },
-		{ startIndex: 17, type: 'identifier.cs' },
-		{ startIndex: 19, type: 'delimiter.parenthesis.cs' },
-		{ startIndex: 20, type: 'delimiter.cs' }
-	]}, {
-	line: '		}',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.curly.cs' }
-	]}, {
-	line: '	}',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.curly.cs' }
-	]}, {
-	line: '}',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.cs' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '#pragma region /MapLayer/*Image* /// ',
-	tokens: [
-		{ startIndex: 0, type: 'namespace.cpp.cs' }
-	]}, {
-	line: 'namespace ShouldNotBeAComment {}',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.namespace.cs' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'namespace.cs' },
-		{ startIndex: 29, type: '' },
-		{ startIndex: 30, type: 'delimiter.curly.cs' }
-	]}, {
-	line: '#pragma endregion Region_1',
-	tokens: [
-		{ startIndex: 0, type: 'namespace.cpp.cs' }
-	]}],
+		line: 'using System;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.using.cs' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'namespace.cs' },
+			{ startIndex: 12, type: 'delimiter.cs' }
+		]
+	}, {
+		line: 'using System.Collections.Generic;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.using.cs' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'namespace.cs' },
+			{ startIndex: 12, type: 'delimiter.cs' },
+			{ startIndex: 13, type: 'namespace.cs' },
+			{ startIndex: 24, type: 'delimiter.cs' },
+			{ startIndex: 25, type: 'namespace.cs' },
+			{ startIndex: 32, type: 'delimiter.cs' }
+		]
+	}, {
+		line: 'using System.Diagnostics;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.using.cs' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'namespace.cs' },
+			{ startIndex: 12, type: 'delimiter.cs' },
+			{ startIndex: 13, type: 'namespace.cs' },
+			{ startIndex: 24, type: 'delimiter.cs' }
+		]
+	}, {
+		line: 'using System.Linq;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.using.cs' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'namespace.cs' },
+			{ startIndex: 12, type: 'delimiter.cs' },
+			{ startIndex: 13, type: 'namespace.cs' },
+			{ startIndex: 17, type: 'delimiter.cs' }
+		]
+	}, {
+		line: 'using System.Text;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.using.cs' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'namespace.cs' },
+			{ startIndex: 12, type: 'delimiter.cs' },
+			{ startIndex: 13, type: 'namespace.cs' },
+			{ startIndex: 17, type: 'delimiter.cs' }
+		]
+	}, {
+		line: 'using System.Threading.Tasks;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.using.cs' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'namespace.cs' },
+			{ startIndex: 12, type: 'delimiter.cs' },
+			{ startIndex: 13, type: 'namespace.cs' },
+			{ startIndex: 22, type: 'delimiter.cs' },
+			{ startIndex: 23, type: 'namespace.cs' },
+			{ startIndex: 28, type: 'delimiter.cs' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'namespace VS',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.namespace.cs' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'namespace.cs' }
+		]
+	}, {
+		line: '{',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.cs' }
+		]
+	}, {
+		line: '	class Program',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'keyword.class.cs' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.cs' }
+		]
+	}, {
+		line: '	{',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.curly.cs' }
+		]
+	}, {
+		line: '		static void Main(string[] args)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.static.cs' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'keyword.void.cs' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'identifier.cs' },
+			{ startIndex: 18, type: 'delimiter.parenthesis.cs' },
+			{ startIndex: 19, type: 'keyword.string.cs' },
+			{ startIndex: 25, type: 'delimiter.square.cs' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'identifier.cs' },
+			{ startIndex: 32, type: 'delimiter.parenthesis.cs' }
+		]
+	}, {
+		line: '		{',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.curly.cs' }
+		]
+	}, {
+		line: '			ProcessStartInfo si = new ProcessStartInfo();',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'identifier.cs' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'identifier.cs' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'delimiter.cs' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'keyword.new.cs' },
+			{ startIndex: 28, type: '' },
+			{ startIndex: 29, type: 'identifier.cs' },
+			{ startIndex: 45, type: 'delimiter.parenthesis.cs' },
+			{ startIndex: 47, type: 'delimiter.cs' }
+		]
+	}, {
+		line: '			float load= 3.2e02f;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.float.cs' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'identifier.cs' },
+			{ startIndex: 13, type: 'delimiter.cs' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'number.float.cs' },
+			{ startIndex: 22, type: 'delimiter.cs' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '			si.FileName = @"tools\\\\node.exe";',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'identifier.cs' },
+			{ startIndex: 5, type: 'delimiter.cs' },
+			{ startIndex: 6, type: 'identifier.cs' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'delimiter.cs' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'string.quote.cs' },
+			{ startIndex: 19, type: 'string.cs' },
+			{ startIndex: 34, type: 'string.quote.cs' },
+			{ startIndex: 35, type: 'delimiter.cs' }
+		]
+	}, {
+		line: '			si.Arguments = "tools\\\\simpl3server.js";',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'identifier.cs' },
+			{ startIndex: 5, type: 'delimiter.cs' },
+			{ startIndex: 6, type: 'identifier.cs' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'delimiter.cs' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'string.quote.cs' },
+			{ startIndex: 19, type: 'string.cs' },
+			{ startIndex: 24, type: 'string.escape.cs' },
+			{ startIndex: 26, type: 'string.cs' },
+			{ startIndex: 41, type: 'string.quote.cs' },
+			{ startIndex: 42, type: 'delimiter.cs' }
+		]
+	}, {
+		line: '			',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '			string someString = $"hello{outside+variable}the string again {{ escaped";',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.string.cs' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.cs' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'delimiter.cs' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'string.quote.cs' },
+			{ startIndex: 25, type: 'string.cs' },
+			{ startIndex: 30, type: 'string.quote.cs' },
+			{ startIndex: 31, type: 'identifier.cs' },
+			{ startIndex: 38, type: 'delimiter.cs' },
+			{ startIndex: 39, type: 'identifier.cs' },
+			{ startIndex: 47, type: 'string.quote.cs' },
+			{ startIndex: 48, type: 'string.cs' },
+			{ startIndex: 65, type: 'string.escape.cs' },
+			{ startIndex: 67, type: 'string.cs' },
+			{ startIndex: 75, type: 'string.quote.cs' },
+			{ startIndex: 76, type: 'delimiter.cs' }
+		]
+	}, {
+		line: '			var @string = 5;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.var.cs' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.cs' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'delimiter.cs' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'number.cs' },
+			{ startIndex: 18, type: 'delimiter.cs' }
+		]
+	}, {
+		line: '			',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '			if (x == 4)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.if.cs' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.parenthesis.cs' },
+			{ startIndex: 7, type: 'identifier.cs' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.cs' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'number.cs' },
+			{ startIndex: 13, type: 'delimiter.parenthesis.cs' }
+		]
+	}, {
+		line: '			{',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'delimiter.curly.cs' }
+		]
+	}, {
+		line: '				for (int i = 4; i<10; i++)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.for.cs' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.parenthesis.cs' },
+			{ startIndex: 9, type: 'keyword.int.cs' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'identifier.cs' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'delimiter.cs' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'number.cs' },
+			{ startIndex: 18, type: 'delimiter.cs' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'identifier.cs' },
+			{ startIndex: 21, type: 'delimiter.angle.cs' },
+			{ startIndex: 22, type: 'number.cs' },
+			{ startIndex: 24, type: 'delimiter.cs' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'identifier.cs' },
+			{ startIndex: 27, type: 'delimiter.cs' },
+			{ startIndex: 29, type: 'delimiter.parenthesis.cs' }
+		]
+	}, {
+		line: '				{',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'delimiter.curly.cs' }
+		]
+	}, {
+		line: '					var d = i;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'keyword.var.cs' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'identifier.cs' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'delimiter.cs' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'identifier.cs' },
+			{ startIndex: 14, type: 'delimiter.cs' }
+		]
+	}, {
+		line: '				}',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'delimiter.curly.cs' }
+		]
+	}, {
+		line: '			}',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'delimiter.curly.cs' }
+		]
+	}, {
+		line: '			else',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.else.cs' }
+		]
+	}, {
+		line: '			{',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'delimiter.curly.cs' }
+		]
+	}, {
+		line: '				return;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.return.cs' },
+			{ startIndex: 10, type: 'delimiter.cs' }
+		]
+	}, {
+		line: '			}',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'delimiter.curly.cs' }
+		]
+	}, {
+		line: '			',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '			Process.Start(si);',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'identifier.cs' },
+			{ startIndex: 10, type: 'delimiter.cs' },
+			{ startIndex: 11, type: 'identifier.cs' },
+			{ startIndex: 16, type: 'delimiter.parenthesis.cs' },
+			{ startIndex: 17, type: 'identifier.cs' },
+			{ startIndex: 19, type: 'delimiter.parenthesis.cs' },
+			{ startIndex: 20, type: 'delimiter.cs' }
+		]
+	}, {
+		line: '		}',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.curly.cs' }
+		]
+	}, {
+		line: '	}',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.curly.cs' }
+		]
+	}, {
+		line: '}',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.cs' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '#pragma region /MapLayer/*Image* /// ',
+		tokens: [
+			{ startIndex: 0, type: 'namespace.cpp.cs' }
+		]
+	}, {
+		line: 'namespace ShouldNotBeAComment {}',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.namespace.cs' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'namespace.cs' },
+			{ startIndex: 29, type: '' },
+			{ startIndex: 30, type: 'delimiter.curly.cs' }
+		]
+	}, {
+		line: '#pragma endregion Region_1',
+		tokens: [
+			{ startIndex: 0, type: 'namespace.cpp.cs' }
+		]
+	}],
 
 	// Keywords
 	[{
-	line: 'namespace VS { class Program { static void Main(string[] args) {} } }',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.namespace.cs' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'namespace.cs' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'delimiter.curly.cs' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'keyword.class.cs' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'identifier.cs' },
-		{ startIndex: 28, type: '' },
-		{ startIndex: 29, type: 'delimiter.curly.cs' },
-		{ startIndex: 30, type: '' },
-		{ startIndex: 31, type: 'keyword.static.cs' },
-		{ startIndex: 37, type: '' },
-		{ startIndex: 38, type: 'keyword.void.cs' },
-		{ startIndex: 42, type: '' },
-		{ startIndex: 43, type: 'identifier.cs' },
-		{ startIndex: 47, type: 'delimiter.parenthesis.cs' },
-		{ startIndex: 48, type: 'keyword.string.cs' },
-		{ startIndex: 54, type: 'delimiter.square.cs' },
-		{ startIndex: 56, type: '' },
-		{ startIndex: 57, type: 'identifier.cs' },
-		{ startIndex: 61, type: 'delimiter.parenthesis.cs' },
-		{ startIndex: 62, type: '' },
-		{ startIndex: 63, type: 'delimiter.curly.cs' },
-		{ startIndex: 65, type: '' },
-		{ startIndex: 66, type: 'delimiter.curly.cs' },
-		{ startIndex: 67, type: '' },
-		{ startIndex: 68, type: 'delimiter.curly.cs' }
-	]}],
+		line: 'namespace VS { class Program { static void Main(string[] args) {} } }',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.namespace.cs' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'namespace.cs' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'delimiter.curly.cs' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'keyword.class.cs' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'identifier.cs' },
+			{ startIndex: 28, type: '' },
+			{ startIndex: 29, type: 'delimiter.curly.cs' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'keyword.static.cs' },
+			{ startIndex: 37, type: '' },
+			{ startIndex: 38, type: 'keyword.void.cs' },
+			{ startIndex: 42, type: '' },
+			{ startIndex: 43, type: 'identifier.cs' },
+			{ startIndex: 47, type: 'delimiter.parenthesis.cs' },
+			{ startIndex: 48, type: 'keyword.string.cs' },
+			{ startIndex: 54, type: 'delimiter.square.cs' },
+			{ startIndex: 56, type: '' },
+			{ startIndex: 57, type: 'identifier.cs' },
+			{ startIndex: 61, type: 'delimiter.parenthesis.cs' },
+			{ startIndex: 62, type: '' },
+			{ startIndex: 63, type: 'delimiter.curly.cs' },
+			{ startIndex: 65, type: '' },
+			{ startIndex: 66, type: 'delimiter.curly.cs' },
+			{ startIndex: 67, type: '' },
+			{ startIndex: 68, type: 'delimiter.curly.cs' }
+		]
+	}],
 
 	// Comments - single line
 	[{
-	line: '//',
-	tokens: [
-		{ startIndex: 0, type: 'comment.cs' }
-	]}],
-
-	[{
-	line: '    // a comment',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'comment.cs' }
-	]}],
-
-	[{
-	line: '// a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.cs' }
-	]}],
-
-	[{
-	line: '//sticky comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.cs' }
-	]}],
-
-	[{
-	line: '/almost a comment',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.cs' },
-		{ startIndex: 1, type: 'identifier.cs' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.cs' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'identifier.cs' }
-	]}],
-
-	[{
-	line: '1 / 2; /* comment',
-	tokens: [
-		{ startIndex: 0, type: 'number.cs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.cs' },
-		{ startIndex: 5, type: 'delimiter.cs' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'comment.cs' }
-	]}],
-
-	[{
-	line: 'var x = 1; // my comment // is a nice one',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.var.cs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.cs' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.cs' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.cs' },
-		{ startIndex: 9, type: 'delimiter.cs' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'comment.cs' }
-	]}],
+		line: '//',
+		tokens: [
+			{ startIndex: 0, type: 'comment.cs' }
+		]
+	}],
+
+	[{
+		line: '    // a comment',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'comment.cs' }
+		]
+	}],
+
+	[{
+		line: '// a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.cs' }
+		]
+	}],
+
+	[{
+		line: '//sticky comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.cs' }
+		]
+	}],
+
+	[{
+		line: '/almost a comment',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.cs' },
+			{ startIndex: 1, type: 'identifier.cs' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.cs' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.cs' }
+		]
+	}],
+
+	[{
+		line: '1 / 2; /* comment',
+		tokens: [
+			{ startIndex: 0, type: 'number.cs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.cs' },
+			{ startIndex: 5, type: 'delimiter.cs' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'comment.cs' }
+		]
+	}],
+
+	[{
+		line: 'var x = 1; // my comment // is a nice one',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.var.cs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.cs' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.cs' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.cs' },
+			{ startIndex: 9, type: 'delimiter.cs' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'comment.cs' }
+		]
+	}],
 
 	// Comments - range comment, single line
 	[{
-	line: '/* a simple comment */',
-	tokens: [
-		{ startIndex: 0, type: 'comment.cs' }
-	]}],
-
-	[{
-	line: 'var x = /* a simple comment */ 1;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.var.cs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.cs' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.cs' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.cs' },
-		{ startIndex: 30, type: '' },
-		{ startIndex: 31, type: 'number.cs' },
-		{ startIndex: 32, type: 'delimiter.cs' }
-	]}],
-
-	[{
-	line: 'var x = /* comment */ 1; */',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.var.cs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.cs' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.cs' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.cs' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'number.cs' },
-		{ startIndex: 23, type: 'delimiter.cs' },
-		{ startIndex: 24, type: '' }
-	]}],
-
-	[{
-	line: 'x = /**/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.cs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.cs' },
-		{ startIndex: 8, type: 'delimiter.cs' }
-	]}],
-
-	[{
-	line: 'x = /*/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.cs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.cs' }
-	]}],
+		line: '/* a simple comment */',
+		tokens: [
+			{ startIndex: 0, type: 'comment.cs' }
+		]
+	}],
+
+	[{
+		line: 'var x = /* a simple comment */ 1;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.var.cs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.cs' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.cs' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.cs' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'number.cs' },
+			{ startIndex: 32, type: 'delimiter.cs' }
+		]
+	}],
+
+	[{
+		line: 'var x = /* comment */ 1; */',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.var.cs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.cs' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.cs' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.cs' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'number.cs' },
+			{ startIndex: 23, type: 'delimiter.cs' },
+			{ startIndex: 24, type: '' }
+		]
+	}],
+
+	[{
+		line: 'x = /**/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.cs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.cs' },
+			{ startIndex: 8, type: 'delimiter.cs' }
+		]
+	}],
+
+	[{
+		line: 'x = /*/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.cs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.cs' }
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '0',
-	tokens: [
-		{ startIndex: 0, type: 'number.cs' }
-	]}],
+		line: '0',
+		tokens: [
+			{ startIndex: 0, type: 'number.cs' }
+		]
+	}],
 
 	[{
-	line: '123_456',
-	tokens: [
-		{ startIndex: 0, type: 'number.cs' }
-	]}],
+		line: '123_456',
+		tokens: [
+			{ startIndex: 0, type: 'number.cs' }
+		]
+	}],
 
 	[{
-	line: '0x',
-	tokens: [
-		{ startIndex: 0, type: 'number.cs' },
-		{ startIndex: 1, type: 'identifier.cs' }
-	]}],
+		line: '0x',
+		tokens: [
+			{ startIndex: 0, type: 'number.cs' },
+			{ startIndex: 1, type: 'identifier.cs' }
+		]
+	}],
 
 	[{
-	line: '0b',
-	tokens: [
-		{ startIndex: 0, type: 'number.cs' },
-		{ startIndex: 1, type: 'identifier.cs' }
-	]}],
+		line: '0b',
+		tokens: [
+			{ startIndex: 0, type: 'number.cs' },
+			{ startIndex: 1, type: 'identifier.cs' }
+		]
+	}],
 
 	[{
-	line: '0x123',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.cs' }
-	]}],
+		line: '0x123',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.cs' }
+		]
+	}],
 
 	[{
-	line: '0x123_456',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.cs' }
-	]}],
+		line: '0x123_456',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.cs' }
+		]
+	}],
 
 	[{
-	line: '0b101',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.cs' }
-	]}],
+		line: '0b101',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.cs' }
+		]
+	}],
 
 	[{
-	line: '0b1010_0001',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.cs' }
-	]}],
+		line: '0b1010_0001',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.cs' }
+		]
+	}],
 
 	[{
-	line: '23.5',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '23.5',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '1_23.5',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '1_23.5',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '23.5e3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '23.5e3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '23.5E3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '23.5E3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '23.5F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '23.5F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '23.5f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '23.5f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '2_3.5f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '2_3.5f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '1.72E3F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '1.72E3F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '1.72E3f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '1.72E3f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '1.72e3F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '1.72e3F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '1.72e3f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '1.72e3f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '23.5D',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '23.5D',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '456_123.5D',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '456_123.5D',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '23.5d',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '23.5d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '1.72E3D',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '1.72E3D',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '1.72E3d',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '1.72E3d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '1.720_123E3d',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '1.720_123E3d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '1.72e3D',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '1.72e3D',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '1.72e3d',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.cs' }
-	]}],
+		line: '1.72e3d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.cs' }
+		]
+	}],
 
 	[{
-	line: '0+0',
-	tokens: [
-		{ startIndex: 0, type: 'number.cs' },
-		{ startIndex: 1, type: 'delimiter.cs' },
-		{ startIndex: 2, type: 'number.cs' }
-	]}],
+		line: '0+0',
+		tokens: [
+			{ startIndex: 0, type: 'number.cs' },
+			{ startIndex: 1, type: 'delimiter.cs' },
+			{ startIndex: 2, type: 'number.cs' }
+		]
+	}],
 
 	[{
-	line: '100+10',
-	tokens: [
-		{ startIndex: 0, type: 'number.cs' },
-		{ startIndex: 3, type: 'delimiter.cs' },
-		{ startIndex: 4, type: 'number.cs' }
-	]}],
+		line: '100+10',
+		tokens: [
+			{ startIndex: 0, type: 'number.cs' },
+			{ startIndex: 3, type: 'delimiter.cs' },
+			{ startIndex: 4, type: 'number.cs' }
+		]
+	}],
 
 	[{
-	line: '0 + 0',
-	tokens: [
-		{ startIndex: 0, type: 'number.cs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.cs' }
-	]}],
+		line: '0 + 0',
+		tokens: [
+			{ startIndex: 0, type: 'number.cs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.cs' }
+		]
+	}],
 
 	// Strings
 	[{
-	line: 'x = "string";',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.cs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'string.quote.cs' },
-		{ startIndex: 5, type: 'string.cs' },
-		{ startIndex: 11, type: 'string.quote.cs' },
-		{ startIndex: 12, type: 'delimiter.cs' }
-	]}],
-
-	[{
-	line: 'x = "stri\\"ng";',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.cs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'string.quote.cs' },
-		{ startIndex: 5, type: 'string.cs' },
-		{ startIndex: 9, type: 'string.escape.cs' },
-		{ startIndex: 11, type: 'string.cs' },
-		{ startIndex: 13, type: 'string.quote.cs' },
-		{ startIndex: 14, type: 'delimiter.cs' }
-	]}],
+		line: 'x = "string";',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.cs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'string.quote.cs' },
+			{ startIndex: 5, type: 'string.cs' },
+			{ startIndex: 11, type: 'string.quote.cs' },
+			{ startIndex: 12, type: 'delimiter.cs' }
+		]
+	}],
+
+	[{
+		line: 'x = "stri\\"ng";',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.cs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'string.quote.cs' },
+			{ startIndex: 5, type: 'string.cs' },
+			{ startIndex: 9, type: 'string.escape.cs' },
+			{ startIndex: 11, type: 'string.cs' },
+			{ startIndex: 13, type: 'string.quote.cs' },
+			{ startIndex: 14, type: 'delimiter.cs' }
+		]
+	}],
 
 	// Verbatim Strings
 	[{
-	line: 'x = @"verbatimstring";',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.cs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'string.quote.cs' },
-		{ startIndex: 6, type: 'string.cs' },
-		{ startIndex: 20, type: 'string.quote.cs' },
-		{ startIndex: 21, type: 'delimiter.cs' }
-	]}],
-
-	[{
-	line: 'x = @"verbatim""string";',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.cs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'string.quote.cs' },
-		{ startIndex: 6, type: 'string.cs' },
-		{ startIndex: 14, type: 'string.escape.cs' },
-		{ startIndex: 16, type: 'string.cs' },
-		{ startIndex: 22, type: 'string.quote.cs' },
-		{ startIndex: 23, type: 'delimiter.cs' }
-	]}],
-
-	[{
-	line: 'x = @"verbatim\\string\\";',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.cs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'string.quote.cs' },
-		{ startIndex: 6, type: 'string.cs' },
-		{ startIndex: 22, type: 'string.quote.cs' },
-		{ startIndex: 23, type: 'delimiter.cs' }
-	]}],
-
-	[{
-	line: 'x = @"verbatim',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.cs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.cs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'string.quote.cs' },
-		{ startIndex: 6, type: 'string.cs' }
-	]},{
-	line: 'string";',
-	tokens: [
-		{ startIndex: 0, type: 'string.cs' },
-		{ startIndex: 6, type: 'string.quote.cs' },
-		{ startIndex: 7, type: 'delimiter.cs' }
-	]}],
-
-	[{
-	line: 'x = $@"verbatim {interpolated} string{{}}"" ";',
-	tokens: [
-		{ startIndex: 0, type: "identifier.cs" },
-		{ startIndex: 1, type: "" },
-		{ startIndex: 2, type: "delimiter.cs" },
-		{ startIndex: 3, type: "" },
-		{ startIndex: 4, type: "string.quote.cs" },
-		{ startIndex: 7, type: "string.cs" },
-		{ startIndex: 16, type: "string.quote.cs" },
-		{ startIndex: 17, type: "identifier.cs" },
-		{ startIndex: 29, type: "string.quote.cs" },
-		{ startIndex: 30, type: "string.cs" },
-		{ startIndex: 37, type: "string.escape.cs" },
-		{ startIndex: 39, type: "string.cs" },
-		{ startIndex: 41, type: "string.escape.cs" },
-		{ startIndex: 43, type: "string.cs" },
-		{ startIndex: 44, type: "string.quote.cs" },
-		{ startIndex: 45, type: "delimiter.cs" },
-	]}],
+		line: 'x = @"verbatimstring";',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.cs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'string.quote.cs' },
+			{ startIndex: 6, type: 'string.cs' },
+			{ startIndex: 20, type: 'string.quote.cs' },
+			{ startIndex: 21, type: 'delimiter.cs' }
+		]
+	}],
+
+	[{
+		line: 'x = @"verbatim""string";',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.cs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'string.quote.cs' },
+			{ startIndex: 6, type: 'string.cs' },
+			{ startIndex: 14, type: 'string.escape.cs' },
+			{ startIndex: 16, type: 'string.cs' },
+			{ startIndex: 22, type: 'string.quote.cs' },
+			{ startIndex: 23, type: 'delimiter.cs' }
+		]
+	}],
+
+	[{
+		line: 'x = @"verbatim\\string\\";',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.cs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'string.quote.cs' },
+			{ startIndex: 6, type: 'string.cs' },
+			{ startIndex: 22, type: 'string.quote.cs' },
+			{ startIndex: 23, type: 'delimiter.cs' }
+		]
+	}],
+
+	[{
+		line: 'x = @"verbatim',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.cs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.cs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'string.quote.cs' },
+			{ startIndex: 6, type: 'string.cs' }
+		]
+	}, {
+		line: 'string";',
+		tokens: [
+			{ startIndex: 0, type: 'string.cs' },
+			{ startIndex: 6, type: 'string.quote.cs' },
+			{ startIndex: 7, type: 'delimiter.cs' }
+		]
+	}],
+
+	[{
+		line: 'x = $@"verbatim {interpolated} string{{}}"" ";',
+		tokens: [
+			{ startIndex: 0, type: "identifier.cs" },
+			{ startIndex: 1, type: "" },
+			{ startIndex: 2, type: "delimiter.cs" },
+			{ startIndex: 3, type: "" },
+			{ startIndex: 4, type: "string.quote.cs" },
+			{ startIndex: 7, type: "string.cs" },
+			{ startIndex: 16, type: "string.quote.cs" },
+			{ startIndex: 17, type: "identifier.cs" },
+			{ startIndex: 29, type: "string.quote.cs" },
+			{ startIndex: 30, type: "string.cs" },
+			{ startIndex: 37, type: "string.escape.cs" },
+			{ startIndex: 39, type: "string.cs" },
+			{ startIndex: 41, type: "string.escape.cs" },
+			{ startIndex: 43, type: "string.cs" },
+			{ startIndex: 44, type: "string.quote.cs" },
+			{ startIndex: 45, type: "delimiter.cs" },
+		]
+	}],
 ]);

+ 410 - 366
test/css.test.ts

@@ -4,16 +4,17 @@
  *--------------------------------------------------------------------------------------------*/
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('css', [
 	// Skip whitespace
 	[{
-	line: '      body',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'tag.css' }
-	]}],
+		line: '      body',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'tag.css' }
+		]
+	}],
 
 	// CSS rule
 	//	body {
@@ -24,242 +25,265 @@ testTokenization('css', [
 	//	  color: #000
 	//	}
 	[{
-	line: 'body {',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'delimiter.bracket.css' }
-	]}, {
-	line: '  margin: 0;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'attribute.name.css' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'attribute.value.number.css' },
-		{ startIndex: 11, type: 'delimiter.css' }
-	]}, {
-	line: '  padding: 3em 6em;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'attribute.name.css' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'attribute.value.number.css' },
-		{ startIndex: 12, type: 'attribute.value.unit.css' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'attribute.value.number.css' },
-		{ startIndex: 16, type: 'attribute.value.unit.css' },
-		{ startIndex: 18, type: 'delimiter.css' }
-	]}, {
-	line: '  font-family: tahoma, arial, sans-serif;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'attribute.name.css' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'attribute.value.css' },
-		{ startIndex: 21, type: 'delimiter.css' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'attribute.value.css' },
-		{ startIndex: 28, type: 'delimiter.css' },
-		{ startIndex: 29, type: '' },
-		{ startIndex: 30, type: 'attribute.value.css' },
-		{ startIndex: 40, type: 'delimiter.css' }
-	]}, {
-	line: '  text-decoration: none !important;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'attribute.name.css' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'attribute.value.css' },
-		{ startIndex: 23, type: '' },
-		{ startIndex: 24, type: 'keyword.css' },
-		{ startIndex: 34, type: 'delimiter.css' }
-	]}, {
-	line: '  color: #000',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'attribute.name.css' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'attribute.value.hex.css' }
-	]}, {
-	line: '  }',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.bracket.css' }
-	]}],
+		line: 'body {',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'delimiter.bracket.css' }
+		]
+	}, {
+		line: '  margin: 0;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'attribute.name.css' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'attribute.value.number.css' },
+			{ startIndex: 11, type: 'delimiter.css' }
+		]
+	}, {
+		line: '  padding: 3em 6em;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'attribute.name.css' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'attribute.value.number.css' },
+			{ startIndex: 12, type: 'attribute.value.unit.css' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'attribute.value.number.css' },
+			{ startIndex: 16, type: 'attribute.value.unit.css' },
+			{ startIndex: 18, type: 'delimiter.css' }
+		]
+	}, {
+		line: '  font-family: tahoma, arial, sans-serif;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'attribute.name.css' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'attribute.value.css' },
+			{ startIndex: 21, type: 'delimiter.css' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'attribute.value.css' },
+			{ startIndex: 28, type: 'delimiter.css' },
+			{ startIndex: 29, type: '' },
+			{ startIndex: 30, type: 'attribute.value.css' },
+			{ startIndex: 40, type: 'delimiter.css' }
+		]
+	}, {
+		line: '  text-decoration: none !important;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'attribute.name.css' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'attribute.value.css' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'keyword.css' },
+			{ startIndex: 34, type: 'delimiter.css' }
+		]
+	}, {
+		line: '  color: #000',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'attribute.name.css' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'attribute.value.hex.css' }
+		]
+	}, {
+		line: '  }',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.bracket.css' }
+		]
+	}],
 
 	// CSS units and numbers
 	[{
-	line: '* { padding: 3em -9pt -0.5px; }',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.bracket.css' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'attribute.name.css' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'attribute.value.number.css' },
-		{ startIndex: 14, type: 'attribute.value.unit.css' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'attribute.value.number.css' },
-		{ startIndex: 19, type: 'attribute.value.unit.css' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'attribute.value.number.css' },
-		{ startIndex: 26, type: 'attribute.value.unit.css' },
-		{ startIndex: 28, type: 'delimiter.css' },
-		{ startIndex: 29, type: '' },
-		{ startIndex: 30, type: 'delimiter.bracket.css' }
-	]}],
+		line: '* { padding: 3em -9pt -0.5px; }',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.bracket.css' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'attribute.name.css' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'attribute.value.number.css' },
+			{ startIndex: 14, type: 'attribute.value.unit.css' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'attribute.value.number.css' },
+			{ startIndex: 19, type: 'attribute.value.unit.css' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'attribute.value.number.css' },
+			{ startIndex: 26, type: 'attribute.value.unit.css' },
+			{ startIndex: 28, type: 'delimiter.css' },
+			{ startIndex: 29, type: '' },
+			{ startIndex: 30, type: 'delimiter.bracket.css' }
+		]
+	}],
 
 	// CSS unfinished unit and numbers
 	[{
-	line: '* { padding: -',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.bracket.css' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'attribute.name.css' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'delimiter.css' }
-	]}],
+		line: '* { padding: -',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.bracket.css' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'attribute.name.css' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'delimiter.css' }
+		]
+	}],
 
 	// CSS single line comment
 	//	h1 /*comment*/ p  {
 	[{
-	line: 'h1 /*comment*/ p {',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'comment.css' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'tag.css' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'delimiter.bracket.css' }
-	]}],
+		line: 'h1 /*comment*/ p {',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'comment.css' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'tag.css' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'delimiter.bracket.css' }
+		]
+	}],
 
 	// CSS multi line comment
 	//	h1 /*com
 	//  ment*/ p  {
 	[{
-	line: 'h1 /*com',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'comment.css' }
-	]}, {
-	line: 'ment*/ p',
-	tokens: [
-		{ startIndex: 0, type: 'comment.css' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'tag.css' }
-	]}],
+		line: 'h1 /*com',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'comment.css' }
+		]
+	}, {
+		line: 'ment*/ p',
+		tokens: [
+			{ startIndex: 0, type: 'comment.css' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'tag.css' }
+		]
+	}],
 
 	// CSS ID rule
 	[{
-	line: '#myID {',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.bracket.css' }
-	]}],
+		line: '#myID {',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.bracket.css' }
+		]
+	}],
 
 	// CSS Class rules
 	[{
-	line: '.myID {',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.bracket.css' }
-	]}],
+		line: '.myID {',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.bracket.css' }
+		]
+	}],
 
 	// CSS @import etc
 	[{
-	line: '@import url(\"something.css\");',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.css' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'attribute.value.css' },
-		{ startIndex: 11, type: 'delimiter.parenthesis.css' },
-		{ startIndex: 12, type: 'string.css' },
-		{ startIndex: 27, type: 'delimiter.parenthesis.css' },
-		{ startIndex: 28, type: 'delimiter.css' }
-	]}],
+		line: '@import url(\"something.css\");',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.css' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'attribute.value.css' },
+			{ startIndex: 11, type: 'delimiter.parenthesis.css' },
+			{ startIndex: 12, type: 'string.css' },
+			{ startIndex: 27, type: 'delimiter.parenthesis.css' },
+			{ startIndex: 28, type: 'delimiter.css' }
+		]
+	}],
 
 	// CSS multi-line string with an escaped newline
 	//	body {
 	//	content: 'con\
 	//  tent';
 	[{
-	line: 'body {',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'delimiter.bracket.css' },
-	]}, {
-	line: '  content: \"con\\',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'attribute.name.css' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'string.css' }
-	]}, {
-	line: 'tent\";',
-	tokens: [
-		{ startIndex: 0, type: 'string.css' },
-		{ startIndex: 5, type: 'delimiter.css' }
-	]}],
+		line: 'body {',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'delimiter.bracket.css' },
+		]
+	}, {
+		line: '  content: \"con\\',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'attribute.name.css' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'string.css' }
+		]
+	}, {
+		line: 'tent\";',
+		tokens: [
+			{ startIndex: 0, type: 'string.css' },
+			{ startIndex: 5, type: 'delimiter.css' }
+		]
+	}],
 
 	// CSS empty string value
 	//	body {
 	//	content: '';
 	[{
-	line: 'body {',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'delimiter.bracket.css' },
-	]}, {
-	line: '  content: \"\";',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'attribute.name.css' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'string.css' },
-		{ startIndex: 13, type: 'delimiter.css' }
-	]}],
+		line: 'body {',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'delimiter.bracket.css' },
+		]
+	}, {
+		line: '  content: \"\";',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'attribute.name.css' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'string.css' },
+			{ startIndex: 13, type: 'delimiter.css' }
+		]
+	}],
 
 	// CSS font face
 	// @font-face {
 	//     font-family: 'Opificio';
 	// }
 	[{
-	line: '@font-face {',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.css' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'delimiter.bracket.css' }
-	]}, {
-	line: '  font-family: "Opificio";',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'attribute.name.css' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'string.css' },
-		{ startIndex: 25, type: 'delimiter.css' }
-	]}],
+		line: '@font-face {',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.css' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'delimiter.bracket.css' }
+		]
+	}, {
+		line: '  font-family: "Opificio";',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'attribute.name.css' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'string.css' },
+			{ startIndex: 25, type: 'delimiter.css' }
+		]
+	}],
 
 	// CSS string with escaped quotes
 	//	's\"tr'
 	[{
-	line: '\"s\\\"tr\" ',
-	tokens: [
-		{ startIndex: 0, type: 'string.css' },
-		{ startIndex: 7, type: '' }
-	]}],
+		line: '\"s\\\"tr\" ',
+		tokens: [
+			{ startIndex: 0, type: 'string.css' },
+			{ startIndex: 7, type: '' }
+		]
+	}],
 
 	// CSS key frame animation syntax
 	//@-webkit-keyframes infinite-spinning {
- 	//	 from {
+	//	 from {
 	//		-webkit-transform: rotate(0deg);
 	//	}
 	//	to {
@@ -267,210 +291,230 @@ testTokenization('css', [
 	//	}
 	//}
 	[{
-	line: '@-webkit-keyframes infinite-spinning {',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.css' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'attribute.value.css' },
-		{ startIndex: 36, type: '' },
-		{ startIndex: 37, type: 'delimiter.bracket.css' }
-	]}, {
-	line: '  from {',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'attribute.value.css' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'delimiter.bracket.css' }
-	]}, {
-	line: '  -webkit-transform: rotate(0deg);',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'attribute.name.css' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'attribute.value.css' },
-		{ startIndex: 28, type: 'attribute.value.number.css' },
-		{ startIndex: 29, type: 'attribute.value.unit.css' },
-		{ startIndex: 32, type: 'attribute.value.css' },
-		{ startIndex: 33, type: 'delimiter.css' }
-	]}, {
-	line: '	 }',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.bracket.css' }
-	]}, {
-	line: '  to {',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'attribute.value.css' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'delimiter.bracket.css' }
-	]}, {
-	line: '  -webkit-transform: rotate(360deg);',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'attribute.name.css' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'attribute.value.css' },
-		{ startIndex: 28, type: 'attribute.value.number.css' },
-		{ startIndex: 31, type: 'attribute.value.unit.css' },
-		{ startIndex: 34, type: 'attribute.value.css' },
-		{ startIndex: 35, type: 'delimiter.css' }
-	]}, {
-	line: '	 }',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.bracket.css' }
-	]}, {
-	line: '}',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.bracket.css' }
-	]}],
+		line: '@-webkit-keyframes infinite-spinning {',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.css' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'attribute.value.css' },
+			{ startIndex: 36, type: '' },
+			{ startIndex: 37, type: 'delimiter.bracket.css' }
+		]
+	}, {
+		line: '  from {',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'attribute.value.css' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'delimiter.bracket.css' }
+		]
+	}, {
+		line: '  -webkit-transform: rotate(0deg);',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'attribute.name.css' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'attribute.value.css' },
+			{ startIndex: 28, type: 'attribute.value.number.css' },
+			{ startIndex: 29, type: 'attribute.value.unit.css' },
+			{ startIndex: 32, type: 'attribute.value.css' },
+			{ startIndex: 33, type: 'delimiter.css' }
+		]
+	}, {
+		line: '	 }',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.bracket.css' }
+		]
+	}, {
+		line: '  to {',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'attribute.value.css' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'delimiter.bracket.css' }
+		]
+	}, {
+		line: '  -webkit-transform: rotate(360deg);',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'attribute.name.css' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'attribute.value.css' },
+			{ startIndex: 28, type: 'attribute.value.number.css' },
+			{ startIndex: 31, type: 'attribute.value.unit.css' },
+			{ startIndex: 34, type: 'attribute.value.css' },
+			{ startIndex: 35, type: 'delimiter.css' }
+		]
+	}, {
+		line: '	 }',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.bracket.css' }
+		]
+	}, {
+		line: '}',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.bracket.css' }
+		]
+	}],
 
 	// CSS @import related coloring bug 9553
 	//		 @import url('something.css');
 	//		.rule1{}
 	//		.rule2{}
 	[{
-	line: '@import url(\"something.css\");',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.css' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'attribute.value.css' },
-		{ startIndex: 11, type: 'delimiter.parenthesis.css' },
-		{ startIndex: 12, type: 'string.css' },
-		{ startIndex: 27, type: 'delimiter.parenthesis.css' },
-		{ startIndex: 28, type: 'delimiter.css' }
-	]}, {
-	line: '.rule1{}',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 6, type: 'delimiter.bracket.css' },
-	]}, {
-	line: '.rule2{}',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 6, type: 'delimiter.bracket.css' },
-	]}],
+		line: '@import url(\"something.css\");',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.css' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'attribute.value.css' },
+			{ startIndex: 11, type: 'delimiter.parenthesis.css' },
+			{ startIndex: 12, type: 'string.css' },
+			{ startIndex: 27, type: 'delimiter.parenthesis.css' },
+			{ startIndex: 28, type: 'delimiter.css' }
+		]
+	}, {
+		line: '.rule1{}',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 6, type: 'delimiter.bracket.css' },
+		]
+	}, {
+		line: '.rule2{}',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 6, type: 'delimiter.bracket.css' },
+		]
+	}],
 
 	// Triple quotes - bug #9870
 	[{
-	line: '"""',
-	tokens: [
-		{ startIndex: 0, type: 'string.css' }
-	]}],
+		line: '"""',
+		tokens: [
+			{ startIndex: 0, type: 'string.css' }
+		]
+	}],
 
 	[{
-	line: '""""',
-	tokens: [
-		{ startIndex: 0, type: 'string.css' }
-	]}],
+		line: '""""',
+		tokens: [
+			{ startIndex: 0, type: 'string.css' }
+		]
+	}],
 
 	[{
-	line: '"""""',
-	tokens: [
-		{ startIndex: 0, type: 'string.css' }
-	]}],
+		line: '"""""',
+		tokens: [
+			{ startIndex: 0, type: 'string.css' }
+		]
+	}],
 
 	// import statement - bug #10308
 	//	@import url('something.css');@import url('something.css');
 	[{
-	line: '@import url(\"something.css\");@import url(\"something.css\");',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.css' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'attribute.value.css' },
-		{ startIndex: 11, type: 'delimiter.parenthesis.css' },
-		{ startIndex: 12, type: 'string.css' },
-		{ startIndex: 27, type: 'delimiter.parenthesis.css' },
-		{ startIndex: 28, type: 'delimiter.css' },
-		{ startIndex: 29, type: 'keyword.css' },
-		{ startIndex: 36, type: '' },
-		{ startIndex: 37, type: 'attribute.value.css' },
-		{ startIndex: 40, type: 'delimiter.parenthesis.css' },
-		{ startIndex: 41, type: 'string.css' },
-		{ startIndex: 56, type: 'delimiter.parenthesis.css' },
-		{ startIndex: 57, type: 'delimiter.css' }
-	]}],
+		line: '@import url(\"something.css\");@import url(\"something.css\");',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.css' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'attribute.value.css' },
+			{ startIndex: 11, type: 'delimiter.parenthesis.css' },
+			{ startIndex: 12, type: 'string.css' },
+			{ startIndex: 27, type: 'delimiter.parenthesis.css' },
+			{ startIndex: 28, type: 'delimiter.css' },
+			{ startIndex: 29, type: 'keyword.css' },
+			{ startIndex: 36, type: '' },
+			{ startIndex: 37, type: 'attribute.value.css' },
+			{ startIndex: 40, type: 'delimiter.parenthesis.css' },
+			{ startIndex: 41, type: 'string.css' },
+			{ startIndex: 56, type: 'delimiter.parenthesis.css' },
+			{ startIndex: 57, type: 'delimiter.css' }
+		]
+	}],
 
 	// !important - bug #9578
 	// .a{background:#f5f9fc !important}.b{font-family:"Helvetica Neue", Helvetica;height:31px;}
 	[{
-	line: '.a{background:#f5f9fc !important}.b{font-family:"Helvetica Neue", Helvetica;height:31px;}',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 2, type: 'delimiter.bracket.css' },
-		{ startIndex: 3, type: 'attribute.name.css' },
-		{ startIndex: 14, type: 'attribute.value.hex.css' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'keyword.css' },
-		{ startIndex: 32, type: 'delimiter.bracket.css' },
-		{ startIndex: 33, type: 'tag.css' },
-		{ startIndex: 35, type: 'delimiter.bracket.css' },
-		{ startIndex: 36, type: 'attribute.name.css' },
-		{ startIndex: 48, type: 'string.css' },
-		{ startIndex: 64, type: 'delimiter.css' },
-		{ startIndex: 65, type: '' },
-		{ startIndex: 66, type: 'attribute.value.css' },
-		{ startIndex: 75, type: 'delimiter.css' },
-		{ startIndex: 76, type: 'attribute.name.css' },
-		{ startIndex: 83, type: 'attribute.value.number.css' },
-		{ startIndex: 85, type: 'attribute.value.unit.css' },
-		{ startIndex: 87, type: 'delimiter.css' },
-		{ startIndex: 88, type: 'delimiter.bracket.css' }
-	]}],
+		line: '.a{background:#f5f9fc !important}.b{font-family:"Helvetica Neue", Helvetica;height:31px;}',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 2, type: 'delimiter.bracket.css' },
+			{ startIndex: 3, type: 'attribute.name.css' },
+			{ startIndex: 14, type: 'attribute.value.hex.css' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'keyword.css' },
+			{ startIndex: 32, type: 'delimiter.bracket.css' },
+			{ startIndex: 33, type: 'tag.css' },
+			{ startIndex: 35, type: 'delimiter.bracket.css' },
+			{ startIndex: 36, type: 'attribute.name.css' },
+			{ startIndex: 48, type: 'string.css' },
+			{ startIndex: 64, type: 'delimiter.css' },
+			{ startIndex: 65, type: '' },
+			{ startIndex: 66, type: 'attribute.value.css' },
+			{ startIndex: 75, type: 'delimiter.css' },
+			{ startIndex: 76, type: 'attribute.name.css' },
+			{ startIndex: 83, type: 'attribute.value.number.css' },
+			{ startIndex: 85, type: 'attribute.value.unit.css' },
+			{ startIndex: 87, type: 'delimiter.css' },
+			{ startIndex: 88, type: 'delimiter.bracket.css' }
+		]
+	}],
 
 	// base64-encoded data uris - bug #9580
 	//.even { background: #fff url(data:image/gif;base64,R0lGODlhBgASALMAAOfn5+rq6uvr6+zs7O7u7vHx8fPz8/b29vj4+P39/f///wAAAAAAAAAAAAAAAAAAACwAAAAABgASAAAIMAAVCBxIsKDBgwgTDkzAsKGAhxARSJx4oKJFAxgzFtjIkYDHjwNCigxAsiSAkygDAgA7) repeat-x bottom}
 	[{
-	line: '.even { background: #fff url(data:image/gif;base64,R0lGODlhBgASALMAAOfn5+rq6uvr6+zs7O7u7vHx8fPz8/b29vj4+P39/f///wAAAAAAAAAAAAAAAAAAACwAAAAABgASAAAIMAAVCBxIsKDBgwgTDkzAsKGAhxARSJx4oKJFAxgzFtjIkYDHjwNCigxAsiSAkygDAgA7) repeat-x bottom}',
-	tokens: [
-		{startIndex: 0, type: 'tag.css'},
-		{startIndex: 5, type: ''},
-		{startIndex: 6, type: 'delimiter.bracket.css'},
-		{startIndex: 7, type: ''},
-		{startIndex: 8, type: 'attribute.name.css'},
-		{startIndex: 19, type: ''},
-		{startIndex: 20, type: 'attribute.value.hex.css'},
-		{startIndex: 24, type: ''},
-		{startIndex: 25, type: 'attribute.value.css'},
-		{startIndex: 28, type: 'delimiter.parenthesis.css'},
-		{startIndex: 29, type: 'string.css'},
-		{startIndex: 215, type: 'delimiter.parenthesis.css'},
-		{startIndex: 216, type: ''},
-		{startIndex: 217, type: 'attribute.value.css'},
-		{startIndex: 225, type: ''},
-		{startIndex: 226, type: 'attribute.value.css'},
-		{startIndex: 232, type: 'delimiter.bracket.css'}
-	]}],
+		line: '.even { background: #fff url(data:image/gif;base64,R0lGODlhBgASALMAAOfn5+rq6uvr6+zs7O7u7vHx8fPz8/b29vj4+P39/f///wAAAAAAAAAAAAAAAAAAACwAAAAABgASAAAIMAAVCBxIsKDBgwgTDkzAsKGAhxARSJx4oKJFAxgzFtjIkYDHjwNCigxAsiSAkygDAgA7) repeat-x bottom}',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.bracket.css' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'attribute.name.css' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'attribute.value.hex.css' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'attribute.value.css' },
+			{ startIndex: 28, type: 'delimiter.parenthesis.css' },
+			{ startIndex: 29, type: 'string.css' },
+			{ startIndex: 215, type: 'delimiter.parenthesis.css' },
+			{ startIndex: 216, type: '' },
+			{ startIndex: 217, type: 'attribute.value.css' },
+			{ startIndex: 225, type: '' },
+			{ startIndex: 226, type: 'attribute.value.css' },
+			{ startIndex: 232, type: 'delimiter.bracket.css' }
+		]
+	}],
 
 	// /a colorization is incorrect in url - bug #9581
 	//.a{background:url(/a.jpg)}
 	[{
-	line: '.a{background:url(/a.jpg)}',
-	tokens: [
-		{startIndex: 0, type: 'tag.css'},
-		{startIndex: 2, type: 'delimiter.bracket.css'},
-		{startIndex: 3, type: 'attribute.name.css'},
-		{startIndex: 14, type: 'attribute.value.css'},
-		{startIndex: 17, type: 'delimiter.parenthesis.css'},
-		{startIndex: 18, type: 'string.css'},
-		{startIndex: 24, type: 'delimiter.parenthesis.css'},
-		{startIndex: 25, type: 'delimiter.bracket.css'}
-	]}],
+		line: '.a{background:url(/a.jpg)}',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 2, type: 'delimiter.bracket.css' },
+			{ startIndex: 3, type: 'attribute.name.css' },
+			{ startIndex: 14, type: 'attribute.value.css' },
+			{ startIndex: 17, type: 'delimiter.parenthesis.css' },
+			{ startIndex: 18, type: 'string.css' },
+			{ startIndex: 24, type: 'delimiter.parenthesis.css' },
+			{ startIndex: 25, type: 'delimiter.bracket.css' }
+		]
+	}],
 
 	// Bracket Matching
 	[{
-	line: 'p{}',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 1, type: 'delimiter.bracket.css' },
-	]}],
+		line: 'p{}',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 1, type: 'delimiter.bracket.css' },
+		]
+	}],
 
 	[{
-	line: 'p:nth() {}',
-	tokens: [
-		{ startIndex: 0, type: 'tag.css' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 8, type: 'delimiter.bracket.css' }
-	]}],
+		line: 'p:nth() {}',
+		tokens: [
+			{ startIndex: 0, type: 'tag.css' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 8, type: 'delimiter.bracket.css' }
+		]
+	}],
 ]);

+ 203 - 171
test/dockerfile.test.ts

@@ -5,185 +5,217 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('dockerfile', [
 	// All
 	[{
-	line: 'FROM mono:3.12',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dockerfile' },
-		{ startIndex: 4, type: '' }
-	]}, {
-	line: '',
-	tokens: [
+		line: 'FROM mono:3.12',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dockerfile' },
+			{ startIndex: 4, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
 
-	]}, {
-	line: 'ENV KRE_FEED https://www.myget.org/F/aspnetvnext/api/v2',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dockerfile' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'variable.dockerfile' },
-		{ startIndex: 12, type: '' }
-	]}, {
-	line: 'ENV KRE_USER_HOME /opt/kre',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dockerfile' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'variable.dockerfile' },
-		{ startIndex: 17, type: '' }
-	]}, {
-	line: '',
-	tokens: [
+		]
+	}, {
+		line: 'ENV KRE_FEED https://www.myget.org/F/aspnetvnext/api/v2',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dockerfile' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'variable.dockerfile' },
+			{ startIndex: 12, type: '' }
+		]
+	}, {
+		line: 'ENV KRE_USER_HOME /opt/kre',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dockerfile' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'variable.dockerfile' },
+			{ startIndex: 17, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
 
-	]}, {
-	line: 'RUN apt-get -qq update && apt-get -qqy install unzip ',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dockerfile' },
-		{ startIndex: 3, type: '' }
-	]}, {
-	line: '',
-	tokens: [
+		]
+	}, {
+		line: 'RUN apt-get -qq update && apt-get -qqy install unzip ',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dockerfile' },
+			{ startIndex: 3, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
 
-	]}, {
-	line: 'ONBUILD RUN curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/kvminstall.sh | sh',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dockerfile' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'keyword.dockerfile' },
-		{ startIndex: 11, type: '' }
-	]}, {
-	line: 'ONBUILD RUN bash -c "source $KRE_USER_HOME/kvm/kvm.sh \\',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dockerfile' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'keyword.dockerfile' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 20, type: 'string.dockerfile' },
-		{ startIndex: 28, type: 'variable.dockerfile' },
-		{ startIndex: 42, type: 'string.dockerfile' }
-	]}, {
-	line: '    && kvm install latest -a default \\',
-	tokens: [
-		{ startIndex: 0, type: 'string.dockerfile' }
-	]}, {
-	line: '    && kvm alias default | xargs -i ln -s $KRE_USER_HOME/packages/{} $KRE_USER_HOME/packages/default"',
-	tokens: [
-		{ startIndex: 0, type: 'string.dockerfile' },
-		{ startIndex: 42, type: 'variable.dockerfile' },
-		{ startIndex: 56, type: 'string.dockerfile' },
-		{ startIndex: 69, type: 'variable.dockerfile' },
-		{ startIndex: 83, type: 'string.dockerfile' }
-	]}, {
-	line: '',
-	tokens: [
+		]
+	}, {
+		line: 'ONBUILD RUN curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/kvminstall.sh | sh',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dockerfile' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'keyword.dockerfile' },
+			{ startIndex: 11, type: '' }
+		]
+	}, {
+		line: 'ONBUILD RUN bash -c "source $KRE_USER_HOME/kvm/kvm.sh \\',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dockerfile' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'keyword.dockerfile' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 20, type: 'string.dockerfile' },
+			{ startIndex: 28, type: 'variable.dockerfile' },
+			{ startIndex: 42, type: 'string.dockerfile' }
+		]
+	}, {
+		line: '    && kvm install latest -a default \\',
+		tokens: [
+			{ startIndex: 0, type: 'string.dockerfile' }
+		]
+	}, {
+		line: '    && kvm alias default | xargs -i ln -s $KRE_USER_HOME/packages/{} $KRE_USER_HOME/packages/default"',
+		tokens: [
+			{ startIndex: 0, type: 'string.dockerfile' },
+			{ startIndex: 42, type: 'variable.dockerfile' },
+			{ startIndex: 56, type: 'string.dockerfile' },
+			{ startIndex: 69, type: 'variable.dockerfile' },
+			{ startIndex: 83, type: 'string.dockerfile' }
+		]
+	}, {
+		line: '',
+		tokens: [
 
-	]}, {
-	line: '# Install libuv for Kestrel from source code (binary is not in wheezy and one in jessie is still too old)',
-	tokens: [
-		{ startIndex: 0, type: 'comment.dockerfile' }
-	]}, {
-	line: 'RUN apt-get -qqy install \\',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dockerfile' },
-		{ startIndex: 3, type: '' }
-	]}, {
-	line: '    autoconf \\',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '    automake \\',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '    build-essential \\',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '    libtool ',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: 'RUN LIBUV_VERSION=1.0.0-rc2 \\',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dockerfile' },
-		{ startIndex: 3, type: '' }
-	]}, {
-	line: '    && curl -sSL https://github.com/joyent/libuv/archive/v${LIBUV_VERSION}.tar.gz | tar zxfv - -C /usr/local/src \\',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 58, type: 'variable.dockerfile' },
-		{ startIndex: 74, type: '' }
-	]}, {
-	line: '    && cd /usr/local/src/libuv-$LIBUV_VERSION \\',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 31, type: 'variable.dockerfile' },
-		{ startIndex: 45, type: '' }
-	]}, {
-	line: '    && sh autogen.sh && ./configure && make && make install \\',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '    && rm -rf /usr/local/src/libuv-$LIBUV_VERSION \\',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 35, type: 'variable.dockerfile' },
-		{ startIndex: 49, type: '' }
-	]}, {
-	line: '    && ldconfig',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '',
-	tokens: [
+		]
+	}, {
+		line: '# Install libuv for Kestrel from source code (binary is not in wheezy and one in jessie is still too old)',
+		tokens: [
+			{ startIndex: 0, type: 'comment.dockerfile' }
+		]
+	}, {
+		line: 'RUN apt-get -qqy install \\',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dockerfile' },
+			{ startIndex: 3, type: '' }
+		]
+	}, {
+		line: '    autoconf \\',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '    automake \\',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '    build-essential \\',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '    libtool ',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: 'RUN LIBUV_VERSION=1.0.0-rc2 \\',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dockerfile' },
+			{ startIndex: 3, type: '' }
+		]
+	}, {
+		line: '    && curl -sSL https://github.com/joyent/libuv/archive/v${LIBUV_VERSION}.tar.gz | tar zxfv - -C /usr/local/src \\',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 58, type: 'variable.dockerfile' },
+			{ startIndex: 74, type: '' }
+		]
+	}, {
+		line: '    && cd /usr/local/src/libuv-$LIBUV_VERSION \\',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 31, type: 'variable.dockerfile' },
+			{ startIndex: 45, type: '' }
+		]
+	}, {
+		line: '    && sh autogen.sh && ./configure && make && make install \\',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '    && rm -rf /usr/local/src/libuv-$LIBUV_VERSION \\',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 35, type: 'variable.dockerfile' },
+			{ startIndex: 49, type: '' }
+		]
+	}, {
+		line: '    && ldconfig',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
 
-	]}, {
-	line: 'ENV PATH $PATH:$KRE_USER_HOME/packages/default/bin',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dockerfile' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'variable.dockerfile' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'variable.dockerfile' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'variable.dockerfile' },
-		{ startIndex: 29, type: '' }
-	]}, {
-	line: '',
-	tokens: [
+		]
+	}, {
+		line: 'ENV PATH $PATH:$KRE_USER_HOME/packages/default/bin',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dockerfile' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'variable.dockerfile' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'variable.dockerfile' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'variable.dockerfile' },
+			{ startIndex: 29, type: '' }
+		]
+	}, {
+		line: '',
+		tokens: [
 
-	]}, {
-	line: '# Extra things to test',
-	tokens: [
-		{ startIndex: 0, type: 'comment.dockerfile' }
-	]}, {
-	line: 'RUN echo "string at end"',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dockerfile' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 9, type: 'string.dockerfile' }
-	]}, {
-	line: 'RUN echo must work \'some str\' and some more',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dockerfile' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 19, type: 'string.dockerfile' },
-		{ startIndex: 29, type: '' }
-	]}, {
-	line: 'RUN echo hi this is # not a comment',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dockerfile' },
-		{ startIndex: 3, type: '' }
-	]}, {
-	line: 'RUN echo \'String with ${VAR} and another $one here\'',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dockerfile' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 9, type: 'string.dockerfile' },
-		{ startIndex: 22, type: 'variable.dockerfile' },
-		{ startIndex: 28, type: 'string.dockerfile' },
-		{ startIndex: 41, type: 'variable.dockerfile' },
-		{ startIndex: 45, type: 'string.dockerfile' }
-	]}]
+		]
+	}, {
+		line: '# Extra things to test',
+		tokens: [
+			{ startIndex: 0, type: 'comment.dockerfile' }
+		]
+	}, {
+		line: 'RUN echo "string at end"',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dockerfile' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 9, type: 'string.dockerfile' }
+		]
+	}, {
+		line: 'RUN echo must work \'some str\' and some more',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dockerfile' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 19, type: 'string.dockerfile' },
+			{ startIndex: 29, type: '' }
+		]
+	}, {
+		line: 'RUN echo hi this is # not a comment',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dockerfile' },
+			{ startIndex: 3, type: '' }
+		]
+	}, {
+		line: 'RUN echo \'String with ${VAR} and another $one here\'',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dockerfile' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 9, type: 'string.dockerfile' },
+			{ startIndex: 22, type: 'variable.dockerfile' },
+			{ startIndex: 28, type: 'string.dockerfile' },
+			{ startIndex: 41, type: 'variable.dockerfile' },
+			{ startIndex: 45, type: 'string.dockerfile' }
+		]
+	}]
 ]);

+ 355 - 303
test/fsharp.test.ts

@@ -5,388 +5,440 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('fsharp', [
 	// comments - single line
 	[{
-	line: '// one line comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.fs' }
-	]}],
-
-	[{
-	line: '//',
-	tokens: [
-		{ startIndex: 0, type: 'comment.fs' }
-	]}],
-
-	[{
-	line: '    // a comment',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'comment.fs' }
-	]}],
-
-	[{
-	line: '// a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.fs' }
-	]}],
-
-	[{
-	line: '//sticky comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.fs' }
-	]}],
-
-	[{
-	line: '/almost a comment',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.fs' },
-		{ startIndex: 1, type: 'identifier.fs' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.fs' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'identifier.fs' }
-	]}],
-
-	[{
-	line: '(/*almost a comment',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.parenthesis.fs' },
-		{ startIndex: 1, type: 'delimiter.fs' },
-		{ startIndex: 3, type: 'identifier.fs' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'identifier.fs' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'identifier.fs' }
-	]}],
-
-	[{
-	line: '1 / 2; (* comment',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.fs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.fs' },
-		{ startIndex: 5, type: 'delimiter.fs' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'comment.fs' }
-	]}],
-
-	[{
-	line: 'let x = 1; // my comment // is a nice one',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.let.fs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.fs' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.fs' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.fs' },
-		{ startIndex: 9, type: 'delimiter.fs' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'comment.fs' }
-	]}],
+		line: '// one line comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.fs' }
+		]
+	}],
+
+	[{
+		line: '//',
+		tokens: [
+			{ startIndex: 0, type: 'comment.fs' }
+		]
+	}],
+
+	[{
+		line: '    // a comment',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'comment.fs' }
+		]
+	}],
+
+	[{
+		line: '// a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.fs' }
+		]
+	}],
+
+	[{
+		line: '//sticky comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.fs' }
+		]
+	}],
+
+	[{
+		line: '/almost a comment',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.fs' },
+			{ startIndex: 1, type: 'identifier.fs' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.fs' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.fs' }
+		]
+	}],
+
+	[{
+		line: '(/*almost a comment',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.parenthesis.fs' },
+			{ startIndex: 1, type: 'delimiter.fs' },
+			{ startIndex: 3, type: 'identifier.fs' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.fs' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'identifier.fs' }
+		]
+	}],
+
+	[{
+		line: '1 / 2; (* comment',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.fs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.fs' },
+			{ startIndex: 5, type: 'delimiter.fs' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'comment.fs' }
+		]
+	}],
+
+	[{
+		line: 'let x = 1; // my comment // is a nice one',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.let.fs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.fs' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.fs' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.fs' },
+			{ startIndex: 9, type: 'delimiter.fs' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'comment.fs' }
+		]
+	}],
 
 	// Keywords
 	[{
-	line: 'namespace Application1',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.namespace.fs' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'identifier.fs' }
-	]}],
-
-	[{
-	line: 'type MyType',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.type.fs' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'identifier.fs' }
-	]}],
-
-	[{
-	line: 'module App =',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.module.fs' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.fs' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'delimiter.fs' }
-	]}],
-
-	[{
-	line: 'let AppName = "App1"',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.let.fs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.fs' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'delimiter.fs' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'string.fs' }
-	]}],
+		line: 'namespace Application1',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.namespace.fs' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.fs' }
+		]
+	}],
+
+	[{
+		line: 'type MyType',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.type.fs' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'identifier.fs' }
+		]
+	}],
+
+	[{
+		line: 'module App =',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.module.fs' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.fs' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'delimiter.fs' }
+		]
+	}],
+
+	[{
+		line: 'let AppName = "App1"',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.let.fs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.fs' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'delimiter.fs' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'string.fs' }
+		]
+	}],
 
 	// Comments - range comment
 	[{
-	line: '(* a simple comment *)',
-	tokens: [
-		{ startIndex: 0, type: 'comment.fs' }
-	]}],
-
-	[{
-	line: 'let x = (* a simple comment *) 1',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.let.fs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.fs' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.fs' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.fs' },
-		{ startIndex: 30, type: '' },
-		{ startIndex: 31, type: 'number.fs' }
-	]}],
-
-	[{
-	line: 'x = (**)',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.fs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.fs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.fs' }
-	]}],
-
-	[{
-	line: 'x = (*)',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.fs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.fs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.fs' }
-	]}],
+		line: '(* a simple comment *)',
+		tokens: [
+			{ startIndex: 0, type: 'comment.fs' }
+		]
+	}],
+
+	[{
+		line: 'let x = (* a simple comment *) 1',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.let.fs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.fs' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.fs' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.fs' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'number.fs' }
+		]
+	}],
+
+	[{
+		line: 'x = (**)',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.fs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.fs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.fs' }
+		]
+	}],
+
+	[{
+		line: 'x = (*)',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.fs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.fs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.fs' }
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '0',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' }
-	]}],
+		line: '0',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '0x123',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.fs' }
-	]}],
+		line: '0x123',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.fs' }
+		]
+	}],
 
 	[{
-	line: '23.5',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '23.5',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '23.5e3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '23.5e3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '23.5E3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '23.5E3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '23.5F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '23.5F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '23.5f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '23.5f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '1.72E3F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '1.72E3F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '1.72E3f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '1.72E3f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '1.72e3F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '1.72e3F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '1.72e3f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '1.72e3f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '23.5M',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '23.5M',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '23.5m',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '23.5m',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '1.72E3M',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '1.72E3M',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '1.72E3m',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '1.72E3m',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '1.72e3M',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '1.72e3M',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '1.72e3m',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}],
+		line: '1.72e3m',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}],
 
 	[{
-	line: '0+0',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' },
-		{ startIndex: 1, type: 'delimiter.fs' },
-		{ startIndex: 2, type: 'number.fs' }
-	]}],
+		line: '0+0',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' },
+			{ startIndex: 1, type: 'delimiter.fs' },
+			{ startIndex: 2, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '100+10',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' },
-		{ startIndex: 3, type: 'delimiter.fs' },
-		{ startIndex: 4, type: 'number.fs' }
-	]}],
+		line: '100+10',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' },
+			{ startIndex: 3, type: 'delimiter.fs' },
+			{ startIndex: 4, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '0 + 0',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.fs' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.fs' }
-	]}],
+		line: '0 + 0',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.fs' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '0b00000101',
-	tokens: [
-		{ startIndex: 0, type: 'number.bin.fs' }
-	]}],
+		line: '0b00000101',
+		tokens: [
+			{ startIndex: 0, type: 'number.bin.fs' }
+		]
+	}],
 
 	[{
-	line: '86y',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' }
-	]}],
+		line: '86y',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '0b00000101y',
-	tokens: [
-		{ startIndex: 0, type: 'number.bin.fs' }
-	]}],
+		line: '0b00000101y',
+		tokens: [
+			{ startIndex: 0, type: 'number.bin.fs' }
+		]
+	}],
 
 	[{
-	line: '86s',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' }
-	]}],
+		line: '86s',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '86us',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' }
-	]}],
+		line: '86us',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '86',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' }
-	]}],
+		line: '86',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '86l',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' }
-	]}],
+		line: '86l',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '86u',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' }
-	]}],
+		line: '86u',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '86ul',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' }
-	]}],
+		line: '86ul',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '0x00002D3Fn',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.fs' }
-	]}],
+		line: '0x00002D3Fn',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.fs' }
+		]
+	}],
 
 	[{
-	line: '0x00002D3Fun',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.fs' }
-	]}],
+		line: '0x00002D3Fun',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.fs' }
+		]
+	}],
 
 	[{
-	line: '86L',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' }
-	]}],
+		line: '86L',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '86UL',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' }
-	]}],
+		line: '86UL',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '9999999999999999999999999999I',
-	tokens: [
-		{ startIndex: 0, type: 'number.fs' }
-	]}],
+		line: '9999999999999999999999999999I',
+		tokens: [
+			{ startIndex: 0, type: 'number.fs' }
+		]
+	}],
 
 	[{
-	line: '0x00002D3FLF',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.fs' }
-	]}]
+		line: '0x00002D3FLF',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.fs' }
+		]
+	}]
 ]);

+ 1267 - 1148
test/go.test.ts

@@ -5,1169 +5,1288 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('go', [
 	// Tests
 	[{
-	line: '/* Block comment. */',
-	tokens: [
-		{ startIndex: 0, type: 'comment.go' }
-	]}],
+		line: '/* Block comment. */',
+		tokens: [
+			{ startIndex: 0, type: 'comment.go' }
+		]
+	}],
 
 	[{
-	line: '/* //*/ a',
-	tokens: [
-		{ startIndex: 0, type: 'comment.go' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.go' }
-	]}],
+		line: '/* //*/ a',
+		tokens: [
+			{ startIndex: 0, type: 'comment.go' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.go' }
+		]
+	}],
 
 	[{
-	line: '// Inline comment.',
-	tokens: [
-		{ startIndex: 0, type: 'comment.go' }
-	]}],
+		line: '// Inline comment.',
+		tokens: [
+			{ startIndex: 0, type: 'comment.go' }
+		]
+	}],
 
 	[{
-	line: '',
-	tokens: [
+		line: '',
+		tokens: [
 
-	]}],
+		]
+	}],
 
 	[{
-	line: 'import {',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.import.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'delimiter.curly.go' }
-	]}],
+		line: 'import {',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.import.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'delimiter.curly.go' }
+		]
+	}],
 
-	[{
-	line: '  "io"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'string.go' }
-	]}],
-
-	[{
-	line: '}',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.go' }
-	]}],
-
-	[{
-	line: '',
-	tokens: [
-
-	]}],
-
-	[{
-	line: 'type name struct {',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.type.go' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'identifier.go' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'keyword.struct.go' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'delimiter.curly.go' }
-	]}],
-
-	[{
-	line: '  firstname string',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'keyword.string.go' }
-	]}],
-
-	[{
-	line: '  lastname string',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'keyword.string.go' }
-	]}],
-
-	[{
-	line: '}',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.go' }
-	]}],
+	[{
+		line: '  "io"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'string.go' }
+		]
+	}],
 
-	[{
-	line: '',
-	tokens: [
-
-	]}],
-
-	[{
-	line: 'func testTypes() {',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.func.go' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'identifier.go' },
-		{ startIndex: 14, type: 'delimiter.parenthesis.go' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'delimiter.curly.go' }
-	]}],
+	[{
+		line: '}',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.go' }
+		]
+	}],
 
 	[{
-	line: '  a int;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.int.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  b uint;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.uint.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  c uintptr;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.uintptr.go' },
-		{ startIndex: 11, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  d string;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.string.go' },
-		{ startIndex: 10, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  e byte;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.byte.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  f rune;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.rune.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  g uint8;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.uint8.go' },
-		{ startIndex: 9, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  h uint16;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.uint16.go' },
-		{ startIndex: 10, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  i uint32;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.uint32.go' },
-		{ startIndex: 10, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  j uint64;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.uint64.go' },
-		{ startIndex: 10, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  k int8;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.int8.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  l int16;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.int16.go' },
-		{ startIndex: 9, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  m int32;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.int32.go' },
-		{ startIndex: 9, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  n int64;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.int64.go' },
-		{ startIndex: 9, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  o float32;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.float32.go' },
-		{ startIndex: 11, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  p float64;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.float64.go' },
-		{ startIndex: 11, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  q complex64;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.complex64.go' },
-		{ startIndex: 13, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  r complex128;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'keyword.complex128.go' },
-		{ startIndex: 14, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '}',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.go' }
-	]}],
-
-	[{
-	line: '',
-	tokens: [
-
-	]}],
-
-	[{
-	line: 'func testOperators() {',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.func.go' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'identifier.go' },
-		{ startIndex: 18, type: 'delimiter.parenthesis.go' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'delimiter.curly.go' }
-	]}],
-
-	[{
-	line: '  ',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}],
-
-	[{
-	line: '  var a;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.var.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  var b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.var.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  ',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}],
-
-	[{
-	line: '  a + b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a - b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a * b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a / b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a % b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a & b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a | b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a ^ b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a << b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a >> b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a &^ b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a += b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a -= b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a *= b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a /= b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a %= b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a &= b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a |= b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a ^= b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a <<= b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.go' },
-		{ startIndex: 9, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a >>= b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.go' },
-		{ startIndex: 9, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a &^= b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.go' },
-		{ startIndex: 9, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a && b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a || b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a <- b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a++;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  b--;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a == b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a < b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.angle.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a > b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.angle.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a = b; ',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' },
-		{ startIndex: 8, type: '' }
-	]}],
-
-	[{
-	line: '  !a;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.go' },
-		{ startIndex: 3, type: 'identifier.go' },
-		{ startIndex: 4, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a != b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a <= b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a >= b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a := b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a...;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  (a)',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.parenthesis.go' },
-		{ startIndex: 3, type: 'identifier.go' },
-		{ startIndex: 4, type: 'delimiter.parenthesis.go' }
-	]}],
-
-	[{
-	line: '  [a]',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.square.go' },
-		{ startIndex: 3, type: 'identifier.go' },
-		{ startIndex: 4, type: 'delimiter.square.go' }
-	]}],
-
-	[{
-	line: '  a.b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: 'delimiter.go' },
-		{ startIndex: 4, type: 'identifier.go' },
-		{ startIndex: 5, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a, b;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: 'delimiter.go' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'identifier.go' },
-		{ startIndex: 6, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  a : b; ',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'identifier.go' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' },
-		{ startIndex: 8, type: '' }
-	]}],
-
-	[{
-	line: '}',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.go' }
-	]}],
-
-	[{
-	line: '',
-	tokens: [
-
-	]}],
-
-	[{
-	line: 'func keywords() {',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.func.go' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'identifier.go' },
-		{ startIndex: 13, type: 'delimiter.parenthesis.go' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'delimiter.curly.go' }
-	]}],
-
-	[{
-	line: '  ',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}],
-
-	[{
-	line: '  var a;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.var.go' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  break;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.break.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  switch(a) {',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.switch.go' },
-		{ startIndex: 8, type: 'delimiter.parenthesis.go' },
-		{ startIndex: 9, type: 'identifier.go' },
-		{ startIndex: 10, type: 'delimiter.parenthesis.go' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'delimiter.curly.go' }
-	]}],
-
-	[{
-	line: '    case 1:',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.case.go' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'number.go' },
-		{ startIndex: 10, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '      fallthrough;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'keyword.fallthrough.go' },
-		{ startIndex: 17, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '    default:',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.default.go' },
-		{ startIndex: 11, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '      break;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'keyword.break.go' },
-		{ startIndex: 11, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  }',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.curly.go' }
-	]}],
-
-	[{
-	line: '  ',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}],
-
-	[{
-	line: '  chan;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.chan.go' },
-		{ startIndex: 6, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  const;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.const.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  continue;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.continue.go' },
-		{ startIndex: 10, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  defer;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.defer.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  if (a)',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.if.go' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'delimiter.parenthesis.go' },
-		{ startIndex: 6, type: 'identifier.go' },
-		{ startIndex: 7, type: 'delimiter.parenthesis.go' }
-	]}],
-
-	[{
-	line: '    return;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.return.go' },
-		{ startIndex: 10, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '  else',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.else.go' }
-	]}],
-
-	[{
-	line: '    return;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.return.go' },
-		{ startIndex: 10, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   for (i = 0; i < 10; i++);',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.for.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'delimiter.parenthesis.go' },
-		{ startIndex: 8, type: 'identifier.go' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'delimiter.go' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'number.go' },
-		{ startIndex: 13, type: 'delimiter.go' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'identifier.go' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'delimiter.angle.go' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'number.go' },
-		{ startIndex: 21, type: 'delimiter.go' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'identifier.go' },
-		{ startIndex: 24, type: 'delimiter.go' },
-		{ startIndex: 26, type: 'delimiter.parenthesis.go' },
-		{ startIndex: 27, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   go;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.go.go' },
-		{ startIndex: 5, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   goto;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.goto.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   interface;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.interface.go' },
-		{ startIndex: 12, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   map;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.map.go' },
-		{ startIndex: 6, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   package;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.package.go' },
-		{ startIndex: 10, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   range;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.range.go' },
-		{ startIndex: 8, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   return;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.return.go' },
-		{ startIndex: 9, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   select;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.select.go' },
-		{ startIndex: 9, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   struct;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.struct.go' },
-		{ startIndex: 9, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   type;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.type.go' },
-		{ startIndex: 7, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   ',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}],
-
-	[{
-	line: '   var x = true;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.var.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'delimiter.go' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'keyword.true.go' },
-		{ startIndex: 15, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   var y = false;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.var.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'delimiter.go' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'keyword.false.go' },
-		{ startIndex: 16, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '   var z = nil;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.var.go' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.go' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'delimiter.go' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'keyword.nil.go' },
-		{ startIndex: 14, type: 'delimiter.go' }
-	]}],
-
-	[{
-	line: '}',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.go' }
-	]}],
-
-	[{
-	line: '`Hello world() ""`',
-	tokens: [
-		{ startIndex: 0, type: 'string.go' }
-	]}]
+		line: '',
+		tokens: [
+
+		]
+	}],
+
+	[{
+		line: 'type name struct {',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.type.go' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'identifier.go' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'keyword.struct.go' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'delimiter.curly.go' }
+		]
+	}],
+
+	[{
+		line: '  firstname string',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'keyword.string.go' }
+		]
+	}],
+
+	[{
+		line: '  lastname string',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'keyword.string.go' }
+		]
+	}],
+
+	[{
+		line: '}',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.go' }
+		]
+	}],
+
+	[{
+		line: '',
+		tokens: [
+
+		]
+	}],
+
+	[{
+		line: 'func testTypes() {',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.func.go' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'identifier.go' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.go' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'delimiter.curly.go' }
+		]
+	}],
+
+	[{
+		line: '  a int;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.int.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  b uint;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.uint.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  c uintptr;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.uintptr.go' },
+			{ startIndex: 11, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  d string;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.string.go' },
+			{ startIndex: 10, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  e byte;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.byte.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  f rune;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.rune.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  g uint8;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.uint8.go' },
+			{ startIndex: 9, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  h uint16;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.uint16.go' },
+			{ startIndex: 10, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  i uint32;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.uint32.go' },
+			{ startIndex: 10, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  j uint64;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.uint64.go' },
+			{ startIndex: 10, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  k int8;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.int8.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  l int16;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.int16.go' },
+			{ startIndex: 9, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  m int32;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.int32.go' },
+			{ startIndex: 9, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  n int64;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.int64.go' },
+			{ startIndex: 9, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  o float32;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.float32.go' },
+			{ startIndex: 11, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  p float64;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.float64.go' },
+			{ startIndex: 11, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  q complex64;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.complex64.go' },
+			{ startIndex: 13, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  r complex128;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'keyword.complex128.go' },
+			{ startIndex: 14, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '}',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.go' }
+		]
+	}],
+
+	[{
+		line: '',
+		tokens: [
+
+		]
+	}],
+
+	[{
+		line: 'func testOperators() {',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.func.go' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'identifier.go' },
+			{ startIndex: 18, type: 'delimiter.parenthesis.go' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'delimiter.curly.go' }
+		]
+	}],
+
+	[{
+		line: '  ',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}],
+
+	[{
+		line: '  var a;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.var.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  var b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.var.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  ',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}],
+
+	[{
+		line: '  a + b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a - b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a * b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a / b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a % b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a & b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a | b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a ^ b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a << b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a >> b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a &^ b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a += b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a -= b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a *= b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a /= b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a %= b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a &= b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a |= b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a ^= b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a <<= b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.go' },
+			{ startIndex: 9, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a >>= b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.go' },
+			{ startIndex: 9, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a &^= b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.go' },
+			{ startIndex: 9, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a && b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a || b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a <- b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a++;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  b--;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a == b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a < b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.angle.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a > b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.angle.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a = b; ',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' },
+			{ startIndex: 8, type: '' }
+		]
+	}],
+
+	[{
+		line: '  !a;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.go' },
+			{ startIndex: 3, type: 'identifier.go' },
+			{ startIndex: 4, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a != b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a <= b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a >= b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a := b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a...;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  (a)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.parenthesis.go' },
+			{ startIndex: 3, type: 'identifier.go' },
+			{ startIndex: 4, type: 'delimiter.parenthesis.go' }
+		]
+	}],
+
+	[{
+		line: '  [a]',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.square.go' },
+			{ startIndex: 3, type: 'identifier.go' },
+			{ startIndex: 4, type: 'delimiter.square.go' }
+		]
+	}],
+
+	[{
+		line: '  a.b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: 'delimiter.go' },
+			{ startIndex: 4, type: 'identifier.go' },
+			{ startIndex: 5, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a, b;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: 'delimiter.go' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'identifier.go' },
+			{ startIndex: 6, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  a : b; ',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.go' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' },
+			{ startIndex: 8, type: '' }
+		]
+	}],
+
+	[{
+		line: '}',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.go' }
+		]
+	}],
+
+	[{
+		line: '',
+		tokens: [
+
+		]
+	}],
+
+	[{
+		line: 'func keywords() {',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.func.go' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'identifier.go' },
+			{ startIndex: 13, type: 'delimiter.parenthesis.go' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'delimiter.curly.go' }
+		]
+	}],
+
+	[{
+		line: '  ',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}],
+
+	[{
+		line: '  var a;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.var.go' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  break;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.break.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  switch(a) {',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.switch.go' },
+			{ startIndex: 8, type: 'delimiter.parenthesis.go' },
+			{ startIndex: 9, type: 'identifier.go' },
+			{ startIndex: 10, type: 'delimiter.parenthesis.go' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'delimiter.curly.go' }
+		]
+	}],
+
+	[{
+		line: '    case 1:',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.case.go' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'number.go' },
+			{ startIndex: 10, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '      fallthrough;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'keyword.fallthrough.go' },
+			{ startIndex: 17, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '    default:',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.default.go' },
+			{ startIndex: 11, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '      break;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'keyword.break.go' },
+			{ startIndex: 11, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  }',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.curly.go' }
+		]
+	}],
+
+	[{
+		line: '  ',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}],
+
+	[{
+		line: '  chan;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.chan.go' },
+			{ startIndex: 6, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  const;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.const.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  continue;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.continue.go' },
+			{ startIndex: 10, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  defer;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.defer.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  if (a)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.if.go' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'delimiter.parenthesis.go' },
+			{ startIndex: 6, type: 'identifier.go' },
+			{ startIndex: 7, type: 'delimiter.parenthesis.go' }
+		]
+	}],
+
+	[{
+		line: '    return;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.return.go' },
+			{ startIndex: 10, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '  else',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.else.go' }
+		]
+	}],
+
+	[{
+		line: '    return;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.return.go' },
+			{ startIndex: 10, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   for (i = 0; i < 10; i++);',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.for.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'delimiter.parenthesis.go' },
+			{ startIndex: 8, type: 'identifier.go' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'delimiter.go' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'number.go' },
+			{ startIndex: 13, type: 'delimiter.go' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'identifier.go' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'delimiter.angle.go' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'number.go' },
+			{ startIndex: 21, type: 'delimiter.go' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'identifier.go' },
+			{ startIndex: 24, type: 'delimiter.go' },
+			{ startIndex: 26, type: 'delimiter.parenthesis.go' },
+			{ startIndex: 27, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   go;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.go.go' },
+			{ startIndex: 5, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   goto;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.goto.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   interface;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.interface.go' },
+			{ startIndex: 12, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   map;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.map.go' },
+			{ startIndex: 6, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   package;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.package.go' },
+			{ startIndex: 10, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   range;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.range.go' },
+			{ startIndex: 8, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   return;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.return.go' },
+			{ startIndex: 9, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   select;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.select.go' },
+			{ startIndex: 9, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   struct;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.struct.go' },
+			{ startIndex: 9, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   type;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.type.go' },
+			{ startIndex: 7, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   ',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}],
+
+	[{
+		line: '   var x = true;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.var.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.go' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'keyword.true.go' },
+			{ startIndex: 15, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   var y = false;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.var.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.go' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'keyword.false.go' },
+			{ startIndex: 16, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '   var z = nil;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.var.go' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.go' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.go' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'keyword.nil.go' },
+			{ startIndex: 14, type: 'delimiter.go' }
+		]
+	}],
+
+	[{
+		line: '}',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.go' }
+		]
+	}],
+
+	[{
+		line: '`Hello world() ""`',
+		tokens: [
+			{ startIndex: 0, type: 'string.go' }
+		]
+	}]
 ]);

+ 152 - 152
test/handlebars.test.ts

@@ -5,8 +5,8 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
-import {htmlTokenTypes} from '../src/handlebars';
+import { testTokenization } from './testRunner';
+import { htmlTokenTypes } from '../src/handlebars';
 
 const HTML_DELIM_START = htmlTokenTypes.DELIM_START;
 const HTML_DELIM_END = htmlTokenTypes.DELIM_END;
@@ -30,13 +30,13 @@ testTokenization(['handlebars', 'css'], [
 	[{
 		line: '<h1>handlebars!</h1>',
 		tokens: [
-			{ startIndex:0, type: HTML_DELIM_START },
-			{ startIndex:1, type: getTag('h1') },
-			{ startIndex:3, type: HTML_DELIM_END },
-			{ startIndex:4, type: '' },
-			{ startIndex:15, type: HTML_DELIM_START },
-			{ startIndex:17, type: getTag('h1') },
-			{ startIndex:19, type: HTML_DELIM_END }
+			{ startIndex: 0, type: HTML_DELIM_START },
+			{ startIndex: 1, type: getTag('h1') },
+			{ startIndex: 3, type: HTML_DELIM_END },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 15, type: HTML_DELIM_START },
+			{ startIndex: 17, type: getTag('h1') },
+			{ startIndex: 19, type: HTML_DELIM_END }
 		]
 	}],
 
@@ -44,17 +44,17 @@ testTokenization(['handlebars', 'css'], [
 	[{
 		line: '<h1>{{ title }}</h1>',
 		tokens: [
-			{ startIndex:0, type: HTML_DELIM_START },
-			{ startIndex:1, type: getTag('h1') },
-			{ startIndex:3, type: HTML_DELIM_END },
-			{ startIndex:4, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:6, type: '' },
-			{ startIndex:7, type: handlebarsTokenTypes.VARIABLE },
-			{ startIndex:12, type: '' },
-			{ startIndex:13, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:15, type: HTML_DELIM_START },
-			{ startIndex:17, type: getTag('h1') },
-			{ startIndex:19, type: HTML_DELIM_END }
+			{ startIndex: 0, type: HTML_DELIM_START },
+			{ startIndex: 1, type: getTag('h1') },
+			{ startIndex: 3, type: HTML_DELIM_END },
+			{ startIndex: 4, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: handlebarsTokenTypes.VARIABLE },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 15, type: HTML_DELIM_START },
+			{ startIndex: 17, type: getTag('h1') },
+			{ startIndex: 19, type: HTML_DELIM_END }
 		]
 	}],
 
@@ -62,15 +62,15 @@ testTokenization(['handlebars', 'css'], [
 	[{
 		line: '<h1>{{title}}</h1>',
 		tokens: [
-			{ startIndex:0, type: HTML_DELIM_START },
-			{ startIndex:1, type: getTag('h1') },
-			{ startIndex:3, type: HTML_DELIM_END },
-			{ startIndex:4, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:6, type: handlebarsTokenTypes.VARIABLE },
-			{ startIndex:11, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:13, type: HTML_DELIM_START },
-			{ startIndex:15, type: getTag('h1') },
-			{ startIndex:17, type: HTML_DELIM_END }
+			{ startIndex: 0, type: HTML_DELIM_START },
+			{ startIndex: 1, type: getTag('h1') },
+			{ startIndex: 3, type: HTML_DELIM_END },
+			{ startIndex: 4, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 6, type: handlebarsTokenTypes.VARIABLE },
+			{ startIndex: 11, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 13, type: HTML_DELIM_START },
+			{ startIndex: 15, type: getTag('h1') },
+			{ startIndex: 17, type: HTML_DELIM_END }
 		]
 	}],
 
@@ -78,17 +78,17 @@ testTokenization(['handlebars', 'css'], [
 	[{
 		line: '<h1>{{{ title }}}</h1>',
 		tokens: [
-			{ startIndex:0, type: HTML_DELIM_START },
-			{ startIndex:1, type: getTag('h1') },
-			{ startIndex:3, type: HTML_DELIM_END },
-			{ startIndex:4, type: handlebarsTokenTypes.EMBED_UNESCAPED },
-			{ startIndex:7, type: '' },
-			{ startIndex:8, type: handlebarsTokenTypes.VARIABLE },
-			{ startIndex:13, type: '' },
-			{ startIndex:14, type: handlebarsTokenTypes.EMBED_UNESCAPED },
-			{ startIndex:17, type: HTML_DELIM_START },
-			{ startIndex:19, type: getTag('h1') },
-			{ startIndex:21, type: HTML_DELIM_END }
+			{ startIndex: 0, type: HTML_DELIM_START },
+			{ startIndex: 1, type: getTag('h1') },
+			{ startIndex: 3, type: HTML_DELIM_END },
+			{ startIndex: 4, type: handlebarsTokenTypes.EMBED_UNESCAPED },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: handlebarsTokenTypes.VARIABLE },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: handlebarsTokenTypes.EMBED_UNESCAPED },
+			{ startIndex: 17, type: HTML_DELIM_START },
+			{ startIndex: 19, type: getTag('h1') },
+			{ startIndex: 21, type: HTML_DELIM_END }
 		]
 	}],
 
@@ -96,29 +96,29 @@ testTokenization(['handlebars', 'css'], [
 	[{
 		line: '<ul>{{#each items}}<li>{{item}}</li>{{/each}}</ul>',
 		tokens: [
-			{ startIndex:0, type: HTML_DELIM_START },
-			{ startIndex:1, type: getTag('ul') },
-			{ startIndex:3, type: HTML_DELIM_END },
-			{ startIndex:4, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:6, type: handlebarsTokenTypes.KEYWORD },
-			{ startIndex:11, type: '' },
-			{ startIndex:12, type: handlebarsTokenTypes.VARIABLE },
-			{ startIndex:17, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:19, type: HTML_DELIM_START },
-			{ startIndex:20, type: getTag('li') },
-			{ startIndex:22, type: HTML_DELIM_END },
-			{ startIndex:23, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:25, type: handlebarsTokenTypes.VARIABLE },
-			{ startIndex:29, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:31, type: HTML_DELIM_START },
-			{ startIndex:33, type: getTag('li') },
-			{ startIndex:35, type: HTML_DELIM_END },
-			{ startIndex:36, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:38, type: handlebarsTokenTypes.KEYWORD },
-			{ startIndex:43, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:45, type: HTML_DELIM_START },
-			{ startIndex:47, type: getTag('ul') },
-			{ startIndex:49, type: HTML_DELIM_END }
+			{ startIndex: 0, type: HTML_DELIM_START },
+			{ startIndex: 1, type: getTag('ul') },
+			{ startIndex: 3, type: HTML_DELIM_END },
+			{ startIndex: 4, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 6, type: handlebarsTokenTypes.KEYWORD },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: handlebarsTokenTypes.VARIABLE },
+			{ startIndex: 17, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 19, type: HTML_DELIM_START },
+			{ startIndex: 20, type: getTag('li') },
+			{ startIndex: 22, type: HTML_DELIM_END },
+			{ startIndex: 23, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 25, type: handlebarsTokenTypes.VARIABLE },
+			{ startIndex: 29, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 31, type: HTML_DELIM_START },
+			{ startIndex: 33, type: getTag('li') },
+			{ startIndex: 35, type: HTML_DELIM_END },
+			{ startIndex: 36, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 38, type: handlebarsTokenTypes.KEYWORD },
+			{ startIndex: 43, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 45, type: HTML_DELIM_START },
+			{ startIndex: 47, type: getTag('ul') },
+			{ startIndex: 49, type: HTML_DELIM_END }
 		]
 	}],
 
@@ -126,38 +126,38 @@ testTokenization(['handlebars', 'css'], [
 	[{
 		line: '<div>',
 		tokens: [
-			{ startIndex:0, type: HTML_DELIM_START },
-			{ startIndex:1, type: getTag('div') },
-			{ startIndex:4, type: HTML_DELIM_END }
+			{ startIndex: 0, type: HTML_DELIM_START },
+			{ startIndex: 1, type: getTag('div') },
+			{ startIndex: 4, type: HTML_DELIM_END }
 		]
 	}, {
 		line: '{{#if foo}}',
 		tokens: [
-			{ startIndex:0, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:2, type: handlebarsTokenTypes.KEYWORD },
-			{ startIndex:5, type: '' },
-			{ startIndex:6, type: handlebarsTokenTypes.VARIABLE },
-			{ startIndex:9, type: handlebarsTokenTypes.EMBED }
+			{ startIndex: 0, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 2, type: handlebarsTokenTypes.KEYWORD },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: handlebarsTokenTypes.VARIABLE },
+			{ startIndex: 9, type: handlebarsTokenTypes.EMBED }
 		]
 	}, {
 		line: '<span>{{bar}}</span>',
 		tokens: [
-			{ startIndex:0, type: HTML_DELIM_START },
-			{ startIndex:1, type: getTag('span') },
-			{ startIndex:5, type: HTML_DELIM_END },
-			{ startIndex:6, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:8, type: handlebarsTokenTypes.VARIABLE },
-			{ startIndex:11, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:13, type: HTML_DELIM_START },
-			{ startIndex:15, type: getTag('span') },
-			{ startIndex:19, type: HTML_DELIM_END }
+			{ startIndex: 0, type: HTML_DELIM_START },
+			{ startIndex: 1, type: getTag('span') },
+			{ startIndex: 5, type: HTML_DELIM_END },
+			{ startIndex: 6, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 8, type: handlebarsTokenTypes.VARIABLE },
+			{ startIndex: 11, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 13, type: HTML_DELIM_START },
+			{ startIndex: 15, type: getTag('span') },
+			{ startIndex: 19, type: HTML_DELIM_END }
 		]
 	}, {
 		line: '{{/if}}',
 		tokens: [
-			{ startIndex:0, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:2, type: handlebarsTokenTypes.KEYWORD },
-			{ startIndex:5, type: handlebarsTokenTypes.EMBED }
+			{ startIndex: 0, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 2, type: handlebarsTokenTypes.KEYWORD },
+			{ startIndex: 5, type: handlebarsTokenTypes.EMBED }
 		]
 	}],
 
@@ -165,9 +165,9 @@ testTokenization(['handlebars', 'css'], [
 	[{
 		line: '</div>',
 		tokens: [
-			{ startIndex:0, type: HTML_DELIM_START },
-			{ startIndex:2, type: getTag('div') },
-			{ startIndex:5, type: HTML_DELIM_END }
+			{ startIndex: 0, type: HTML_DELIM_START },
+			{ startIndex: 2, type: getTag('div') },
+			{ startIndex: 5, type: HTML_DELIM_END }
 		]
 	}],
 
@@ -175,27 +175,27 @@ testTokenization(['handlebars', 'css'], [
 	[{
 		line: '<script type="text/x-handlebars-template"><h1>{{ title }}</h1></script>',
 		tokens: [
-			{ startIndex:0, type: HTML_DELIM_START },
-			{ startIndex:1, type: getTag('script') },
-			{ startIndex:7, type: '' },
-			{ startIndex:8, type: HTML_ATTRIB_NAME },
-			{ startIndex:12, type: DELIM_ASSIGN },
-			{ startIndex:13, type: HTML_ATTRIB_VALUE },
-			{ startIndex:41, type: HTML_DELIM_END },
-			{ startIndex:42, type: HTML_DELIM_START },
-			{ startIndex:43, type: getTag('h1') },
-			{ startIndex:45, type: HTML_DELIM_END },
-			{ startIndex:46, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:48, type: '' },
-			{ startIndex:49, type: handlebarsTokenTypes.VARIABLE },
-			{ startIndex:54, type: '' },
-			{ startIndex:55, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:57, type: HTML_DELIM_START },
-			{ startIndex:59, type: getTag('h1') },
-			{ startIndex:61, type: HTML_DELIM_END },
-			{ startIndex:62, type: HTML_DELIM_START },
-			{ startIndex:64, type: getTag('script') },
-			{ startIndex:70, type: HTML_DELIM_END }
+			{ startIndex: 0, type: HTML_DELIM_START },
+			{ startIndex: 1, type: getTag('script') },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: HTML_ATTRIB_NAME },
+			{ startIndex: 12, type: DELIM_ASSIGN },
+			{ startIndex: 13, type: HTML_ATTRIB_VALUE },
+			{ startIndex: 41, type: HTML_DELIM_END },
+			{ startIndex: 42, type: HTML_DELIM_START },
+			{ startIndex: 43, type: getTag('h1') },
+			{ startIndex: 45, type: HTML_DELIM_END },
+			{ startIndex: 46, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 48, type: '' },
+			{ startIndex: 49, type: handlebarsTokenTypes.VARIABLE },
+			{ startIndex: 54, type: '' },
+			{ startIndex: 55, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 57, type: HTML_DELIM_START },
+			{ startIndex: 59, type: getTag('h1') },
+			{ startIndex: 61, type: HTML_DELIM_END },
+			{ startIndex: 62, type: HTML_DELIM_START },
+			{ startIndex: 64, type: getTag('script') },
+			{ startIndex: 70, type: HTML_DELIM_END }
 		]
 	}],
 
@@ -203,35 +203,35 @@ testTokenization(['handlebars', 'css'], [
 	[{
 		line: '<script type="text/x-handlebars-template">',
 		tokens: [
-			{ startIndex:0, type: HTML_DELIM_START },
-			{ startIndex:1, type: getTag('script') },
-			{ startIndex:7, type: '' },
-			{ startIndex:8, type: HTML_ATTRIB_NAME },
-			{ startIndex:12, type: DELIM_ASSIGN },
-			{ startIndex:13, type: HTML_ATTRIB_VALUE },
-			{ startIndex:41, type: HTML_DELIM_END }
+			{ startIndex: 0, type: HTML_DELIM_START },
+			{ startIndex: 1, type: getTag('script') },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: HTML_ATTRIB_NAME },
+			{ startIndex: 12, type: DELIM_ASSIGN },
+			{ startIndex: 13, type: HTML_ATTRIB_VALUE },
+			{ startIndex: 41, type: HTML_DELIM_END }
 		]
 	}, {
 		line: '<h1>{{ title }}</h1>',
 		tokens: [
-			{ startIndex:0, type: HTML_DELIM_START },
-			{ startIndex:1, type: getTag('h1') },
-			{ startIndex:3, type: HTML_DELIM_END },
-			{ startIndex:4, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:6, type: '' },
-			{ startIndex:7, type: handlebarsTokenTypes.VARIABLE },
-			{ startIndex:12, type: '' },
-			{ startIndex:13, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:15, type: HTML_DELIM_START },
-			{ startIndex:17, type: getTag('h1') },
-			{ startIndex:19, type: HTML_DELIM_END }
+			{ startIndex: 0, type: HTML_DELIM_START },
+			{ startIndex: 1, type: getTag('h1') },
+			{ startIndex: 3, type: HTML_DELIM_END },
+			{ startIndex: 4, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: handlebarsTokenTypes.VARIABLE },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 15, type: HTML_DELIM_START },
+			{ startIndex: 17, type: getTag('h1') },
+			{ startIndex: 19, type: HTML_DELIM_END }
 		]
 	}, {
 		line: '</script>',
 		tokens: [
-			{ startIndex:0, type: HTML_DELIM_START },
-			{ startIndex:2, type: getTag('script') },
-			{ startIndex:8, type: HTML_DELIM_END }
+			{ startIndex: 0, type: HTML_DELIM_START },
+			{ startIndex: 2, type: getTag('script') },
+			{ startIndex: 8, type: HTML_DELIM_END }
 		]
 	}],
 
@@ -239,18 +239,18 @@ testTokenization(['handlebars', 'css'], [
 	[{
 		line: '{{foo}}<script></script>{{bar}}',
 		tokens: [
-			{ startIndex:0, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:2, type: handlebarsTokenTypes.VARIABLE },
-			{ startIndex:5, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:7, type: HTML_DELIM_START },
-			{ startIndex:8, type: getTag('script') },
-			{ startIndex:14, type: HTML_DELIM_END },
+			{ startIndex: 0, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 2, type: handlebarsTokenTypes.VARIABLE },
+			{ startIndex: 5, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 7, type: HTML_DELIM_START },
+			{ startIndex: 8, type: getTag('script') },
+			{ startIndex: 14, type: HTML_DELIM_END },
 			// { startIndex:15, type: HTML_DELIM_START },
-			{ startIndex:17, type: getTag('script') },
-			{ startIndex:23, type: HTML_DELIM_END },
-			{ startIndex:24, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:26, type: handlebarsTokenTypes.VARIABLE },
-			{ startIndex:29, type: handlebarsTokenTypes.EMBED }
+			{ startIndex: 17, type: getTag('script') },
+			{ startIndex: 23, type: HTML_DELIM_END },
+			{ startIndex: 24, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 26, type: handlebarsTokenTypes.VARIABLE },
+			{ startIndex: 29, type: handlebarsTokenTypes.EMBED }
 		]
 	}],
 
@@ -258,9 +258,9 @@ testTokenization(['handlebars', 'css'], [
 	[{
 		line: '{{else}}',
 		tokens: [
-			{ startIndex:0, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:2, type: handlebarsTokenTypes.KEYWORD },
-			{ startIndex:6, type: handlebarsTokenTypes.EMBED }
+			{ startIndex: 0, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 2, type: handlebarsTokenTypes.KEYWORD },
+			{ startIndex: 6, type: handlebarsTokenTypes.EMBED }
 		]
 	}],
 
@@ -268,9 +268,9 @@ testTokenization(['handlebars', 'css'], [
 	[{
 		line: '{{elseFoo}}',
 		tokens: [
-			{ startIndex:0, type: handlebarsTokenTypes.EMBED },
-			{ startIndex:2, type: handlebarsTokenTypes.VARIABLE },
-			{ startIndex:9, type: handlebarsTokenTypes.EMBED }
+			{ startIndex: 0, type: handlebarsTokenTypes.EMBED },
+			{ startIndex: 2, type: handlebarsTokenTypes.VARIABLE },
+			{ startIndex: 9, type: handlebarsTokenTypes.EMBED }
 		]
 	}],
 
@@ -278,13 +278,13 @@ testTokenization(['handlebars', 'css'], [
 	[{
 		line: '<a href="/posts/{{permalink}}">',
 		tokens: [
-			{ startIndex:0, type: HTML_DELIM_START },
-			{ startIndex:1, type: getTag('a') },
-			{ startIndex:2, type: '' },
-			{ startIndex:3, type: HTML_ATTRIB_NAME },
-			{ startIndex:7, type: DELIM_ASSIGN },
-			{ startIndex:8, type: HTML_ATTRIB_VALUE },
-			{ startIndex:30, type: HTML_DELIM_END }
+			{ startIndex: 0, type: HTML_DELIM_START },
+			{ startIndex: 1, type: getTag('a') },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: HTML_ATTRIB_NAME },
+			{ startIndex: 7, type: DELIM_ASSIGN },
+			{ startIndex: 8, type: HTML_ATTRIB_VALUE },
+			{ startIndex: 30, type: HTML_DELIM_END }
 		]
 	}]
 ]);

+ 275 - 275
test/html.test.ts

@@ -5,8 +5,8 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
-import {htmlTokenTypes} from '../src/html';
+import { testTokenization } from './testRunner';
+import { htmlTokenTypes } from '../src/html';
 
 const DELIM_START = htmlTokenTypes.DELIM_START + '.html';
 const DELIM_END = htmlTokenTypes.DELIM_END + '.html';
@@ -14,7 +14,7 @@ const ATTRIB_NAME = 'attribute.name.html';
 const DELIM_ASSIGN = 'delimiter.html';
 const ATTRIB_VALUE = 'attribute.value.html';
 
-function getTag(name:string): string {
+function getTag(name: string): string {
 	return htmlTokenTypes.getTag(name) + '.html';
 }
 
@@ -29,8 +29,8 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') }
 		]
 	}],
 
@@ -38,8 +38,8 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<input',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('input') }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('input') }
 		]
 	}],
 
@@ -47,8 +47,8 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '< abc',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: '' }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: '' }
 		]
 	}],
 
@@ -56,19 +56,19 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '< abc>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: '' }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: '' }
 		]
 	}],
 
 	// Open Start Tag #4
-		[{
+	[{
 		line: 'i <len;',
 		tokens: [
-			{ startIndex:0, type: '' },
-			{ startIndex:2, type: DELIM_START },
-			{ startIndex:3, type: getTag('len') },
-			{ startIndex:6, type: '' }
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: DELIM_START },
+			{ startIndex: 3, type: getTag('len') },
+			{ startIndex: 6, type: '' }
 		]
 	}],
 
@@ -76,7 +76,7 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<',
 		tokens: [
-			{ startIndex:0, type: DELIM_START }
+			{ startIndex: 0, type: DELIM_START }
 		]
 	}],
 
@@ -84,8 +84,8 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '</a',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:2, type: getTag('a') }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 2, type: getTag('a') }
 		]
 	}],
 
@@ -93,9 +93,9 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: DELIM_END }
 		]
 	}],
 
@@ -103,10 +103,10 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc >',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:5, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: DELIM_END }
 		]
 	}],
 
@@ -114,9 +114,9 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<foo:bar>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('foo-bar') },
-			{ startIndex:8, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('foo-bar') },
+			{ startIndex: 8, type: DELIM_END }
 		]
 	}],
 
@@ -124,9 +124,9 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '</abc>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:2, type: getTag('abc') },
-			{ startIndex:5, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 2, type: getTag('abc') },
+			{ startIndex: 5, type: DELIM_END }
 		]
 	}],
 
@@ -134,10 +134,10 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '</abc  >',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:2, type: getTag('abc') },
-			{ startIndex:5, type: '' },
-			{ startIndex:7, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 2, type: getTag('abc') },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 7, type: DELIM_END }
 		]
 	}],
 
@@ -145,10 +145,10 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc />',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:5, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: DELIM_END }
 		]
 	}],
 
@@ -156,17 +156,17 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<script type="text/javascript">var i= 10;</script>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('script') },
-			{ startIndex:7, type: '' },
-			{ startIndex:8, type: ATTRIB_NAME },
-			{ startIndex:12, type: DELIM_ASSIGN },
-			{ startIndex:13, type: ATTRIB_VALUE },
-			{ startIndex:30, type: DELIM_END },
-			{ startIndex:31, type: '' },
-			{ startIndex:41, type: DELIM_START },
-			{ startIndex:43, type: getTag('script') },
-			{ startIndex:49, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('script') },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: ATTRIB_NAME },
+			{ startIndex: 12, type: DELIM_ASSIGN },
+			{ startIndex: 13, type: ATTRIB_VALUE },
+			{ startIndex: 30, type: DELIM_END },
+			{ startIndex: 31, type: '' },
+			{ startIndex: 41, type: DELIM_START },
+			{ startIndex: 43, type: getTag('script') },
+			{ startIndex: 49, type: DELIM_END }
 		]
 	}],
 
@@ -174,25 +174,25 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<script type="text/javascript">',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('script') },
-			{ startIndex:7, type: '' },
-			{ startIndex:8, type: ATTRIB_NAME },
-			{ startIndex:12, type: DELIM_ASSIGN },
-			{ startIndex:13, type: ATTRIB_VALUE },
-			{ startIndex:30, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('script') },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: ATTRIB_NAME },
+			{ startIndex: 12, type: DELIM_ASSIGN },
+			{ startIndex: 13, type: ATTRIB_VALUE },
+			{ startIndex: 30, type: DELIM_END }
 		]
 	}, {
 		line: 'var i= 10;',
 		tokens: [
-			{ startIndex:0, type: '' },
+			{ startIndex: 0, type: '' },
 		]
 	}, {
 		line: '</script>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:2, type: getTag('script') },
-			{ startIndex:8, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 2, type: getTag('script') },
+			{ startIndex: 8, type: DELIM_END }
 		]
 	}],
 
@@ -200,21 +200,21 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<script type="text/javascript">var i= 10;',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('script') },
-			{ startIndex:7, type: '' },
-			{ startIndex:8, type: ATTRIB_NAME },
-			{ startIndex:12, type: DELIM_ASSIGN },
-			{ startIndex:13, type: ATTRIB_VALUE },
-			{ startIndex:30, type: DELIM_END },
-			{ startIndex:31, type: '' },
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('script') },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: ATTRIB_NAME },
+			{ startIndex: 12, type: DELIM_ASSIGN },
+			{ startIndex: 13, type: ATTRIB_VALUE },
+			{ startIndex: 30, type: DELIM_END },
+			{ startIndex: 31, type: '' },
 		]
 	}, {
 		line: '</script>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:2, type: getTag('script') },
-			{ startIndex:8, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 2, type: getTag('script') },
+			{ startIndex: 8, type: DELIM_END }
 		]
 	}],
 
@@ -222,21 +222,21 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<script type="text/javascript">',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('script') },
-			{ startIndex:7, type: '' },
-			{ startIndex:8, type: ATTRIB_NAME },
-			{ startIndex:12, type: DELIM_ASSIGN },
-			{ startIndex:13, type: ATTRIB_VALUE },
-			{ startIndex:30, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('script') },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: ATTRIB_NAME },
+			{ startIndex: 12, type: DELIM_ASSIGN },
+			{ startIndex: 13, type: ATTRIB_VALUE },
+			{ startIndex: 30, type: DELIM_END }
 		]
 	}, {
 		line: 'var i= 10;</script>',
 		tokens: [
-			{ startIndex:0, type: '' },
-			{ startIndex:10, type: DELIM_START },
-			{ startIndex:12, type: getTag('script') },
-			{ startIndex:18, type: DELIM_END }
+			{ startIndex: 0, type: '' },
+			{ startIndex: 10, type: DELIM_START },
+			{ startIndex: 12, type: getTag('script') },
+			{ startIndex: 18, type: DELIM_END }
 		]
 	}],
 
@@ -244,22 +244,22 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<script type="text/plain">a',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('script') },
-			{ startIndex:7, type: '' },
-			{ startIndex:8, type: ATTRIB_NAME },
-			{ startIndex:12, type: DELIM_ASSIGN },
-			{ startIndex:13, type: ATTRIB_VALUE },
-			{ startIndex:25, type: DELIM_END },
-			{ startIndex:26, type: '' },
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('script') },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: ATTRIB_NAME },
+			{ startIndex: 12, type: DELIM_ASSIGN },
+			{ startIndex: 13, type: ATTRIB_VALUE },
+			{ startIndex: 25, type: DELIM_END },
+			{ startIndex: 26, type: '' },
 		]
-	},{
+	}, {
 		line: '<a</script>',
 		tokens: [
-			{ startIndex:0, type: '' },
-			{ startIndex:2, type: DELIM_START },
-			{ startIndex:4, type: getTag('script') },
-			{ startIndex:10, type: DELIM_END }
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: DELIM_START },
+			{ startIndex: 4, type: getTag('script') },
+			{ startIndex: 10, type: DELIM_END }
 		]
 	}],
 
@@ -267,20 +267,20 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<script>a</script><script>b</script>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('script') },
-			{ startIndex:7, type: DELIM_END },
-			{ startIndex:8, type: '' },
-			{ startIndex:9, type: DELIM_START },
-			{ startIndex:11, type: getTag('script') },
-			{ startIndex:17, type: DELIM_END },
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('script') },
+			{ startIndex: 7, type: DELIM_END },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: DELIM_START },
+			{ startIndex: 11, type: getTag('script') },
+			{ startIndex: 17, type: DELIM_END },
 			// { startIndex:18, type: DELIM_START },
-			{ startIndex:19, type: getTag('script') },
-			{ startIndex:25, type: DELIM_END },
-			{ startIndex:26, type: '' },
-			{ startIndex:27, type: DELIM_START },
-			{ startIndex:29, type: getTag('script') },
-			{ startIndex:35, type: DELIM_END }
+			{ startIndex: 19, type: getTag('script') },
+			{ startIndex: 25, type: DELIM_END },
+			{ startIndex: 26, type: '' },
+			{ startIndex: 27, type: DELIM_START },
+			{ startIndex: 29, type: getTag('script') },
+			{ startIndex: 35, type: DELIM_END }
 		]
 	}],
 
@@ -288,16 +288,16 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<script type="text/javascript"></script>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('script') },
-			{ startIndex:7, type: '' },
-			{ startIndex:8, type: ATTRIB_NAME },
-			{ startIndex:12, type: DELIM_ASSIGN },
-			{ startIndex:13, type: ATTRIB_VALUE },
-			{ startIndex:30, type: DELIM_END },
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('script') },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: ATTRIB_NAME },
+			{ startIndex: 12, type: DELIM_ASSIGN },
+			{ startIndex: 13, type: ATTRIB_VALUE },
+			{ startIndex: 30, type: DELIM_END },
 			// { startIndex:31, type: DELIM_START },
-			{ startIndex:33, type: getTag('script') },
-			{ startIndex:39, type: DELIM_END }
+			{ startIndex: 33, type: getTag('script') },
+			{ startIndex: 39, type: DELIM_END }
 		]
 	}],
 
@@ -305,13 +305,13 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<script>var i= 10;</script>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('script') },
-			{ startIndex:7, type: DELIM_END },
-			{ startIndex:8, type: '' },
-			{ startIndex:18, type: DELIM_START },
-			{ startIndex:20, type: getTag('script') },
-			{ startIndex:26, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('script') },
+			{ startIndex: 7, type: DELIM_END },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 18, type: DELIM_START },
+			{ startIndex: 20, type: getTag('script') },
+			{ startIndex: 26, type: DELIM_END }
 		]
 	}],
 
@@ -319,20 +319,20 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<script type="text/javascript" src="main.js"></script>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('script') },
-			{ startIndex:7, type: '' },
-			{ startIndex:8, type: ATTRIB_NAME },
-			{ startIndex:12, type: DELIM_ASSIGN },
-			{ startIndex:13, type: ATTRIB_VALUE },
-			{ startIndex:30, type: '' },
-			{ startIndex:31, type: ATTRIB_NAME },
-			{ startIndex:34, type: DELIM_ASSIGN },
-			{ startIndex:35, type: ATTRIB_VALUE },
-			{ startIndex:44, type: DELIM_END },
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('script') },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: ATTRIB_NAME },
+			{ startIndex: 12, type: DELIM_ASSIGN },
+			{ startIndex: 13, type: ATTRIB_VALUE },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: ATTRIB_NAME },
+			{ startIndex: 34, type: DELIM_ASSIGN },
+			{ startIndex: 35, type: ATTRIB_VALUE },
+			{ startIndex: 44, type: DELIM_END },
 			// { startIndex:45, type: DELIM_START },
-			{ startIndex:47, type: getTag('script') },
-			{ startIndex:53, type: DELIM_END }
+			{ startIndex: 47, type: getTag('script') },
+			{ startIndex: 53, type: DELIM_END }
 		]
 	}],
 
@@ -340,13 +340,13 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc foo="bar">',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:5, type: ATTRIB_NAME },
-			{ startIndex:8, type: DELIM_ASSIGN },
-			{ startIndex:9, type: ATTRIB_VALUE },
-			{ startIndex:14, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: ATTRIB_NAME },
+			{ startIndex: 8, type: DELIM_ASSIGN },
+			{ startIndex: 9, type: ATTRIB_VALUE },
+			{ startIndex: 14, type: DELIM_END }
 		]
 	}],
 
@@ -354,13 +354,13 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc foo=\'bar\'>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:5, type: ATTRIB_NAME },
-			{ startIndex:8, type: DELIM_ASSIGN },
-			{ startIndex:9, type: ATTRIB_VALUE },
-			{ startIndex:14, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: ATTRIB_NAME },
+			{ startIndex: 8, type: DELIM_ASSIGN },
+			{ startIndex: 9, type: ATTRIB_VALUE },
+			{ startIndex: 14, type: DELIM_END }
 		]
 	}],
 
@@ -368,13 +368,13 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc foo="">',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:5, type: ATTRIB_NAME },
-			{ startIndex:8, type: DELIM_ASSIGN },
-			{ startIndex:9, type: ATTRIB_VALUE },
-			{ startIndex:11, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: ATTRIB_NAME },
+			{ startIndex: 8, type: DELIM_ASSIGN },
+			{ startIndex: 9, type: ATTRIB_VALUE },
+			{ startIndex: 11, type: DELIM_END }
 		]
 	}],
 
@@ -382,17 +382,17 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc foo="bar" bar=\'foo\'>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:5, type: ATTRIB_NAME },
-			{ startIndex:8, type: DELIM_ASSIGN },
-			{ startIndex:9, type: ATTRIB_VALUE },
-			{ startIndex:14, type: '' },
-			{ startIndex:15, type: ATTRIB_NAME },
-			{ startIndex:18, type: DELIM_ASSIGN },
-			{ startIndex:19, type: ATTRIB_VALUE },
-			{ startIndex:24, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: ATTRIB_NAME },
+			{ startIndex: 8, type: DELIM_ASSIGN },
+			{ startIndex: 9, type: ATTRIB_VALUE },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: ATTRIB_NAME },
+			{ startIndex: 18, type: DELIM_ASSIGN },
+			{ startIndex: 19, type: ATTRIB_VALUE },
+			{ startIndex: 24, type: DELIM_END }
 		]
 	}],
 
@@ -400,17 +400,17 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc foo=bar bar=help-me>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:5, type: ATTRIB_NAME },
-			{ startIndex:8, type: DELIM_ASSIGN },
-			{ startIndex:9, type: ATTRIB_NAME }, // slightly incorrect
-			{ startIndex:12, type: '' },
-			{ startIndex:13, type: ATTRIB_NAME },
-			{ startIndex:16, type: DELIM_ASSIGN },
-			{ startIndex:17, type: ATTRIB_NAME }, // slightly incorrect
-			{ startIndex:24, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: ATTRIB_NAME },
+			{ startIndex: 8, type: DELIM_ASSIGN },
+			{ startIndex: 9, type: ATTRIB_NAME }, // slightly incorrect
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: ATTRIB_NAME },
+			{ startIndex: 16, type: DELIM_ASSIGN },
+			{ startIndex: 17, type: ATTRIB_NAME }, // slightly incorrect
+			{ startIndex: 24, type: DELIM_END }
 		]
 	}],
 
@@ -418,14 +418,14 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc foo=  "bar">',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:5, type: ATTRIB_NAME },
-			{ startIndex:8, type: DELIM_ASSIGN },
-			{ startIndex:9, type: '' },
-			{ startIndex:11, type: ATTRIB_VALUE },
-			{ startIndex:16, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: ATTRIB_NAME },
+			{ startIndex: 8, type: DELIM_ASSIGN },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 11, type: ATTRIB_VALUE },
+			{ startIndex: 16, type: DELIM_END }
 		]
 	}],
 
@@ -433,15 +433,15 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc foo = "bar">',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:5, type: ATTRIB_NAME },
-			{ startIndex:8, type: '' },
-			{ startIndex:9, type: DELIM_ASSIGN },
-			{ startIndex:10, type: '' },
-			{ startIndex:11, type: ATTRIB_VALUE },
-			{ startIndex:16, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: ATTRIB_NAME },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: DELIM_ASSIGN },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: ATTRIB_VALUE },
+			{ startIndex: 16, type: DELIM_END }
 		]
 	}],
 
@@ -449,11 +449,11 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc foo>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:5, type: ATTRIB_NAME },
-			{ startIndex:8, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: ATTRIB_NAME },
+			{ startIndex: 8, type: DELIM_END }
 		]
 	}],
 
@@ -461,13 +461,13 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc foo bar>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:5, type: ATTRIB_NAME },
-			{ startIndex:8, type: '' },
-			{ startIndex:9, type: ATTRIB_NAME },
-			{ startIndex:12, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: ATTRIB_NAME },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: ATTRIB_NAME },
+			{ startIndex: 12, type: DELIM_END }
 		]
 	}],
 
@@ -475,14 +475,14 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc foo!@#="bar">',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:5, type: ATTRIB_NAME },
-			{ startIndex:8, type: '' },
-			{ startIndex:11, type: DELIM_ASSIGN },
-			{ startIndex:12, type: ATTRIB_VALUE },
-			{ startIndex:17, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: ATTRIB_NAME },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 11, type: DELIM_ASSIGN },
+			{ startIndex: 12, type: ATTRIB_VALUE },
+			{ startIndex: 17, type: DELIM_END }
 		]
 	}],
 
@@ -490,25 +490,25 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc #myinput (click)="bar" [value]="someProperty" *ngIf="someCondition">',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:6, type: ATTRIB_NAME },
-			{ startIndex:13, type: '' },
-			{ startIndex:15, type: ATTRIB_NAME },
-			{ startIndex:20, type: '' },
-			{ startIndex:21, type: DELIM_ASSIGN },
-			{ startIndex:22, type: ATTRIB_VALUE },
-			{ startIndex:27, type: '' },
-			{ startIndex:29, type: ATTRIB_NAME },
-			{ startIndex:34, type: '' },
-			{ startIndex:35, type: DELIM_ASSIGN },
-			{ startIndex:36, type: ATTRIB_VALUE },
-			{ startIndex:50, type: '' },
-			{ startIndex:52, type: ATTRIB_NAME },
-			{ startIndex:56, type: DELIM_ASSIGN },
-			{ startIndex:57, type: ATTRIB_VALUE },
-			{ startIndex:72, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 6, type: ATTRIB_NAME },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 15, type: ATTRIB_NAME },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: DELIM_ASSIGN },
+			{ startIndex: 22, type: ATTRIB_VALUE },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 29, type: ATTRIB_NAME },
+			{ startIndex: 34, type: '' },
+			{ startIndex: 35, type: DELIM_ASSIGN },
+			{ startIndex: 36, type: ATTRIB_VALUE },
+			{ startIndex: 50, type: '' },
+			{ startIndex: 52, type: ATTRIB_NAME },
+			{ startIndex: 56, type: DELIM_ASSIGN },
+			{ startIndex: 57, type: ATTRIB_VALUE },
+			{ startIndex: 72, type: DELIM_END }
 		]
 	}],
 
@@ -516,13 +516,13 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<abc foo=">',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('abc') },
-			{ startIndex:4, type: '' },
-			{ startIndex:5, type: ATTRIB_NAME },
-			{ startIndex:8, type: DELIM_ASSIGN },
-			{ startIndex:9, type: '' },
-			{ startIndex:10, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('abc') },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: ATTRIB_NAME },
+			{ startIndex: 8, type: DELIM_ASSIGN },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: DELIM_END }
 		]
 	}],
 
@@ -530,9 +530,9 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<!--a-->',
 		tokens: [
-			{ startIndex:0, type: DELIM_COMMENT },
-			{ startIndex:4, type: COMMENT },
-			{ startIndex:5, type: DELIM_COMMENT }
+			{ startIndex: 0, type: DELIM_COMMENT },
+			{ startIndex: 4, type: COMMENT },
+			{ startIndex: 5, type: DELIM_COMMENT }
 		]
 	}],
 
@@ -540,9 +540,9 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<!--a>foo bar</a -->',
 		tokens: [
-			{ startIndex:0, type: DELIM_COMMENT },
-			{ startIndex:4, type: COMMENT },
-			{ startIndex:17, type: DELIM_COMMENT }
+			{ startIndex: 0, type: DELIM_COMMENT },
+			{ startIndex: 4, type: COMMENT },
+			{ startIndex: 17, type: DELIM_COMMENT }
 		]
 	}],
 
@@ -550,19 +550,19 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<!--a>',
 		tokens: [
-			{ startIndex:0, type: DELIM_COMMENT },
-			{ startIndex:4, type: COMMENT }
+			{ startIndex: 0, type: DELIM_COMMENT },
+			{ startIndex: 4, type: COMMENT }
 		]
-	},{
+	}, {
 		line: 'foo ',
 		tokens: [
-			{ startIndex:0, type: COMMENT },
+			{ startIndex: 0, type: COMMENT },
 		]
-	},{
+	}, {
 		line: 'bar</a -->',
 		tokens: [
-			{ startIndex:0, type: COMMENT },
-			{ startIndex:7, type: DELIM_COMMENT }
+			{ startIndex: 0, type: COMMENT },
+			{ startIndex: 7, type: DELIM_COMMENT }
 		]
 	}],
 
@@ -570,9 +570,9 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<!DOCTYPE a>',
 		tokens: [
-			{ startIndex:0, type: DELIM_DOCTYPE },
-			{ startIndex:9, type: DOCTYPE },
-			{ startIndex:11, type: DELIM_DOCTYPE }
+			{ startIndex: 0, type: DELIM_DOCTYPE },
+			{ startIndex: 9, type: DOCTYPE },
+			{ startIndex: 11, type: DELIM_DOCTYPE }
 		]
 	}],
 
@@ -580,9 +580,9 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<!doctype a>',
 		tokens: [
-			{ startIndex:0, type: DELIM_DOCTYPE },
-			{ startIndex:9, type: DOCTYPE },
-			{ startIndex:11, type: DELIM_DOCTYPE }
+			{ startIndex: 0, type: DELIM_DOCTYPE },
+			{ startIndex: 9, type: DOCTYPE },
+			{ startIndex: 11, type: DELIM_DOCTYPE }
 		]
 	}],
 
@@ -590,14 +590,14 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<!DOCTYPE a',
 		tokens: [
-			{ startIndex:0, type: DELIM_DOCTYPE },
-			{ startIndex:9, type: DOCTYPE },
+			{ startIndex: 0, type: DELIM_DOCTYPE },
+			{ startIndex: 9, type: DOCTYPE },
 		]
 	}, {
 		line: '"foo" \'bar\'>',
 		tokens: [
-			{ startIndex:0, type: DOCTYPE },
-			{ startIndex:11, type: DELIM_DOCTYPE }
+			{ startIndex: 0, type: DOCTYPE },
+			{ startIndex: 11, type: DELIM_DOCTYPE }
 		]
 	}],
 
@@ -605,13 +605,13 @@ testTokenization(['html', 'css'], [
 	[{
 		line: '<asdf:bar>asd</asdf:bar>',
 		tokens: [
-			{ startIndex:0, type: DELIM_START },
-			{ startIndex:1, type: getTag('asdf:bar') },
-			{ startIndex:9, type: DELIM_END },
-			{ startIndex:10, type: '' },
-			{ startIndex:13, type: DELIM_START },
-			{ startIndex:15, type: getTag('asdf:bar') },
-			{ startIndex:23, type: DELIM_END }
+			{ startIndex: 0, type: DELIM_START },
+			{ startIndex: 1, type: getTag('asdf:bar') },
+			{ startIndex: 9, type: DELIM_END },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 13, type: DELIM_START },
+			{ startIndex: 15, type: getTag('asdf:bar') },
+			{ startIndex: 23, type: DELIM_END }
 		]
 	}]
 ]);

+ 374 - 321
test/jade.test.ts

@@ -5,376 +5,429 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('jade', [
 	// Tags [Jade]
 	[{
-	line: 'p 5',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 1, type: '' }
-	]}],
+		line: 'p 5',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 1, type: '' }
+		]
+	}],
 
 	[{
-	line: 'div#container.stuff',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 3, type: 'tag.id.jade' },
-		{ startIndex: 13, type: 'tag.class.jade' }
-	]}],
+		line: 'div#container.stuff',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 3, type: 'tag.id.jade' },
+			{ startIndex: 13, type: 'tag.class.jade' }
+		]
+	}],
 
 	[{
-	line: 'div.container#stuff',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 3, type: 'tag.class.jade' },
-		{ startIndex: 13, type: 'tag.id.jade' }
-	]}],
+		line: 'div.container#stuff',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 3, type: 'tag.class.jade' },
+			{ startIndex: 13, type: 'tag.id.jade' }
+		]
+	}],
 
 	[{
-	line: 'div.container#stuff .container',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 3, type: 'tag.class.jade' },
-		{ startIndex: 13, type: 'tag.id.jade' },
-		{ startIndex: 19, type: '' }
-	]}],
+		line: 'div.container#stuff .container',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 3, type: 'tag.class.jade' },
+			{ startIndex: 13, type: 'tag.id.jade' },
+			{ startIndex: 19, type: '' }
+		]
+	}],
 
 	[{
-	line: '#tag-id-1',
-	tokens: [
-		{ startIndex: 0, type: 'tag.id.jade' }
-	]}],
+		line: '#tag-id-1',
+		tokens: [
+			{ startIndex: 0, type: 'tag.id.jade' }
+		]
+	}],
 
 	[{
-	line: '.tag-id-1',
-	tokens: [
-		{ startIndex: 0, type: 'tag.class.jade' }
-	]}],
+		line: '.tag-id-1',
+		tokens: [
+			{ startIndex: 0, type: 'tag.class.jade' }
+		]
+	}],
 
 	// Attributes - Single Line [Jade]
 	[{
-	line: 'input(type="checkbox")',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 5, type: 'delimiter.parenthesis.jade' },
-		{ startIndex: 6, type: 'attribute.name.jade' },
-		{ startIndex: 10, type: 'delimiter.jade' },
-		{ startIndex: 11, type: 'attribute.value.jade' },
-		{ startIndex: 21, type: 'delimiter.parenthesis.jade' }
-	]}],
+		line: 'input(type="checkbox")',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 5, type: 'delimiter.parenthesis.jade' },
+			{ startIndex: 6, type: 'attribute.name.jade' },
+			{ startIndex: 10, type: 'delimiter.jade' },
+			{ startIndex: 11, type: 'attribute.value.jade' },
+			{ startIndex: 21, type: 'delimiter.parenthesis.jade' }
+		]
+	}],
 
 	[{
-	line: 'input (type="checkbox")',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 5, type: '' }
-	]}],
+		line: 'input (type="checkbox")',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 5, type: '' }
+		]
+	}],
 
 	[{
-	line: 'input(type="checkbox",name="agreement",checked)',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 5, type: 'delimiter.parenthesis.jade' },
-		{ startIndex: 6, type: 'attribute.name.jade' },
-		{ startIndex: 10, type: 'delimiter.jade' },
-		{ startIndex: 11, type: 'attribute.value.jade' },
-		{ startIndex: 21, type: 'attribute.delimiter.jade' },
-		{ startIndex: 22, type: 'attribute.name.jade' },
-		{ startIndex: 26, type: 'delimiter.jade' },
-		{ startIndex: 27, type: 'attribute.value.jade' },
-		{ startIndex: 38, type: 'attribute.delimiter.jade' },
-		{ startIndex: 39, type: 'attribute.name.jade' },
-		{ startIndex: 46, type: 'delimiter.parenthesis.jade' }
-	]}],
+		line: 'input(type="checkbox",name="agreement",checked)',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 5, type: 'delimiter.parenthesis.jade' },
+			{ startIndex: 6, type: 'attribute.name.jade' },
+			{ startIndex: 10, type: 'delimiter.jade' },
+			{ startIndex: 11, type: 'attribute.value.jade' },
+			{ startIndex: 21, type: 'attribute.delimiter.jade' },
+			{ startIndex: 22, type: 'attribute.name.jade' },
+			{ startIndex: 26, type: 'delimiter.jade' },
+			{ startIndex: 27, type: 'attribute.value.jade' },
+			{ startIndex: 38, type: 'attribute.delimiter.jade' },
+			{ startIndex: 39, type: 'attribute.name.jade' },
+			{ startIndex: 46, type: 'delimiter.parenthesis.jade' }
+		]
+	}],
 
 	[{
-	line: 'input(type="checkbox"',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 5, type: 'delimiter.parenthesis.jade' },
-		{ startIndex: 6, type: 'attribute.name.jade' },
-		{ startIndex: 10, type: 'delimiter.jade' },
-		{ startIndex: 11, type: 'attribute.value.jade' }
-	]}, {
-	line: 'name="agreement"',
-	tokens: [
-		{ startIndex: 0, type: 'attribute.name.jade' },
-		{ startIndex: 4, type: 'delimiter.jade' },
-		{ startIndex: 5, type: 'attribute.value.jade' }
-	]}, {
-	line: 'checked)',
-	tokens: [
-		{ startIndex: 0, type: 'attribute.name.jade' },
-		{ startIndex: 7, type: 'delimiter.parenthesis.jade' }
-	]}, {
-	line: 'body',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' }
-	]}],
+		line: 'input(type="checkbox"',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 5, type: 'delimiter.parenthesis.jade' },
+			{ startIndex: 6, type: 'attribute.name.jade' },
+			{ startIndex: 10, type: 'delimiter.jade' },
+			{ startIndex: 11, type: 'attribute.value.jade' }
+		]
+	}, {
+		line: 'name="agreement"',
+		tokens: [
+			{ startIndex: 0, type: 'attribute.name.jade' },
+			{ startIndex: 4, type: 'delimiter.jade' },
+			{ startIndex: 5, type: 'attribute.value.jade' }
+		]
+	}, {
+		line: 'checked)',
+		tokens: [
+			{ startIndex: 0, type: 'attribute.name.jade' },
+			{ startIndex: 7, type: 'delimiter.parenthesis.jade' }
+		]
+	}, {
+		line: 'body',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' }
+		]
+	}],
 
 	// Attributes - MultiLine [Jade]
 	[{
-	line: 'input(type="checkbox"',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 5, type: 'delimiter.parenthesis.jade' },
-		{ startIndex: 6, type: 'attribute.name.jade' },
-		{ startIndex: 10, type: 'delimiter.jade' },
-		{ startIndex: 11, type: 'attribute.value.jade' }
-	]}, {
-	line: 'disabled',
-	tokens: [
-		{ startIndex: 0, type: 'attribute.name.jade' }
-	]}, {
-	line: 'checked)',
-	tokens: [
-		{ startIndex: 0, type: 'attribute.name.jade' },
-		{ startIndex: 7, type: 'delimiter.parenthesis.jade' }
-	]}, {
-	line: 'body',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' }
-	]}],
+		line: 'input(type="checkbox"',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 5, type: 'delimiter.parenthesis.jade' },
+			{ startIndex: 6, type: 'attribute.name.jade' },
+			{ startIndex: 10, type: 'delimiter.jade' },
+			{ startIndex: 11, type: 'attribute.value.jade' }
+		]
+	}, {
+		line: 'disabled',
+		tokens: [
+			{ startIndex: 0, type: 'attribute.name.jade' }
+		]
+	}, {
+		line: 'checked)',
+		tokens: [
+			{ startIndex: 0, type: 'attribute.name.jade' },
+			{ startIndex: 7, type: 'delimiter.parenthesis.jade' }
+		]
+	}, {
+		line: 'body',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' }
+		]
+	}],
 
 	// Interpolation [Jade]
 	[{
-	line: 'p print #{count} lines',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 8, type: 'interpolation.delimiter.jade' },
-		{ startIndex: 10, type: 'interpolation.jade' },
-		{ startIndex: 15, type: 'interpolation.delimiter.jade' },
-		{ startIndex: 16, type: '' }
-	]}],
+		line: 'p print #{count} lines',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 8, type: 'interpolation.delimiter.jade' },
+			{ startIndex: 10, type: 'interpolation.jade' },
+			{ startIndex: 15, type: 'interpolation.delimiter.jade' },
+			{ startIndex: 16, type: '' }
+		]
+	}],
 
 	[{
-	line: 'p print "#{count}" lines',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 9, type: 'interpolation.delimiter.jade' },
-		{ startIndex: 11, type: 'interpolation.jade' },
-		{ startIndex: 16, type: 'interpolation.delimiter.jade' },
-		{ startIndex: 17, type: '' }
-	]}],
+		line: 'p print "#{count}" lines',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 9, type: 'interpolation.delimiter.jade' },
+			{ startIndex: 11, type: 'interpolation.jade' },
+			{ startIndex: 16, type: 'interpolation.delimiter.jade' },
+			{ startIndex: 17, type: '' }
+		]
+	}],
 
 	[{
-	line: '{ key: 123 }',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.jade' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 5, type: 'delimiter.jade' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'number.jade' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'delimiter.curly.jade' }
-	]}],
+		line: '{ key: 123 }',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.jade' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 5, type: 'delimiter.jade' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'number.jade' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'delimiter.curly.jade' }
+		]
+	}],
 
 	// Comments - Single Line [Jade]
 	[{
-	line: '// html#id1.class1',
-	tokens: [
-		{ startIndex: 0, type: 'comment.jade' }
-	]}],
+		line: '// html#id1.class1',
+		tokens: [
+			{ startIndex: 0, type: 'comment.jade' }
+		]
+	}],
 
 	[{
-	line: 'body hello // not a comment 123',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 4, type: '' }
-	]}],
+		line: 'body hello // not a comment 123',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 4, type: '' }
+		]
+	}],
 
 	// Comments - MultiLine [Jade]
 	[{
-	line: '//',
-	tokens: [
-		{ startIndex: 0, type: 'comment.jade' }
-	]}, {
-	line: '    should be a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.jade' }
-	]}, {
-	line: '    should still be a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.jade' }
-	]}, {
-	line: 'div should not be a comment',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 3, type: '' }
-	]}],
+		line: '//',
+		tokens: [
+			{ startIndex: 0, type: 'comment.jade' }
+		]
+	}, {
+		line: '    should be a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.jade' }
+		]
+	}, {
+		line: '    should still be a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.jade' }
+		]
+	}, {
+		line: 'div should not be a comment',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 3, type: '' }
+		]
+	}],
 
 	// Code [Jade]
 	[{
-	line: '- var a = 1',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.var.jade' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 8, type: 'delimiter.jade' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'number.jade' }
-	]}],
+		line: '- var a = 1',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.var.jade' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 8, type: 'delimiter.jade' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'number.jade' }
+		]
+	}],
 
 	[{
-	line: 'each item in items',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.each.jade' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 10, type: 'keyword.in.jade' },
-		{ startIndex: 12, type: '' }
-	]}],
+		line: 'each item in items',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.each.jade' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 10, type: 'keyword.in.jade' },
+			{ startIndex: 12, type: '' }
+		]
+	}],
 
 	[{
-	line: '- var html = "<script></script>"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.var.jade' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 11, type: 'delimiter.jade' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'string.jade' }
-	]}],
+		line: '- var html = "<script></script>"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.var.jade' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 11, type: 'delimiter.jade' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'string.jade' }
+		]
+	}],
 
 	// Generated from sample
 	[{
-	line: 'doctype 5',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.doctype.jade' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.jade' }
-	]}, {
-	line: 'html(lang="en")',
-	tokens: [
-		{ startIndex: 0, type: 'tag.jade' },
-		{ startIndex: 4, type: 'delimiter.parenthesis.jade' },
-		{ startIndex: 5, type: 'attribute.name.jade' },
-		{ startIndex: 9, type: 'delimiter.jade' },
-		{ startIndex: 10, type: 'attribute.value.jade' },
-		{ startIndex: 14, type: 'delimiter.parenthesis.jade' }
-	]}, {
-	line: '    head',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'tag.jade' }
-	]}, {
-	line: '        title= pageTitle',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'tag.jade' },
-		{ startIndex: 13, type: '' }
-	]}, {
-	line: '        script(type=\'text/javascript\')',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'tag.jade' },
-		{ startIndex: 14, type: 'delimiter.parenthesis.jade' },
-		{ startIndex: 15, type: 'attribute.name.jade' },
-		{ startIndex: 19, type: 'delimiter.jade' },
-		{ startIndex: 20, type: 'attribute.value.jade' },
-		{ startIndex: 37, type: 'delimiter.parenthesis.jade' }
-	]}, {
-	line: '            if (foo) {',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 12, type: 'keyword.if.jade' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'delimiter.parenthesis.jade' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 19, type: 'delimiter.parenthesis.jade' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'delimiter.curly.jade' }
-	]}, {
-	line: '                bar()',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 19, type: 'delimiter.parenthesis.jade' }
-	]}, {
-	line: '            }',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 12, type: 'delimiter.curly.jade' }
-	]}, {
-	line: '    body',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'tag.jade' }
-	]}, {
-	line: '        // Disclaimer: You will need to turn insertSpaces to true in order for the',
-	tokens: [
-		{ startIndex: 0, type: 'comment.jade' }
-	]}, {
-	line: '         syntax highlighting to kick in properly (especially for comments)',
-	tokens: [
-		{ startIndex: 0, type: 'comment.jade' }
-	]}, {
-	line: '            Enjoy :)',
-	tokens: [
-		{ startIndex: 0, type: 'comment.jade' }
-	]}, {
-	line: '        h1 Jade - node template engine if in',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'tag.jade' },
-		{ startIndex: 10, type: '' }
-	]}, {
-	line: '        p.',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'tag.jade' },
-		{ startIndex: 9, type: 'delimiter.jade' }
-	]}, {
-	line: '          text ',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '            text',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '          #container',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '         #container',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '        #container',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'tag.id.jade' }
-	]}, {
-	line: '          if youAreUsingJade',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 10, type: 'keyword.if.jade' },
-		{ startIndex: 12, type: '' }
-	]}, {
-	line: '            p You are amazing',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 12, type: 'tag.jade' },
-		{ startIndex: 13, type: '' }
-	]}, {
-	line: '          else',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 10, type: 'keyword.else.jade' }
-	]}, {
-	line: '            p Get on it!',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 12, type: 'tag.jade' },
-		{ startIndex: 13, type: '' }
-	]}, {
-	line: '     p Text can be included in a number of different ways.',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: 'tag.jade' },
-		{ startIndex: 6, type: '' }
-	]}]
+		line: 'doctype 5',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.doctype.jade' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.jade' }
+		]
+	}, {
+		line: 'html(lang="en")',
+		tokens: [
+			{ startIndex: 0, type: 'tag.jade' },
+			{ startIndex: 4, type: 'delimiter.parenthesis.jade' },
+			{ startIndex: 5, type: 'attribute.name.jade' },
+			{ startIndex: 9, type: 'delimiter.jade' },
+			{ startIndex: 10, type: 'attribute.value.jade' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.jade' }
+		]
+	}, {
+		line: '    head',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'tag.jade' }
+		]
+	}, {
+		line: '        title= pageTitle',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'tag.jade' },
+			{ startIndex: 13, type: '' }
+		]
+	}, {
+		line: '        script(type=\'text/javascript\')',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'tag.jade' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.jade' },
+			{ startIndex: 15, type: 'attribute.name.jade' },
+			{ startIndex: 19, type: 'delimiter.jade' },
+			{ startIndex: 20, type: 'attribute.value.jade' },
+			{ startIndex: 37, type: 'delimiter.parenthesis.jade' }
+		]
+	}, {
+		line: '            if (foo) {',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 12, type: 'keyword.if.jade' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'delimiter.parenthesis.jade' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 19, type: 'delimiter.parenthesis.jade' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'delimiter.curly.jade' }
+		]
+	}, {
+		line: '                bar()',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 19, type: 'delimiter.parenthesis.jade' }
+		]
+	}, {
+		line: '            }',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 12, type: 'delimiter.curly.jade' }
+		]
+	}, {
+		line: '    body',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'tag.jade' }
+		]
+	}, {
+		line: '        // Disclaimer: You will need to turn insertSpaces to true in order for the',
+		tokens: [
+			{ startIndex: 0, type: 'comment.jade' }
+		]
+	}, {
+		line: '         syntax highlighting to kick in properly (especially for comments)',
+		tokens: [
+			{ startIndex: 0, type: 'comment.jade' }
+		]
+	}, {
+		line: '            Enjoy :)',
+		tokens: [
+			{ startIndex: 0, type: 'comment.jade' }
+		]
+	}, {
+		line: '        h1 Jade - node template engine if in',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'tag.jade' },
+			{ startIndex: 10, type: '' }
+		]
+	}, {
+		line: '        p.',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'tag.jade' },
+			{ startIndex: 9, type: 'delimiter.jade' }
+		]
+	}, {
+		line: '          text ',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '            text',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '          #container',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '         #container',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '        #container',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'tag.id.jade' }
+		]
+	}, {
+		line: '          if youAreUsingJade',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 10, type: 'keyword.if.jade' },
+			{ startIndex: 12, type: '' }
+		]
+	}, {
+		line: '            p You are amazing',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 12, type: 'tag.jade' },
+			{ startIndex: 13, type: '' }
+		]
+	}, {
+		line: '          else',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 10, type: 'keyword.else.jade' }
+		]
+	}, {
+		line: '            p Get on it!',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 12, type: 'tag.jade' },
+			{ startIndex: 13, type: '' }
+		]
+	}, {
+		line: '     p Text can be included in a number of different ways.',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'tag.jade' },
+			{ startIndex: 6, type: '' }
+		]
+	}]
 ]);

+ 565 - 489
test/java.test.ts

@@ -5,601 +5,677 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('java', [
 	// Comments - single line
 	[{
-	line: '//',
-	tokens: [
-		{ startIndex: 0, type: 'comment.java' }
-	]}],
+		line: '//',
+		tokens: [
+			{ startIndex: 0, type: 'comment.java' }
+		]
+	}],
 
 	[{
-	line: '    // a comment',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'comment.java' }
-	]}],
+		line: '    // a comment',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'comment.java' }
+		]
+	}],
 
 	// Broken nested tokens due to invalid comment tokenization
 	[{
-	line: '/* //*/ a',
-	tokens: [
-		{ startIndex: 0, type: 'comment.java' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.java' }
-	]}],
-
-	[{
-	line: '// a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.java' }
-	]}],
-
-	[{
-	line: '//sticky comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.java' }
-	]}],
-
-	[{
-	line: '/almost a comment',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.java' },
-		{ startIndex: 1, type: 'identifier.java' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.java' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'identifier.java' }
-	]}],
-
-	[{
-	line: '1 / 2; /* comment',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.java' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.java' },
-		{ startIndex: 5, type: 'delimiter.java' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'comment.java' }
-	]}],
-
-	[{
-	line: 'int x = 1; // my comment // is a nice one',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.int.java' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.java' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.java' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.java' },
-		{ startIndex: 9, type: 'delimiter.java' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'comment.java' }
-	]}],
+		line: '/* //*/ a',
+		tokens: [
+			{ startIndex: 0, type: 'comment.java' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.java' }
+		]
+	}],
+
+	[{
+		line: '// a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.java' }
+		]
+	}],
+
+	[{
+		line: '//sticky comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.java' }
+		]
+	}],
+
+	[{
+		line: '/almost a comment',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.java' },
+			{ startIndex: 1, type: 'identifier.java' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.java' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.java' }
+		]
+	}],
+
+	[{
+		line: '1 / 2; /* comment',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.java' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.java' },
+			{ startIndex: 5, type: 'delimiter.java' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'comment.java' }
+		]
+	}],
+
+	[{
+		line: 'int x = 1; // my comment // is a nice one',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.int.java' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.java' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.java' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.java' },
+			{ startIndex: 9, type: 'delimiter.java' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'comment.java' }
+		]
+	}],
 
 	// Comments - range comment, single line
 	[{
-	line: '/* a simple comment */',
-	tokens: [
-		{ startIndex: 0, type: 'comment.java' }
-	]}],
-
-	[{
-	line: 'int x = /* a simple comment */ 1;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.int.java' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.java' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.java' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.java' },
-		{ startIndex: 30, type: '' },
-		{ startIndex: 31, type: 'number.java' },
-		{ startIndex: 32, type: 'delimiter.java' }
-	]}],
-
-	[{
-	line: 'int x = /* comment */ 1; */',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.int.java' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.java' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.java' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.java' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'number.java' },
-		{ startIndex: 23, type: 'delimiter.java' },
-		{ startIndex: 24, type: '' }
-	]}],
-
-	[{
-	line: 'x = /**/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.java' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.java' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.java' },
-		{ startIndex: 8, type: 'delimiter.java' }
-	]}],
-
-	[{
-	line: 'x = /*/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.java' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.java' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.java' }
-	]}],
+		line: '/* a simple comment */',
+		tokens: [
+			{ startIndex: 0, type: 'comment.java' }
+		]
+	}],
+
+	[{
+		line: 'int x = /* a simple comment */ 1;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.int.java' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.java' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.java' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.java' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'number.java' },
+			{ startIndex: 32, type: 'delimiter.java' }
+		]
+	}],
+
+	[{
+		line: 'int x = /* comment */ 1; */',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.int.java' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.java' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.java' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.java' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'number.java' },
+			{ startIndex: 23, type: 'delimiter.java' },
+			{ startIndex: 24, type: '' }
+		]
+	}],
+
+	[{
+		line: 'x = /**/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.java' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.java' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.java' },
+			{ startIndex: 8, type: 'delimiter.java' }
+		]
+	}],
+
+	[{
+		line: 'x = /*/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.java' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.java' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.java' }
+		]
+	}],
 
 	// Comments - range comment, multiple lines
 	[{
-	line: '/* start of multiline comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.java' }
-	]}, {
-	line: 'a comment between without a star',
-	tokens: [
-		{ startIndex: 0, type: 'comment.java' }
-	]}, {
-	line: 'end of multiline comment*/',
-	tokens: [
-		{ startIndex: 0, type: 'comment.java' }
-	]}],
-
-	[{
-	line: 'int x = /* start a comment',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.int.java' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.java' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.java' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.java' }
-	]}, {
-	line: ' a ',
-	tokens: [
-		{ startIndex: 0, type: 'comment.java' }
-	]}, {
-	line: 'and end it */ 2;',
-	tokens: [
-		{ startIndex: 0, type: 'comment.java' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'number.java' },
-		{ startIndex: 15, type: 'delimiter.java' }
-	]}],
+		line: '/* start of multiline comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.java' }
+		]
+	}, {
+		line: 'a comment between without a star',
+		tokens: [
+			{ startIndex: 0, type: 'comment.java' }
+		]
+	}, {
+		line: 'end of multiline comment*/',
+		tokens: [
+			{ startIndex: 0, type: 'comment.java' }
+		]
+	}],
+
+	[{
+		line: 'int x = /* start a comment',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.int.java' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.java' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.java' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.java' }
+		]
+	}, {
+		line: ' a ',
+		tokens: [
+			{ startIndex: 0, type: 'comment.java' }
+		]
+	}, {
+		line: 'and end it */ 2;',
+		tokens: [
+			{ startIndex: 0, type: 'comment.java' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'number.java' },
+			{ startIndex: 15, type: 'delimiter.java' }
+		]
+	}],
 
 	// Java Doc, multiple lines
 	[{
-	line: '/** start of Java Doc',
-	tokens: [
-		{ startIndex: 0, type: 'comment.doc.java' }
-	]}, {
-	line: 'a comment between without a star',
-	tokens: [
-		{ startIndex: 0, type: 'comment.doc.java' }
-	]}, {
-	line: 'end of multiline comment*/',
-	tokens: [
-		{ startIndex: 0, type: 'comment.doc.java' }
-	]}],
+		line: '/** start of Java Doc',
+		tokens: [
+			{ startIndex: 0, type: 'comment.doc.java' }
+		]
+	}, {
+		line: 'a comment between without a star',
+		tokens: [
+			{ startIndex: 0, type: 'comment.doc.java' }
+		]
+	}, {
+		line: 'end of multiline comment*/',
+		tokens: [
+			{ startIndex: 0, type: 'comment.doc.java' }
+		]
+	}],
 
 	// Keywords
 	[{
-	line: 'package test; class Program { static void main(String[] args) {} } }',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.package.java' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.java' },
-		{ startIndex: 12, type: 'delimiter.java' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'keyword.class.java' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'identifier.java' },
-		{ startIndex: 27, type: '' },
-		{ startIndex: 28, type: 'delimiter.curly.java' },
-		{ startIndex: 29, type: '' },
-		{ startIndex: 30, type: 'keyword.static.java' },
-		{ startIndex: 36, type: '' },
-		{ startIndex: 37, type: 'keyword.void.java' },
-		{ startIndex: 41, type: '' },
-		{ startIndex: 42, type: 'identifier.java' },
-		{ startIndex: 46, type: 'delimiter.parenthesis.java' },
-		{ startIndex: 47, type: 'identifier.java' },
-		{ startIndex: 53, type: 'delimiter.square.java' },
-		{ startIndex: 55, type: '' },
-		{ startIndex: 56, type: 'identifier.java' },
-		{ startIndex: 60, type: 'delimiter.parenthesis.java' },
-		{ startIndex: 61, type: '' },
-		{ startIndex: 62, type: 'delimiter.curly.java' },
-		{ startIndex: 64, type: '' },
-		{ startIndex: 65, type: 'delimiter.curly.java' },
-		{ startIndex: 66, type: '' },
-		{ startIndex: 67, type: 'delimiter.curly.java' }
-	]}],
+		line: 'package test; class Program { static void main(String[] args) {} } }',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.package.java' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.java' },
+			{ startIndex: 12, type: 'delimiter.java' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'keyword.class.java' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'identifier.java' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'delimiter.curly.java' },
+			{ startIndex: 29, type: '' },
+			{ startIndex: 30, type: 'keyword.static.java' },
+			{ startIndex: 36, type: '' },
+			{ startIndex: 37, type: 'keyword.void.java' },
+			{ startIndex: 41, type: '' },
+			{ startIndex: 42, type: 'identifier.java' },
+			{ startIndex: 46, type: 'delimiter.parenthesis.java' },
+			{ startIndex: 47, type: 'identifier.java' },
+			{ startIndex: 53, type: 'delimiter.square.java' },
+			{ startIndex: 55, type: '' },
+			{ startIndex: 56, type: 'identifier.java' },
+			{ startIndex: 60, type: 'delimiter.parenthesis.java' },
+			{ startIndex: 61, type: '' },
+			{ startIndex: 62, type: 'delimiter.curly.java' },
+			{ startIndex: 64, type: '' },
+			{ startIndex: 65, type: 'delimiter.curly.java' },
+			{ startIndex: 66, type: '' },
+			{ startIndex: 67, type: 'delimiter.curly.java' }
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '0',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' }
-	]}],
+		line: '0',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' }
+		]
+	}],
 
 	[{
-	line: '0.10',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '0.10',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '0x',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' },
-		{ startIndex: 1, type: 'identifier.java' }
-	]}],
+		line: '0x',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' },
+			{ startIndex: 1, type: 'identifier.java' }
+		]
+	}],
 
 	[{
-	line: '0x123',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.java' }
-	]}],
+		line: '0x123',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.java' }
+		]
+	}],
 
 	[{
-	line: '0x5_2',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.java' }
-	]}],
+		line: '0x5_2',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.java' }
+		]
+	}],
 
 	[{
-	line: '023L',
-	tokens: [
-		{ startIndex: 0, type: 'number.octal.java' }
-	]}],
+		line: '023L',
+		tokens: [
+			{ startIndex: 0, type: 'number.octal.java' }
+		]
+	}],
 
 	[{
-	line: '0123l',
-	tokens: [
-		{ startIndex: 0, type: 'number.octal.java' }
-	]}],
+		line: '0123l',
+		tokens: [
+			{ startIndex: 0, type: 'number.octal.java' }
+		]
+	}],
 
 	[{
-	line: '05_2',
-	tokens: [
-		{ startIndex: 0, type: 'number.octal.java' }
-	]}],
+		line: '05_2',
+		tokens: [
+			{ startIndex: 0, type: 'number.octal.java' }
+		]
+	}],
 
 	[{
-	line: '0b1010_0101',
-	tokens: [
-		{ startIndex: 0, type: 'number.binary.java' }
-	]}],
+		line: '0b1010_0101',
+		tokens: [
+			{ startIndex: 0, type: 'number.binary.java' }
+		]
+	}],
 
 	[{
-	line: '0B001',
-	tokens: [
-		{ startIndex: 0, type: 'number.binary.java' }
-	]}],
+		line: '0B001',
+		tokens: [
+			{ startIndex: 0, type: 'number.binary.java' }
+		]
+	}],
 
 	[{
-	line: '10e3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '10e3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '10f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '10f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '23.5',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '23.5',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '23.5e3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '23.5e3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '23.5e-3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '23.5e-3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '23.5E3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '23.5E3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '23.5E-3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '23.5E-3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '23.5F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '23.5F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '23.5f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '23.5f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '23.5D',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '23.5D',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '23.5d',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '23.5d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '1.72E3D',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '1.72E3D',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '1.72E3d',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '1.72E3d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '1.72E-3d',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '1.72E-3d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '1.72e3D',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '1.72e3D',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '1.72e3d',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '1.72e3d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '1.72e-3d',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' }
-	]}],
+		line: '1.72e-3d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '23L',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' }
-	]}],
+		line: '23L',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' }
+		]
+	}],
 
 	[{
-	line: '23l',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' }
-	]}],
+		line: '23l',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' }
+		]
+	}],
 
 	[{
-	line: '0_52',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' }
-	]}],
+		line: '0_52',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' }
+		]
+	}],
 
 	[{
-	line: '5_2',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' }
-	]}],
+		line: '5_2',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' }
+		]
+	}],
 
 	[{
-	line: '5_______2',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' }
-	]}],
+		line: '5_______2',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' }
+		]
+	}],
 
 	[{
-	line: '3_.1415F',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' },
-		{ startIndex: 1, type: 'identifier.java' },
-		{ startIndex: 2, type: 'delimiter.java' },
-		{ startIndex: 3, type: 'number.float.java' }
-	]}],
+		line: '3_.1415F',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' },
+			{ startIndex: 1, type: 'identifier.java' },
+			{ startIndex: 2, type: 'delimiter.java' },
+			{ startIndex: 3, type: 'number.float.java' }
+		]
+	}],
 
 	[{
-	line: '3._1415F',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' },
-		{ startIndex: 1, type: 'delimiter.java' },
-		{ startIndex: 2, type: 'identifier.java' }
-	]}],
+		line: '3._1415F',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' },
+			{ startIndex: 1, type: 'delimiter.java' },
+			{ startIndex: 2, type: 'identifier.java' }
+		]
+	}],
 
 	[{
-	line: '999_99_9999_L',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' },
-		{ startIndex: 11, type: 'identifier.java' }
-	]}],
+		line: '999_99_9999_L',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' },
+			{ startIndex: 11, type: 'identifier.java' }
+		]
+	}],
 
 	[{
-	line: '52_',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' },
-		{ startIndex: 2, type: 'identifier.java' }
-	]}],
+		line: '52_',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' },
+			{ startIndex: 2, type: 'identifier.java' }
+		]
+	}],
 
 	[{
-	line: '0_x52',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' },
-		{ startIndex: 1, type: 'identifier.java' }
-	]}],
+		line: '0_x52',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' },
+			{ startIndex: 1, type: 'identifier.java' }
+		]
+	}],
 
 	[{
-	line: '0x_52',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' },
-		{ startIndex: 1, type: 'identifier.java' }
-	]}],
+		line: '0x_52',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' },
+			{ startIndex: 1, type: 'identifier.java' }
+		]
+	}],
 
 	[{
-	line: '0x52_',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.java' },
-		{ startIndex: 4, type: 'identifier.java' }
-	]}],
+		line: '0x52_',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.java' },
+			{ startIndex: 4, type: 'identifier.java' }
+		]
+	}],
 
-	[{
-	line: '052_',
-	tokens: [
-		{ startIndex: 0, type: 'number.octal.java' },
-		{ startIndex: 3, type: 'identifier.java' }
-	]}],
-
-	[{
-	line: '23.5L',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.java' },
-		{ startIndex: 4, type: 'identifier.java' }
-	]}],
-
-	[{
-	line: '0+0',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' },
-		{ startIndex: 1, type: 'delimiter.java' },
-		{ startIndex: 2, type: 'number.java' }
-	]}],
-
-	[{
-	line: '100+10',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' },
-		{ startIndex: 3, type: 'delimiter.java' },
-		{ startIndex: 4, type: 'number.java' }
-	]}],
-
-	[{
-	line: '0 + 0',
-	tokens: [
-		{ startIndex: 0, type: 'number.java' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.java' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.java' }
-	]}],
+	[{
+		line: '052_',
+		tokens: [
+			{ startIndex: 0, type: 'number.octal.java' },
+			{ startIndex: 3, type: 'identifier.java' }
+		]
+	}],
+
+	[{
+		line: '23.5L',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.java' },
+			{ startIndex: 4, type: 'identifier.java' }
+		]
+	}],
+
+	[{
+		line: '0+0',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' },
+			{ startIndex: 1, type: 'delimiter.java' },
+			{ startIndex: 2, type: 'number.java' }
+		]
+	}],
+
+	[{
+		line: '100+10',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' },
+			{ startIndex: 3, type: 'delimiter.java' },
+			{ startIndex: 4, type: 'number.java' }
+		]
+	}],
+
+	[{
+		line: '0 + 0',
+		tokens: [
+			{ startIndex: 0, type: 'number.java' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.java' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.java' }
+		]
+	}],
 
 	// single line Strings
 	[{
-	line: 'String s = "I\'m a Java String";',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.java' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.java' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'delimiter.java' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'string.java' },
-		{ startIndex: 30, type: 'delimiter.java' }
-	]}],
-
-	[{
-	line: 'String s = "concatenated" + " String" ;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.java' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.java' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'delimiter.java' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'string.java' },
-		{ startIndex: 25, type: '' },
-		{ startIndex: 26, type: 'delimiter.java' },
-		{ startIndex: 27, type: '' },
-		{ startIndex: 28, type: 'string.java' },
-		{ startIndex: 37, type: '' },
-		{ startIndex: 38, type: 'delimiter.java' }
-	]}],
-
-	[{
-	line: '"quote in a string"',
-	tokens: [
-		{ startIndex: 0, type: 'string.java' }
-	]}],
-
-	[{
-	line: '"escaping \\"quotes\\" is cool"',
-	tokens: [
-		{ startIndex: 0, type: 'string.java' },
-		{ startIndex: 10, type: 'string.escape.java' },
-		{ startIndex: 12, type: 'string.java' },
-		{ startIndex: 18, type: 'string.escape.java' },
-		{ startIndex: 20, type: 'string.java' }
-	]}],
-
-	[{
-	line: '"\\"',
-	tokens: [
-		{ startIndex: 0, type: 'string.invalid.java' }
-	]}],
+		line: 'String s = "I\'m a Java String";',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.java' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.java' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.java' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'string.java' },
+			{ startIndex: 30, type: 'delimiter.java' }
+		]
+	}],
+
+	[{
+		line: 'String s = "concatenated" + " String" ;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.java' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.java' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.java' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'string.java' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'delimiter.java' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'string.java' },
+			{ startIndex: 37, type: '' },
+			{ startIndex: 38, type: 'delimiter.java' }
+		]
+	}],
+
+	[{
+		line: '"quote in a string"',
+		tokens: [
+			{ startIndex: 0, type: 'string.java' }
+		]
+	}],
+
+	[{
+		line: '"escaping \\"quotes\\" is cool"',
+		tokens: [
+			{ startIndex: 0, type: 'string.java' },
+			{ startIndex: 10, type: 'string.escape.java' },
+			{ startIndex: 12, type: 'string.java' },
+			{ startIndex: 18, type: 'string.escape.java' },
+			{ startIndex: 20, type: 'string.java' }
+		]
+	}],
+
+	[{
+		line: '"\\"',
+		tokens: [
+			{ startIndex: 0, type: 'string.invalid.java' }
+		]
+	}],
 
 	// Annotations
 	[{
-	line: '@',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}],
-
-	[{
-	line: '@Override',
-	tokens: [
-		{ startIndex: 0, type: 'annotation.java' }
-	]}],
-
-	[{
-	line: '@SuppressWarnings(value = "aString")',
-	tokens: [
-		{ startIndex: 0, type: 'annotation.java' },
-		{ startIndex: 17, type: 'delimiter.parenthesis.java' },
-		{ startIndex: 18, type: 'identifier.java' },
-		{ startIndex: 23, type: '' },
-		{ startIndex: 24, type: 'delimiter.java' },
-		{ startIndex: 25, type: '' },
-		{ startIndex: 26, type: 'string.java' },
-		{ startIndex: 35, type: 'delimiter.parenthesis.java' }
-	]}],
-
-	[{
-	line: '@ AnnotationWithKeywordAfter private',
-	tokens: [
-		{ startIndex: 0, type: 'annotation.java' },
-		{ startIndex: 28, type: '' },
-		{ startIndex: 29, type: 'keyword.private.java' }
-	]}]
+		line: '@',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}],
+
+	[{
+		line: '@Override',
+		tokens: [
+			{ startIndex: 0, type: 'annotation.java' }
+		]
+	}],
+
+	[{
+		line: '@SuppressWarnings(value = "aString")',
+		tokens: [
+			{ startIndex: 0, type: 'annotation.java' },
+			{ startIndex: 17, type: 'delimiter.parenthesis.java' },
+			{ startIndex: 18, type: 'identifier.java' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'delimiter.java' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'string.java' },
+			{ startIndex: 35, type: 'delimiter.parenthesis.java' }
+		]
+	}],
+
+	[{
+		line: '@ AnnotationWithKeywordAfter private',
+		tokens: [
+			{ startIndex: 0, type: 'annotation.java' },
+			{ startIndex: 28, type: '' },
+			{ startIndex: 29, type: 'keyword.private.java' }
+		]
+	}]
 ]);
 

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 889 - 819
test/less.test.ts


+ 59 - 54
test/lua.test.ts

@@ -5,72 +5,77 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('lua', [
 
 	// Keywords
 	[{
-	line: 'local x, y = 1, 10',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.local.lua' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'identifier.lua' },
-		{ startIndex: 7, type: 'delimiter.lua' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'identifier.lua' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'delimiter.lua' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'number.lua' },
-		{ startIndex: 14, type: 'delimiter.lua' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'number.lua' }
-	]}],
+		line: 'local x, y = 1, 10',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.local.lua' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.lua' },
+			{ startIndex: 7, type: 'delimiter.lua' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'identifier.lua' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'delimiter.lua' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'number.lua' },
+			{ startIndex: 14, type: 'delimiter.lua' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'number.lua' }
+		]
+	}],
 
 	[{
-	line: 'foo = "Hello" .. "World"; local foo = foo',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.lua' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.lua' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'string.lua' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'delimiter.lua' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'string.lua' },
-		{ startIndex: 24, type: 'delimiter.lua' },
-		{ startIndex: 25, type: '' },
-		{ startIndex: 26, type: 'keyword.local.lua' },
-		{ startIndex: 31, type: '' },
-		{ startIndex: 32, type: 'identifier.lua' },
-		{ startIndex: 35, type: '' },
-		{ startIndex: 36, type: 'delimiter.lua' },
-		{ startIndex: 37, type: '' },
-		{ startIndex: 38, type: 'identifier.lua' }
-	]}],
+		line: 'foo = "Hello" .. "World"; local foo = foo',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.lua' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.lua' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'string.lua' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'delimiter.lua' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'string.lua' },
+			{ startIndex: 24, type: 'delimiter.lua' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'keyword.local.lua' },
+			{ startIndex: 31, type: '' },
+			{ startIndex: 32, type: 'identifier.lua' },
+			{ startIndex: 35, type: '' },
+			{ startIndex: 36, type: 'delimiter.lua' },
+			{ startIndex: 37, type: '' },
+			{ startIndex: 38, type: 'identifier.lua' }
+		]
+	}],
 
 	// Comments
 	[{
-	line: '--[[ text ]] x',
-	tokens: [
-		{ startIndex: 0, type: 'comment.lua' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'identifier.lua' }
-	]}],
+		line: '--[[ text ]] x',
+		tokens: [
+			{ startIndex: 0, type: 'comment.lua' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'identifier.lua' }
+		]
+	}],
 
 	[{
-	line: '--[===[ text ]===] x',
-	tokens: [
-		{ startIndex: 0, type: 'comment.lua' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'identifier.lua' }
-	]}],
+		line: '--[===[ text ]===] x',
+		tokens: [
+			{ startIndex: 0, type: 'comment.lua' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'identifier.lua' }
+		]
+	}],
 
 	[{
-	line: '--[===[ text ]==] x',
-	tokens: [
-		{ startIndex: 0, type: 'comment.lua' }
-	]}]
+		line: '--[===[ text ]==] x',
+		tokens: [
+			{ startIndex: 0, type: 'comment.lua' }
+		]
+	}]
 ]);

+ 31 - 31
test/markdown.test.ts

@@ -5,40 +5,40 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('markdown', [
 
-    [{
-        line: '# Some header',
-        tokens: [
-            { startIndex: 0, type: 'keyword.md' }
-        ]
-    }],
+	[{
+		line: '# Some header',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.md' }
+		]
+	}],
 
-    [{
-        line: '* Some list item',
-        tokens: [
-            { startIndex: 0, type: 'keyword.md' },
-            { startIndex: 2, type: '' }
-        ]
-    }],
+	[{
+		line: '* Some list item',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.md' },
+			{ startIndex: 2, type: '' }
+		]
+	}],
 
-    [{
-        line: 'some `code`',
-        tokens: [
-            { startIndex: 0, type: '' },
-            { startIndex: 5, type: 'variable.md' }
-        ]
-    }],
+	[{
+		line: 'some `code`',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'variable.md' }
+		]
+	}],
 
-    [{
-        line: 'some ![link](http://link.com)',
-        tokens: [
-            { startIndex: 0, type: '' },
-            { startIndex: 5, type: 'string.link.md' },
-            { startIndex: 7, type: '' },
-            { startIndex: 11, type: 'string.link.md' }
-        ]
-    }]
-]);
+	[{
+		line: 'some ![link](http://link.com)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: 'string.link.md' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 11, type: 'string.link.md' }
+		]
+	}]
+]);

+ 340 - 296
test/msdax.test.ts

@@ -5,366 +5,410 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('msdax', [
 	// Comments
 	[{
-	line: '// a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.msdax' }
-	]}],
-
-	[{
-	line: '-almost a comment',
-	tokens: [
-		{ startIndex: 0, type: 'operator.msdax' },
-		{ startIndex: 1, type: 'identifier.msdax' },
-		{ startIndex: 7, type: 'white.msdax' },
-		{ startIndex: 8, type: 'identifier.msdax' },
-		{ startIndex: 9, type: 'white.msdax' },
-		{ startIndex: 10, type: 'identifier.msdax' }
-	]}],
-
-	[{
-	line: '/* a full line comment */',
-	tokens: [
-		{ startIndex: 0, type: 'comment.quote.msdax' },
-		{ startIndex: 2, type: 'comment.msdax' },
-		{ startIndex: 23, type: 'comment.quote.msdax' }
-	]}],
-
-	[{
-	line: '/* /// *** /// */',
-	tokens: [
-		{ startIndex: 0, type: 'comment.quote.msdax' },
-		{ startIndex: 2, type: 'comment.msdax' },
-		{ startIndex: 15, type: 'comment.quote.msdax' }
-	]}],
-
-	[{
-  line: 'define measure x = /* a simple comment */ 1;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.msdax' },
-		{ startIndex: 6, type: 'white.msdax' },
-		{ startIndex: 7, type: 'keyword.msdax' },
-		{ startIndex: 14, type: 'white.msdax' },
-		{ startIndex: 15, type: 'identifier.msdax' },
-		{ startIndex: 16, type: 'white.msdax' },
-		{ startIndex: 17, type: 'operator.msdax' },
-		{ startIndex: 18, type: 'white.msdax' },
-		{ startIndex: 19, type: 'comment.quote.msdax' },
-		{ startIndex: 21, type: 'comment.msdax' },
-		{ startIndex: 39, type: 'comment.quote.msdax' },
-		{ startIndex: 41, type: 'white.msdax' },
-		{ startIndex: 42, type: 'number.msdax' },
-		{ startIndex: 43, type: 'delimiter.msdax' }
-	]}],
+		line: '// a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.msdax' }
+		]
+	}],
+
+	[{
+		line: '-almost a comment',
+		tokens: [
+			{ startIndex: 0, type: 'operator.msdax' },
+			{ startIndex: 1, type: 'identifier.msdax' },
+			{ startIndex: 7, type: 'white.msdax' },
+			{ startIndex: 8, type: 'identifier.msdax' },
+			{ startIndex: 9, type: 'white.msdax' },
+			{ startIndex: 10, type: 'identifier.msdax' }
+		]
+	}],
+
+	[{
+		line: '/* a full line comment */',
+		tokens: [
+			{ startIndex: 0, type: 'comment.quote.msdax' },
+			{ startIndex: 2, type: 'comment.msdax' },
+			{ startIndex: 23, type: 'comment.quote.msdax' }
+		]
+	}],
+
+	[{
+		line: '/* /// *** /// */',
+		tokens: [
+			{ startIndex: 0, type: 'comment.quote.msdax' },
+			{ startIndex: 2, type: 'comment.msdax' },
+			{ startIndex: 15, type: 'comment.quote.msdax' }
+		]
+	}],
+
+	[{
+		line: 'define measure x = /* a simple comment */ 1;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.msdax' },
+			{ startIndex: 6, type: 'white.msdax' },
+			{ startIndex: 7, type: 'keyword.msdax' },
+			{ startIndex: 14, type: 'white.msdax' },
+			{ startIndex: 15, type: 'identifier.msdax' },
+			{ startIndex: 16, type: 'white.msdax' },
+			{ startIndex: 17, type: 'operator.msdax' },
+			{ startIndex: 18, type: 'white.msdax' },
+			{ startIndex: 19, type: 'comment.quote.msdax' },
+			{ startIndex: 21, type: 'comment.msdax' },
+			{ startIndex: 39, type: 'comment.quote.msdax' },
+			{ startIndex: 41, type: 'white.msdax' },
+			{ startIndex: 42, type: 'number.msdax' },
+			{ startIndex: 43, type: 'delimiter.msdax' }
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '123',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '123',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '-123',
-	tokens: [
-		{ startIndex: 0, type: 'operator.msdax' },
-		{ startIndex: 1, type: 'number.msdax' }
-	]}],
+		line: '-123',
+		tokens: [
+			{ startIndex: 0, type: 'operator.msdax' },
+			{ startIndex: 1, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '0xaBc123',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '0xaBc123',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '0XaBc123',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '0XaBc123',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '0x',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '0x',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '0x0',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '0x0',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '0xAB_CD',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' },
-		{ startIndex: 4, type: 'identifier.msdax' }
-	]}],
+		line: '0xAB_CD',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' },
+			{ startIndex: 4, type: 'identifier.msdax' }
+		]
+	}],
 
 	[{
-	line: '.',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.msdax' }
-	]}],
+		line: '.',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.msdax' }
+		]
+	}],
 
 	[{
-	line: '123',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '123',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '123.5678',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '123.5678',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '0.99',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '0.99',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '.99',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '.99',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '99.',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '99.',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '0.',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '0.',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '.0',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '.0',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '1E-2',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '1E-2',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '1E+2',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '1E+2',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '1E2',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '1E2',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '0.1E2',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '0.1E2',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '1.E2',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '1.E2',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	[{
-	line: '.1E2',
-	tokens: [
-		{ startIndex: 0, type: 'number.msdax' }
-	]}],
+		line: '.1E2',
+		tokens: [
+			{ startIndex: 0, type: 'number.msdax' }
+		]
+	}],
 
 	// Identifiers
 	[{
-	line: '_abc01',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.msdax' }
-	]}],
-
-	[{
-	line: 'abc01',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.msdax' }
-	]}],
-
-	[{
-	line: 'evaluate filter',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.msdax' },
-		{ startIndex: 8, type: 'white.msdax' },
-		{ startIndex: 9, type: 'keyword.msdax' }
-	]}],
-
-	[{
-	line: '[abc[[ 321 ]] xyz]',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.quote.msdax' },
-		{ startIndex: 1, type: 'identifier.msdax' },
-		{ startIndex: 17, type: 'identifier.quote.msdax' }
-	]}],
-
-	[{
-	line: '[abc',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.quote.msdax' },
-		{ startIndex: 1, type: 'identifier.msdax' }
-	]}],
-
-	[{
-	line: 'define measure \'abc\'[def]',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.msdax' },
-		{ startIndex: 6, type: 'white.msdax' },
-		{ startIndex: 7, type: 'keyword.msdax' },
-		{ startIndex: 14, type: 'white.msdax' },
-		{ startIndex: 15, type: 'identifier.quote.msdax' },
-		{ startIndex: 16, type: 'identifier.msdax' },
-		{ startIndex: 19, type: 'identifier.quote.msdax' },
-		{ startIndex: 21, type: 'identifier.msdax' },
-		{ startIndex: 24, type: 'identifier.quote.msdax' }
-	]}],
-
-	[{
-	line: 'int',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.msdax' }
-	]}],
-
-	[{
-	line: '[int]',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.quote.msdax' },
-		{ startIndex: 1, type: 'identifier.msdax' },
-		{ startIndex: 4, type: 'identifier.quote.msdax' }
-	]}],
+		line: '_abc01',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.msdax' }
+		]
+	}],
+
+	[{
+		line: 'abc01',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.msdax' }
+		]
+	}],
+
+	[{
+		line: 'evaluate filter',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.msdax' },
+			{ startIndex: 8, type: 'white.msdax' },
+			{ startIndex: 9, type: 'keyword.msdax' }
+		]
+	}],
+
+	[{
+		line: '[abc[[ 321 ]] xyz]',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.quote.msdax' },
+			{ startIndex: 1, type: 'identifier.msdax' },
+			{ startIndex: 17, type: 'identifier.quote.msdax' }
+		]
+	}],
+
+	[{
+		line: '[abc',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.quote.msdax' },
+			{ startIndex: 1, type: 'identifier.msdax' }
+		]
+	}],
+
+	[{
+		line: 'define measure \'abc\'[def]',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.msdax' },
+			{ startIndex: 6, type: 'white.msdax' },
+			{ startIndex: 7, type: 'keyword.msdax' },
+			{ startIndex: 14, type: 'white.msdax' },
+			{ startIndex: 15, type: 'identifier.quote.msdax' },
+			{ startIndex: 16, type: 'identifier.msdax' },
+			{ startIndex: 19, type: 'identifier.quote.msdax' },
+			{ startIndex: 21, type: 'identifier.msdax' },
+			{ startIndex: 24, type: 'identifier.quote.msdax' }
+		]
+	}],
+
+	[{
+		line: 'int',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.msdax' }
+		]
+	}],
+
+	[{
+		line: '[int]',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.quote.msdax' },
+			{ startIndex: 1, type: 'identifier.msdax' },
+			{ startIndex: 4, type: 'identifier.quote.msdax' }
+		]
+	}],
 
 	// Strings
 	[{
-	line: '"abc"" 321 "" xyz"',
-	tokens: [
-		{ startIndex: 0, type: 'string.msdax' }
-	]}],
+		line: '"abc"" 321 "" xyz"',
+		tokens: [
+			{ startIndex: 0, type: 'string.msdax' }
+		]
+	}],
 
 	[{
-	line: 'define var x=\"a string\"',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.msdax' },
-		{ startIndex: 6, type: 'white.msdax' },
-		{ startIndex: 7, type: 'keyword.msdax' },
-		{ startIndex: 10, type: 'white.msdax' },
-		{ startIndex: 11, type: 'identifier.msdax' },
-		{ startIndex: 12, type: 'operator.msdax' },
-		{ startIndex: 13, type: 'string.msdax' }
-	]}],
+		line: 'define var x=\"a string\"',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.msdax' },
+			{ startIndex: 6, type: 'white.msdax' },
+			{ startIndex: 7, type: 'keyword.msdax' },
+			{ startIndex: 10, type: 'white.msdax' },
+			{ startIndex: 11, type: 'identifier.msdax' },
+			{ startIndex: 12, type: 'operator.msdax' },
+			{ startIndex: 13, type: 'string.msdax' }
+		]
+	}],
 
 	[{
-	line: '"a "" string with quotes"',
-	tokens: [
-		{ startIndex: 0, type: 'string.msdax' },
-	]}],
+		line: '"a "" string with quotes"',
+		tokens: [
+			{ startIndex: 0, type: 'string.msdax' },
+		]
+	}],
 
 	[{
-	line: '"a // string with comment"',
-	tokens: [
-		{ startIndex: 0, type: 'string.msdax' },
-	]}],
+		line: '"a // string with comment"',
+		tokens: [
+			{ startIndex: 0, type: 'string.msdax' },
+		]
+	}],
 
 	[{
-	line: 'N"a unicode string"',
-	tokens: [
-		{ startIndex: 0, type: 'string.msdax' },
-	]}],
+		line: 'N"a unicode string"',
+		tokens: [
+			{ startIndex: 0, type: 'string.msdax' },
+		]
+	}],
 
 	[{
-	line: '"a endless string',
-	tokens: [
-		{ startIndex: 0, type: 'string.msdax' },
-	]}],
+		line: '"a endless string',
+		tokens: [
+			{ startIndex: 0, type: 'string.msdax' },
+		]
+	}],
 
 	// Operators
 	[{
-	line: 'define var x=1+3',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.msdax' },
-		{ startIndex: 6, type: 'white.msdax' },
-		{ startIndex: 7, type: 'keyword.msdax' },
-		{ startIndex: 10, type: 'white.msdax' },
-		{ startIndex: 11, type: 'identifier.msdax' },
-		{ startIndex: 12, type: 'operator.msdax' },
-		{ startIndex: 13, type: 'number.msdax' },
-		{ startIndex: 14, type: 'operator.msdax' },
-		{ startIndex: 15, type: 'number.msdax' }
-	]}],
-
-	[{
-	line: 'define var x=1^+abc',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.msdax' },
-		{ startIndex: 6, type: 'white.msdax' },
-		{ startIndex: 7, type: 'keyword.msdax' },
-		{ startIndex: 10, type: 'white.msdax' },
-		{ startIndex: 11, type: 'identifier.msdax' },
-		{ startIndex: 12, type: 'operator.msdax' },
-		{ startIndex: 13, type: 'number.msdax' },
-		{ startIndex: 14, type: 'operator.msdax' },
-		{ startIndex: 16, type: 'identifier.msdax' }
-	]}],
-
-  // Realistic queries and expressions
-	[{
-	line: 'EVALUATE \'Products\' ORDER BY [Product Id] DESC',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.msdax' },
-		{ startIndex: 8, type: 'white.msdax' },
-		{ startIndex: 9, type: 'identifier.quote.msdax' },
-		{ startIndex: 10, type: 'identifier.msdax' },
-		{ startIndex: 18, type: 'identifier.quote.msdax' },
-		{ startIndex: 19, type: 'white.msdax' },
-		{ startIndex: 20, type: 'keyword.msdax' },
-		{ startIndex: 25, type: 'white.msdax' },
-		{ startIndex: 26, type: 'keyword.msdax' },
-		{ startIndex: 28, type: 'white.msdax' },
-		{ startIndex: 29, type: 'identifier.quote.msdax' },
-		{ startIndex: 30, type: 'identifier.msdax' },
-		{ startIndex: 40, type: 'identifier.quote.msdax' },
-		{ startIndex: 41, type: 'white.msdax' },
-		{ startIndex: 42, type: 'keyword.msdax' }
-	]}],
-
-	[{
-	line: 'DATATABLE("Price", STRING, {{"Low"},{"Medium"}})',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.msdax' },
-		{ startIndex: 9, type: 'delimiter.parenthesis.msdax' },
-		{ startIndex: 10, type: 'string.msdax' },
-		{ startIndex: 17, type: 'delimiter.msdax' },
-		{ startIndex: 18, type: 'white.msdax' },
-		{ startIndex: 19, type: 'keyword.msdax' },
-		{ startIndex: 25, type: 'delimiter.msdax' },
-		{ startIndex: 26, type: 'white.msdax' },
-		{ startIndex: 27, type: 'delimiter.brackets.msdax' },
-		{ startIndex: 29, type: 'string.msdax' },
-		{ startIndex: 34, type: 'delimiter.brackets.msdax' },
-		{ startIndex: 35, type: 'delimiter.msdax' },
-		{ startIndex: 36, type: 'delimiter.brackets.msdax' },
-		{ startIndex: 37, type: 'string.msdax' },
-		{ startIndex: 45, type: 'delimiter.brackets.msdax' },
-		{ startIndex: 47, type: 'delimiter.parenthesis.msdax' }
-	]}]
+		line: 'define var x=1+3',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.msdax' },
+			{ startIndex: 6, type: 'white.msdax' },
+			{ startIndex: 7, type: 'keyword.msdax' },
+			{ startIndex: 10, type: 'white.msdax' },
+			{ startIndex: 11, type: 'identifier.msdax' },
+			{ startIndex: 12, type: 'operator.msdax' },
+			{ startIndex: 13, type: 'number.msdax' },
+			{ startIndex: 14, type: 'operator.msdax' },
+			{ startIndex: 15, type: 'number.msdax' }
+		]
+	}],
+
+	[{
+		line: 'define var x=1^+abc',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.msdax' },
+			{ startIndex: 6, type: 'white.msdax' },
+			{ startIndex: 7, type: 'keyword.msdax' },
+			{ startIndex: 10, type: 'white.msdax' },
+			{ startIndex: 11, type: 'identifier.msdax' },
+			{ startIndex: 12, type: 'operator.msdax' },
+			{ startIndex: 13, type: 'number.msdax' },
+			{ startIndex: 14, type: 'operator.msdax' },
+			{ startIndex: 16, type: 'identifier.msdax' }
+		]
+	}],
+
+	// Realistic queries and expressions
+	[{
+		line: 'EVALUATE \'Products\' ORDER BY [Product Id] DESC',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.msdax' },
+			{ startIndex: 8, type: 'white.msdax' },
+			{ startIndex: 9, type: 'identifier.quote.msdax' },
+			{ startIndex: 10, type: 'identifier.msdax' },
+			{ startIndex: 18, type: 'identifier.quote.msdax' },
+			{ startIndex: 19, type: 'white.msdax' },
+			{ startIndex: 20, type: 'keyword.msdax' },
+			{ startIndex: 25, type: 'white.msdax' },
+			{ startIndex: 26, type: 'keyword.msdax' },
+			{ startIndex: 28, type: 'white.msdax' },
+			{ startIndex: 29, type: 'identifier.quote.msdax' },
+			{ startIndex: 30, type: 'identifier.msdax' },
+			{ startIndex: 40, type: 'identifier.quote.msdax' },
+			{ startIndex: 41, type: 'white.msdax' },
+			{ startIndex: 42, type: 'keyword.msdax' }
+		]
+	}],
+
+	[{
+		line: 'DATATABLE("Price", STRING, {{"Low"},{"Medium"}})',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.msdax' },
+			{ startIndex: 9, type: 'delimiter.parenthesis.msdax' },
+			{ startIndex: 10, type: 'string.msdax' },
+			{ startIndex: 17, type: 'delimiter.msdax' },
+			{ startIndex: 18, type: 'white.msdax' },
+			{ startIndex: 19, type: 'keyword.msdax' },
+			{ startIndex: 25, type: 'delimiter.msdax' },
+			{ startIndex: 26, type: 'white.msdax' },
+			{ startIndex: 27, type: 'delimiter.brackets.msdax' },
+			{ startIndex: 29, type: 'string.msdax' },
+			{ startIndex: 34, type: 'delimiter.brackets.msdax' },
+			{ startIndex: 35, type: 'delimiter.msdax' },
+			{ startIndex: 36, type: 'delimiter.brackets.msdax' },
+			{ startIndex: 37, type: 'string.msdax' },
+			{ startIndex: 45, type: 'delimiter.brackets.msdax' },
+			{ startIndex: 47, type: 'delimiter.parenthesis.msdax' }
+		]
+	}]
 ]);

+ 248 - 219
test/objective-c.test.ts

@@ -5,287 +5,316 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('objective-c', [
 	// Keywords
 	[{
-	line: '-(id) initWithParams:(id<anObject>) aHandler withDeviceStateManager:(id<anotherObject>) deviceStateManager',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.parenthesis.objective-c' },
-		{ startIndex: 2, type: 'keyword.objective-c' },
-		{ startIndex: 4, type: 'delimiter.parenthesis.objective-c' },
-		{ startIndex: 5, type: 'white.objective-c' },
-		{ startIndex: 6, type: 'identifier.objective-c' },
-		{ startIndex: 20, type: 'delimiter.objective-c' },
-		{ startIndex: 21, type: 'delimiter.parenthesis.objective-c' },
-		{ startIndex: 22, type: 'keyword.objective-c' },
-		{ startIndex: 24, type: 'delimiter.angle.objective-c' },
-		{ startIndex: 25, type: 'identifier.objective-c' },
-		{ startIndex: 33, type: 'delimiter.angle.objective-c' },
-		{ startIndex: 34, type: 'delimiter.parenthesis.objective-c' },
-		{ startIndex: 35, type: 'white.objective-c' },
-		{ startIndex: 36, type: 'identifier.objective-c' },
-		{ startIndex: 44, type: 'white.objective-c' },
-		{ startIndex: 45, type: 'identifier.objective-c' },
-		{ startIndex: 67, type: 'delimiter.objective-c' },
-		{ startIndex: 68, type: 'delimiter.parenthesis.objective-c' },
-		{ startIndex: 69, type: 'keyword.objective-c' },
-		{ startIndex: 71, type: 'delimiter.angle.objective-c' },
-		{ startIndex: 72, type: 'identifier.objective-c' },
-		{ startIndex: 85, type: 'delimiter.angle.objective-c' },
-		{ startIndex: 86, type: 'delimiter.parenthesis.objective-c' },
-		{ startIndex: 87, type: 'white.objective-c' },
-		{ startIndex: 88, type: 'identifier.objective-c' }
-	]}],
+		line: '-(id) initWithParams:(id<anObject>) aHandler withDeviceStateManager:(id<anotherObject>) deviceStateManager',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.parenthesis.objective-c' },
+			{ startIndex: 2, type: 'keyword.objective-c' },
+			{ startIndex: 4, type: 'delimiter.parenthesis.objective-c' },
+			{ startIndex: 5, type: 'white.objective-c' },
+			{ startIndex: 6, type: 'identifier.objective-c' },
+			{ startIndex: 20, type: 'delimiter.objective-c' },
+			{ startIndex: 21, type: 'delimiter.parenthesis.objective-c' },
+			{ startIndex: 22, type: 'keyword.objective-c' },
+			{ startIndex: 24, type: 'delimiter.angle.objective-c' },
+			{ startIndex: 25, type: 'identifier.objective-c' },
+			{ startIndex: 33, type: 'delimiter.angle.objective-c' },
+			{ startIndex: 34, type: 'delimiter.parenthesis.objective-c' },
+			{ startIndex: 35, type: 'white.objective-c' },
+			{ startIndex: 36, type: 'identifier.objective-c' },
+			{ startIndex: 44, type: 'white.objective-c' },
+			{ startIndex: 45, type: 'identifier.objective-c' },
+			{ startIndex: 67, type: 'delimiter.objective-c' },
+			{ startIndex: 68, type: 'delimiter.parenthesis.objective-c' },
+			{ startIndex: 69, type: 'keyword.objective-c' },
+			{ startIndex: 71, type: 'delimiter.angle.objective-c' },
+			{ startIndex: 72, type: 'identifier.objective-c' },
+			{ startIndex: 85, type: 'delimiter.angle.objective-c' },
+			{ startIndex: 86, type: 'delimiter.parenthesis.objective-c' },
+			{ startIndex: 87, type: 'white.objective-c' },
+			{ startIndex: 88, type: 'identifier.objective-c' }
+		]
+	}],
 
 	// Comments - single line
 	[{
-	line: '//',
-	tokens: [
-		{ startIndex: 0, type: 'comment.objective-c' }
-	]}],
+		line: '//',
+		tokens: [
+			{ startIndex: 0, type: 'comment.objective-c' }
+		]
+	}],
 
 	[{
-	line: '    // a comment',
-	tokens: [
-		{ startIndex: 0, type: 'white.objective-c' },
-		{ startIndex: 4, type: 'comment.objective-c' }
-	]}],
+		line: '    // a comment',
+		tokens: [
+			{ startIndex: 0, type: 'white.objective-c' },
+			{ startIndex: 4, type: 'comment.objective-c' }
+		]
+	}],
 
 	[{
-	line: '// a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.objective-c' }
-	]}],
+		line: '// a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.objective-c' }
+		]
+	}],
 
 	[{
-	line: '//sticky comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.objective-c' }
-	]}],
+		line: '//sticky comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.objective-c' }
+		]
+	}],
 
 	[{
-	line: '/almost a comment',
-	tokens: [
-		{ startIndex: 0, type: 'operator.objective-c' },
-		{ startIndex: 1, type: 'identifier.objective-c' },
-		{ startIndex: 7, type: 'white.objective-c' },
-		{ startIndex: 8, type: 'identifier.objective-c' },
-		{ startIndex: 9, type: 'white.objective-c' },
-		{ startIndex: 10, type: 'identifier.objective-c' }
-	]}],
+		line: '/almost a comment',
+		tokens: [
+			{ startIndex: 0, type: 'operator.objective-c' },
+			{ startIndex: 1, type: 'identifier.objective-c' },
+			{ startIndex: 7, type: 'white.objective-c' },
+			{ startIndex: 8, type: 'identifier.objective-c' },
+			{ startIndex: 9, type: 'white.objective-c' },
+			{ startIndex: 10, type: 'identifier.objective-c' }
+		]
+	}],
 
 	[{
-	line: '1 / 2; /* comment',
-	tokens: [
-		{ startIndex: 0, type: 'number.objective-c' },
-		{ startIndex: 1, type: 'white.objective-c' },
-		{ startIndex: 2, type: 'operator.objective-c' },
-		{ startIndex: 3, type: 'white.objective-c' },
-		{ startIndex: 4, type: 'number.objective-c' },
-		{ startIndex: 5, type: 'delimiter.objective-c' },
-		{ startIndex: 6, type: 'white.objective-c' },
-		{ startIndex: 7, type: 'comment.objective-c' }
-	]}],
+		line: '1 / 2; /* comment',
+		tokens: [
+			{ startIndex: 0, type: 'number.objective-c' },
+			{ startIndex: 1, type: 'white.objective-c' },
+			{ startIndex: 2, type: 'operator.objective-c' },
+			{ startIndex: 3, type: 'white.objective-c' },
+			{ startIndex: 4, type: 'number.objective-c' },
+			{ startIndex: 5, type: 'delimiter.objective-c' },
+			{ startIndex: 6, type: 'white.objective-c' },
+			{ startIndex: 7, type: 'comment.objective-c' }
+		]
+	}],
 
 	[{
-	line: 'int x = 1; // my comment // is a nice one',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.objective-c' },
-		{ startIndex: 3, type: 'white.objective-c' },
-		{ startIndex: 4, type: 'identifier.objective-c' },
-		{ startIndex: 5, type: 'white.objective-c' },
-		{ startIndex: 6, type: 'operator.objective-c' },
-		{ startIndex: 7, type: 'white.objective-c' },
-		{ startIndex: 8, type: 'number.objective-c' },
-		{ startIndex: 9, type: 'delimiter.objective-c' },
-		{ startIndex: 10, type: 'white.objective-c' },
-		{ startIndex: 11, type: 'comment.objective-c' }
-	]}],
+		line: 'int x = 1; // my comment // is a nice one',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.objective-c' },
+			{ startIndex: 3, type: 'white.objective-c' },
+			{ startIndex: 4, type: 'identifier.objective-c' },
+			{ startIndex: 5, type: 'white.objective-c' },
+			{ startIndex: 6, type: 'operator.objective-c' },
+			{ startIndex: 7, type: 'white.objective-c' },
+			{ startIndex: 8, type: 'number.objective-c' },
+			{ startIndex: 9, type: 'delimiter.objective-c' },
+			{ startIndex: 10, type: 'white.objective-c' },
+			{ startIndex: 11, type: 'comment.objective-c' }
+		]
+	}],
 
 	// Comments - range comment, single line
 	[{
-	line: '/* a simple comment */',
-	tokens: [
-		{ startIndex: 0, type: 'comment.objective-c' }
-	]}],
+		line: '/* a simple comment */',
+		tokens: [
+			{ startIndex: 0, type: 'comment.objective-c' }
+		]
+	}],
 
 	[{
-	line: 'int x = /* embedded comment */ 1;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.objective-c' },
-		{ startIndex: 3, type: 'white.objective-c' },
-		{ startIndex: 4, type: 'identifier.objective-c' },
-		{ startIndex: 5, type: 'white.objective-c' },
-		{ startIndex: 6, type: 'operator.objective-c' },
-		{ startIndex: 7, type: 'white.objective-c' },
-		{ startIndex: 8, type: 'comment.objective-c' },
-		{ startIndex: 30, type: 'white.objective-c' },
-		{ startIndex: 31, type: 'number.objective-c' },
-		{ startIndex: 32, type: 'delimiter.objective-c' }
-	]}],
+		line: 'int x = /* embedded comment */ 1;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.objective-c' },
+			{ startIndex: 3, type: 'white.objective-c' },
+			{ startIndex: 4, type: 'identifier.objective-c' },
+			{ startIndex: 5, type: 'white.objective-c' },
+			{ startIndex: 6, type: 'operator.objective-c' },
+			{ startIndex: 7, type: 'white.objective-c' },
+			{ startIndex: 8, type: 'comment.objective-c' },
+			{ startIndex: 30, type: 'white.objective-c' },
+			{ startIndex: 31, type: 'number.objective-c' },
+			{ startIndex: 32, type: 'delimiter.objective-c' }
+		]
+	}],
 
 	[{
-	line: 'int x = /* comment and syntax error*/ 1; */',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.objective-c' },
-		{ startIndex: 3, type: 'white.objective-c' },
-		{ startIndex: 4, type: 'identifier.objective-c' },
-		{ startIndex: 5, type: 'white.objective-c' },
-		{ startIndex: 6, type: 'operator.objective-c' },
-		{ startIndex: 7, type: 'white.objective-c' },
-		{ startIndex: 8, type: 'comment.objective-c' },
-		{ startIndex: 37, type: 'white.objective-c' },
-		{ startIndex: 38, type: 'number.objective-c' },
-		{ startIndex: 39, type: 'delimiter.objective-c' },
-		{ startIndex: 40, type: 'white.objective-c' },
-		{ startIndex: 41, type: 'operator.objective-c' }
-	]}],
+		line: 'int x = /* comment and syntax error*/ 1; */',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.objective-c' },
+			{ startIndex: 3, type: 'white.objective-c' },
+			{ startIndex: 4, type: 'identifier.objective-c' },
+			{ startIndex: 5, type: 'white.objective-c' },
+			{ startIndex: 6, type: 'operator.objective-c' },
+			{ startIndex: 7, type: 'white.objective-c' },
+			{ startIndex: 8, type: 'comment.objective-c' },
+			{ startIndex: 37, type: 'white.objective-c' },
+			{ startIndex: 38, type: 'number.objective-c' },
+			{ startIndex: 39, type: 'delimiter.objective-c' },
+			{ startIndex: 40, type: 'white.objective-c' },
+			{ startIndex: 41, type: 'operator.objective-c' }
+		]
+	}],
 
 	[{
-	line: 'x = /**/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.objective-c' },
-		{ startIndex: 1, type: 'white.objective-c' },
-		{ startIndex: 2, type: 'operator.objective-c' },
-		{ startIndex: 3, type: 'white.objective-c' },
-		{ startIndex: 4, type: 'comment.objective-c' },
-		{ startIndex: 8, type: 'delimiter.objective-c' }
-	]}],
+		line: 'x = /**/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.objective-c' },
+			{ startIndex: 1, type: 'white.objective-c' },
+			{ startIndex: 2, type: 'operator.objective-c' },
+			{ startIndex: 3, type: 'white.objective-c' },
+			{ startIndex: 4, type: 'comment.objective-c' },
+			{ startIndex: 8, type: 'delimiter.objective-c' }
+		]
+	}],
 
 	[{
-	line: 'x = /*/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.objective-c' },
-		{ startIndex: 1, type: 'white.objective-c' },
-		{ startIndex: 2, type: 'operator.objective-c' },
-		{ startIndex: 3, type: 'white.objective-c' },
-		{ startIndex: 4, type: 'comment.objective-c' }
-	]}],
+		line: 'x = /*/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.objective-c' },
+			{ startIndex: 1, type: 'white.objective-c' },
+			{ startIndex: 2, type: 'operator.objective-c' },
+			{ startIndex: 3, type: 'white.objective-c' },
+			{ startIndex: 4, type: 'comment.objective-c' }
+		]
+	}],
 
 	// Non-Alpha Keywords
 	[{
-	line: '#import <GTLT.h>',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.objective-c' },
-		{ startIndex: 7, type: 'white.objective-c' },
-		{ startIndex: 8, type: 'delimiter.angle.objective-c' },
-		{ startIndex: 9, type: 'identifier.objective-c' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'identifier.objective-c' },
-		{ startIndex: 15, type: 'delimiter.angle.objective-c' }
-	]}],
+		line: '#import <GTLT.h>',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.objective-c' },
+			{ startIndex: 7, type: 'white.objective-c' },
+			{ startIndex: 8, type: 'delimiter.angle.objective-c' },
+			{ startIndex: 9, type: 'identifier.objective-c' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'identifier.objective-c' },
+			{ startIndex: 15, type: 'delimiter.angle.objective-c' }
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '0 ',
-	tokens: [
-		{ startIndex: 0, type: 'number.objective-c' },
-		{ startIndex: 1, type: 'white.objective-c' }
-	]}],
+		line: '0 ',
+		tokens: [
+			{ startIndex: 0, type: 'number.objective-c' },
+			{ startIndex: 1, type: 'white.objective-c' }
+		]
+	}],
 
 	[{
-	line: '0x ',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.objective-c' },
-		{ startIndex: 2, type: 'white.objective-c' }
-	]}],
+		line: '0x ',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.objective-c' },
+			{ startIndex: 2, type: 'white.objective-c' }
+		]
+	}],
 
 	[{
-	line: '0x123 ',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.objective-c' },
-		{ startIndex: 5, type: 'white.objective-c' }
-	]}],
+		line: '0x123 ',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.objective-c' },
+			{ startIndex: 5, type: 'white.objective-c' }
+		]
+	}],
 
 	[{
-	line: '23.5 ',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.objective-c' },
-		{ startIndex: 4, type: 'white.objective-c' }
-	]}],
+		line: '23.5 ',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.objective-c' },
+			{ startIndex: 4, type: 'white.objective-c' }
+		]
+	}],
 
 	[{
-	line: '23.5e3 ',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.objective-c' },
-		{ startIndex: 6, type: 'white.objective-c' }
-	]}],
+		line: '23.5e3 ',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.objective-c' },
+			{ startIndex: 6, type: 'white.objective-c' }
+		]
+	}],
 
 	[{
-	line: '23.5E3 ',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.objective-c' },
-		{ startIndex: 6, type: 'white.objective-c' }
-	]}],
+		line: '23.5E3 ',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.objective-c' },
+			{ startIndex: 6, type: 'white.objective-c' }
+		]
+	}],
 
 	[{
-	line: '23.5F ',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.objective-c' },
-		{ startIndex: 5, type: 'white.objective-c' }
-	]}],
+		line: '23.5F ',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.objective-c' },
+			{ startIndex: 5, type: 'white.objective-c' }
+		]
+	}],
 
 	[{
-	line: '23.5f ',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.objective-c' },
-		{ startIndex: 5, type: 'white.objective-c' }
-	]}],
+		line: '23.5f ',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.objective-c' },
+			{ startIndex: 5, type: 'white.objective-c' }
+		]
+	}],
 
 	[{
-	line: '1.72E3F ',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.objective-c' },
-		{ startIndex: 7, type: 'white.objective-c' }
-	]}],
+		line: '1.72E3F ',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.objective-c' },
+			{ startIndex: 7, type: 'white.objective-c' }
+		]
+	}],
 
 	[{
-	line: '1.72E3f ',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.objective-c' },
-		{ startIndex: 7, type: 'white.objective-c' }
-	]}],
+		line: '1.72E3f ',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.objective-c' },
+			{ startIndex: 7, type: 'white.objective-c' }
+		]
+	}],
 
 	[{
-	line: '1.72e3F ',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.objective-c' },
-		{ startIndex: 7, type: 'white.objective-c' }
-	]}],
+		line: '1.72e3F ',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.objective-c' },
+			{ startIndex: 7, type: 'white.objective-c' }
+		]
+	}],
 
 	[{
-	line: '1.72e3f ',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.objective-c' },
-		{ startIndex: 7, type: 'white.objective-c' }
-	]}],
+		line: '1.72e3f ',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.objective-c' },
+			{ startIndex: 7, type: 'white.objective-c' }
+		]
+	}],
 
 	[{
-	line: '0+0',
-	tokens: [
-		{ startIndex: 0, type: 'number.objective-c' },
-		{ startIndex: 1, type: 'operator.objective-c' },
-		{ startIndex: 2, type: 'number.objective-c' }
-	]}],
+		line: '0+0',
+		tokens: [
+			{ startIndex: 0, type: 'number.objective-c' },
+			{ startIndex: 1, type: 'operator.objective-c' },
+			{ startIndex: 2, type: 'number.objective-c' }
+		]
+	}],
 
 	[{
-	line: '100+10',
-	tokens: [
-		{ startIndex: 0, type: 'number.objective-c' },
-		{ startIndex: 3, type: 'operator.objective-c' },
-		{ startIndex: 4, type: 'number.objective-c' }
-	]}],
+		line: '100+10',
+		tokens: [
+			{ startIndex: 0, type: 'number.objective-c' },
+			{ startIndex: 3, type: 'operator.objective-c' },
+			{ startIndex: 4, type: 'number.objective-c' }
+		]
+	}],
 
 	[{
-	line: '0 + 0',
-	tokens: [
-		{ startIndex: 0, type: 'number.objective-c' },
-		{ startIndex: 1, type: 'white.objective-c' },
-		{ startIndex: 2, type: 'operator.objective-c' },
-		{ startIndex: 3, type: 'white.objective-c' },
-		{ startIndex: 4, type: 'number.objective-c' }
-	]}]
+		line: '0 + 0',
+		tokens: [
+			{ startIndex: 0, type: 'number.objective-c' },
+			{ startIndex: 1, type: 'white.objective-c' },
+			{ startIndex: 2, type: 'operator.objective-c' },
+			{ startIndex: 3, type: 'white.objective-c' },
+			{ startIndex: 4, type: 'number.objective-c' }
+		]
+	}]
 ]);

+ 1966 - 1803
test/php.test.ts

@@ -5,1880 +5,2043 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
-import {htmlTokenTypes} from '../src/php';
+import { testTokenization } from './testRunner';
+import { htmlTokenTypes } from '../src/php';
 
 testTokenization(['php', 'css'], [
 	// Bug 13596:[ErrorTelemetry] Stream did not advance while tokenizing. Mode id is php (stuck)
 	// We're testing the fact that tokenize does not throw
 	[
-	{ line: '<?php', tokens: [{ startIndex:0, type: "metatag.php" }]},
-	{ line: '"', tokens: [{ startIndex:0, type: "string.php" }]},
-	{ line: '\\', tokens: [{startIndex:0, type:"" }]}
+		{ line: '<?php', tokens: [{ startIndex: 0, type: "metatag.php" }] },
+		{ line: '"', tokens: [{ startIndex: 0, type: "string.php" }] },
+		{ line: '\\', tokens: [{ startIndex: 0, type: "" }] }
 	],
 
 	// Blocks
 	[{
-	line: '<?php',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' }
-	]}],
+		line: '<?php',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' }
+		]
+	}],
 
 	[{
-	line: '<?php ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'metatag.php' }
-	]}],
+		line: '<?php ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'metatag.php' }
+		]
+	}],
 
 	[{
-	line: '<?=',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' }
-	]}],
+		line: '<?=',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' }
+		]
+	}],
 
 	[{
-	line: '<?php /* comment */ ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'comment.php' },
-		{ startIndex:19, type: '' },
-		{ startIndex:20, type: 'metatag.php' }
-	]}],
+		line: '<?php /* comment */ ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.php' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'metatag.php' }
+		]
+	}],
 
 	// Variables
 	[{
-	line: '<?php $abc = 5; ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'delimiter.php' },
-		{ startIndex:12, type: '' },
-		{ startIndex:13, type: 'number.php' },
-		{ startIndex:14, type: 'delimiter.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $a = "chris"; ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'delimiter.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'string.php' },
-		{ startIndex:18, type: 'delimiter.php' },
-		{ startIndex:19, type: '' },
-		{ startIndex:20, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $myVar = -10; ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:12, type: '' },
-		{ startIndex:13, type: 'delimiter.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'delimiter.php' },
-		{ startIndex:16, type: 'number.php' },
-		{ startIndex:18, type: 'delimiter.php' },
-		{ startIndex:19, type: '' },
-		{ startIndex:20, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $myVar = 5 + (10 * 2); ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:12, type: '' },
-		{ startIndex:13, type: 'delimiter.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'number.php' },
-		{ startIndex:16, type: '' },
-		{ startIndex:17, type: 'delimiter.php' },
-		{ startIndex:18, type: '' },
-		{ startIndex:19, type: 'delimiter.parenthesis.php' },
-		{ startIndex:20, type: 'number.php' },
-		{ startIndex:22, type: '' },
-		{ startIndex:23, type: 'delimiter.php' },
-		{ startIndex:24, type: '' },
-		{ startIndex:25, type: 'number.php' },
-		{ startIndex:26, type: 'delimiter.parenthesis.php' },
-		{ startIndex:27, type: 'delimiter.php' },
-		{ startIndex:28, type: '' },
-		{ startIndex:29, type: 'metatag.php' }
-	]}],
+		line: '<?php $abc = 5; ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'delimiter.php' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'number.php' },
+			{ startIndex: 14, type: 'delimiter.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $a = "chris"; ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'string.php' },
+			{ startIndex: 18, type: 'delimiter.php' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $myVar = -10; ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'delimiter.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'delimiter.php' },
+			{ startIndex: 16, type: 'number.php' },
+			{ startIndex: 18, type: 'delimiter.php' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $myVar = 5 + (10 * 2); ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'delimiter.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'number.php' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'delimiter.php' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'delimiter.parenthesis.php' },
+			{ startIndex: 20, type: 'number.php' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'delimiter.php' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'number.php' },
+			{ startIndex: 26, type: 'delimiter.parenthesis.php' },
+			{ startIndex: 27, type: 'delimiter.php' },
+			{ startIndex: 28, type: '' },
+			{ startIndex: 29, type: 'metatag.php' }
+		]
+	}],
 
 	// Keywords
 	[{
-	line: '<?php function myFunc() { } ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'identifier.php' },
-		{ startIndex:21, type: 'delimiter.parenthesis.php' },
-		{ startIndex:23, type: '' },
-		{ startIndex:24, type: 'delimiter.bracket.php' },
-		{ startIndex:25, type: '' },
-		{ startIndex:26, type: 'delimiter.bracket.php' },
-		{ startIndex:27, type: '' },
-		{ startIndex:28, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php function ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php if ($start > 52) { $start = 0; } ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'delimiter.parenthesis.php' },
-		{ startIndex:10, type: 'variable.php' },
-		{ startIndex:16, type: '' },
-		{ startIndex:17, type: 'delimiter.php' },
-		{ startIndex:18, type: '' },
-		{ startIndex:19, type: 'number.php' },
-		{ startIndex:21, type: 'delimiter.parenthesis.php' },
-		{ startIndex:22, type: '' },
-		{ startIndex:23, type: 'delimiter.bracket.php' },
-		{ startIndex:24, type: '' },
-		{ startIndex:25, type: 'variable.php' },
-		{ startIndex:31, type: '' },
-		{ startIndex:32, type: 'delimiter.php' },
-		{ startIndex:33, type: '' },
-		{ startIndex:34, type: 'number.php' },
-		{ startIndex:35, type: 'delimiter.php' },
-		{ startIndex:36, type: '' },
-		{ startIndex:37, type: 'delimiter.bracket.php' },
-		{ startIndex:38, type: '' },
-		{ startIndex:39, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php if (true) { $start = 0; } ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'delimiter.parenthesis.php' },
-		{ startIndex:10, type: 'keyword.php' },
-		{ startIndex:14, type: 'delimiter.parenthesis.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'delimiter.bracket.php' },
-		{ startIndex:17, type: '' },
-		{ startIndex:18, type: 'variable.php' },
-		{ startIndex:24, type: '' },
-		{ startIndex:25, type: 'delimiter.php' },
-		{ startIndex:26, type: '' },
-		{ startIndex:27, type: 'number.php' },
-		{ startIndex:28, type: 'delimiter.php' },
-		{ startIndex:29, type: '' },
-		{ startIndex:30, type: 'delimiter.bracket.php' },
-		{ startIndex:31, type: '' },
-		{ startIndex:32, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php abstract ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php and ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:9, type: '' },
-		{ startIndex:10, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php array ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php as ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php break ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php case ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php catch ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php cfunction ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php class ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php clone ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php const ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php continue ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php declare ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php default ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php do ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php else ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php elseif ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:12, type: '' },
-		{ startIndex:13, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php enddeclare ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:16, type: '' },
-		{ startIndex:17, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php endfor ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:12, type: '' },
-		{ startIndex:13, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php endforeach ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:16, type: '' },
-		{ startIndex:17, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php endif ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php endswitch ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php endwhile ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php extends ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php false ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php final ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php for ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:9, type: '' },
-		{ startIndex:10, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php foreach ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php function ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php global ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:12, type: '' },
-		{ startIndex:13, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php goto ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php if ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php implements ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:16, type: '' },
-		{ startIndex:17, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php interface ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php instanceof ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:16, type: '' },
-		{ startIndex:17, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php namespace ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php new ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:9, type: '' },
-		{ startIndex:10, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php null ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php object ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:12, type: '' },
-		{ startIndex:13, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php old_function ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:18, type: '' },
-		{ startIndex:19, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php or ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php private ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php protected ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php public ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:12, type: '' },
-		{ startIndex:13, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php resource ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php static ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:12, type: '' },
-		{ startIndex:13, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php switch ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:12, type: '' },
-		{ startIndex:13, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php throw ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php try ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:9, type: '' },
-		{ startIndex:10, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php true ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php use ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:9, type: '' },
-		{ startIndex:10, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php var ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:9, type: '' },
-		{ startIndex:10, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php while ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php xor ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:9, type: '' },
-		{ startIndex:10, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php die ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:9, type: '' },
-		{ startIndex:10, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php echo ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php empty ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php exit ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php eval ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php include ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php include_once ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:18, type: '' },
-		{ startIndex:19, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php isset ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php list ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php require ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php require_once ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:18, type: '' },
-		{ startIndex:19, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php return ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:12, type: '' },
-		{ startIndex:13, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php print ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php unset ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php __construct ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:17, type: '' },
-		{ startIndex:18, type: 'metatag.php' }
-	]}],
+		line: '<?php function myFunc() { } ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'identifier.php' },
+			{ startIndex: 21, type: 'delimiter.parenthesis.php' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'delimiter.bracket.php' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'delimiter.bracket.php' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php function ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php if ($start > 52) { $start = 0; } ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.parenthesis.php' },
+			{ startIndex: 10, type: 'variable.php' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'delimiter.php' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'number.php' },
+			{ startIndex: 21, type: 'delimiter.parenthesis.php' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'delimiter.bracket.php' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'variable.php' },
+			{ startIndex: 31, type: '' },
+			{ startIndex: 32, type: 'delimiter.php' },
+			{ startIndex: 33, type: '' },
+			{ startIndex: 34, type: 'number.php' },
+			{ startIndex: 35, type: 'delimiter.php' },
+			{ startIndex: 36, type: '' },
+			{ startIndex: 37, type: 'delimiter.bracket.php' },
+			{ startIndex: 38, type: '' },
+			{ startIndex: 39, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php if (true) { $start = 0; } ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.parenthesis.php' },
+			{ startIndex: 10, type: 'keyword.php' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'delimiter.bracket.php' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'variable.php' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'delimiter.php' },
+			{ startIndex: 26, type: '' },
+			{ startIndex: 27, type: 'number.php' },
+			{ startIndex: 28, type: 'delimiter.php' },
+			{ startIndex: 29, type: '' },
+			{ startIndex: 30, type: 'delimiter.bracket.php' },
+			{ startIndex: 31, type: '' },
+			{ startIndex: 32, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php abstract ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php and ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php array ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php as ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php break ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php case ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php catch ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php cfunction ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php class ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php clone ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php const ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php continue ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php declare ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php default ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php do ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php else ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php elseif ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php enddeclare ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php endfor ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php endforeach ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php endif ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php endswitch ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php endwhile ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php extends ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php false ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php final ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php for ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php foreach ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php function ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php global ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php goto ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php if ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php implements ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php interface ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php instanceof ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php namespace ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php new ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php null ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php object ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php old_function ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php or ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php private ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php protected ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php public ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php resource ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php static ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php switch ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php throw ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php try ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php true ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php use ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php var ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php while ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php xor ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php die ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php echo ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php empty ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php exit ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php eval ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php include ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php include_once ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php isset ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php list ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php require ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php require_once ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php return ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php print ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php unset ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php __construct ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'metatag.php' }
+		]
+	}],
 
 	// Compile Time Constants
 	[{
-	line: '<?php __FILE__ ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'constant.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $myscript = __FILE__; ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'delimiter.php' },
-		{ startIndex:17, type: '' },
-		{ startIndex:18, type: 'constant.php' },
-		{ startIndex:26, type: 'delimiter.php' },
-		{ startIndex:27, type: '' },
-		{ startIndex:28, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php __CLASS__ ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'constant.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php __DIR__ ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'constant.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php __LINE__ ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'constant.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php __NAMESPACE__ ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'constant.php' },
-		{ startIndex:19, type: '' },
-		{ startIndex:20, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php __METHOD__ ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'constant.php' },
-		{ startIndex:16, type: '' },
-		{ startIndex:17, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php __FUNCTION__ ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'constant.php' },
-		{ startIndex:18, type: '' },
-		{ startIndex:19, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php __TRAIT__ ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'constant.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'metatag.php' }
-	]}],
+		line: '<?php __FILE__ ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'constant.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $myscript = __FILE__; ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'delimiter.php' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'constant.php' },
+			{ startIndex: 26, type: 'delimiter.php' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php __CLASS__ ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'constant.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php __DIR__ ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'constant.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php __LINE__ ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'constant.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php __NAMESPACE__ ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'constant.php' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php __METHOD__ ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'constant.php' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php __FUNCTION__ ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'constant.php' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php __TRAIT__ ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'constant.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'metatag.php' }
+		]
+	}],
 
 	// Predefined Variables
 	[{
-	line: '<?php $_ENV ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php echo $_ENV; ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'keyword.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'variable.predefined.php' },
-		{ startIndex:16, type: 'delimiter.php' },
-		{ startIndex:17, type: '' },
-		{ startIndex:18, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $GLOBALS ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $_SERVER ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $_GET ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $_POST ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:12, type: '' },
-		{ startIndex:13, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $_FILES ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $_REQUEST ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $_SESSION ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $_ENV ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $_COOKIE ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:14, type: '' },
-		{ startIndex:15, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $php_errormsg ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:19, type: '' },
-		{ startIndex:20, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $HTTP_RAW_POST_DATA ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:25, type: '' },
-		{ startIndex:26, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $http_response_header ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:27, type: '' },
-		{ startIndex:28, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $argc ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $argv ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.predefined.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
+		line: '<?php $_ENV ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php echo $_ENV; ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'variable.predefined.php' },
+			{ startIndex: 16, type: 'delimiter.php' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $GLOBALS ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $_SERVER ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $_GET ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $_POST ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $_FILES ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $_REQUEST ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $_SESSION ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $_ENV ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $_COOKIE ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $php_errormsg ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $HTTP_RAW_POST_DATA ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $http_response_header ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $argc ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $argv ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.predefined.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
 
 	// Comments - single line
 	[{
-	line: '<?php // a',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'comment.php' }
-	]}],
-
-	[{
-	line: '<?php / / / not a comment',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'delimiter.php' },
-		{ startIndex:7, type: '' },
-		{ startIndex:8, type: 'delimiter.php' },
-		{ startIndex:9, type: '' },
-		{ startIndex:10, type: 'delimiter.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'identifier.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'identifier.php' },
-		{ startIndex:17, type: '' },
-		{ startIndex:18, type: 'identifier.php' },
-	]}],
-
-	[{
-	line: '<?php    // a comment',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:9, type: 'comment.php' }
-	]}],
-
-	[{
-	line: '<?php // a comment',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'comment.php' }
-	]}],
-
-	[{
-	line: '<?php //sticky comment',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'comment.php' }
-	]}],
-
-	[{
-	line: '<?php /almost a comment',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'delimiter.php' },
-		{ startIndex:7, type: 'identifier.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'identifier.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'identifier.php' },
-	]}],
-
-	[{
-	line: '<?php $x = 1; // my comment // is a nice one',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'delimiter.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'number.php' },
-		{ startIndex:12, type: 'delimiter.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'comment.php' }
-	]}],
+		line: '<?php // a',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.php' }
+		]
+	}],
+
+	[{
+		line: '<?php / / / not a comment',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.php' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.php' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'delimiter.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'identifier.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'identifier.php' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'identifier.php' },
+		]
+	}],
+
+	[{
+		line: '<?php    // a comment',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 9, type: 'comment.php' }
+		]
+	}],
+
+	[{
+		line: '<?php // a comment',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.php' }
+		]
+	}],
+
+	[{
+		line: '<?php //sticky comment',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.php' }
+		]
+	}],
+
+	[{
+		line: '<?php /almost a comment',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.php' },
+			{ startIndex: 7, type: 'identifier.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'identifier.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'identifier.php' },
+		]
+	}],
+
+	[{
+		line: '<?php $x = 1; // my comment // is a nice one',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'number.php' },
+			{ startIndex: 12, type: 'delimiter.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'comment.php' }
+		]
+	}],
 
 	// Comments - range comment, single line
 	[{
-	line: '<?php /* a simple comment */ ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'comment.php' },
-		{ startIndex:28, type: '' },
-		{ startIndex:29, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $x = /* a simple comment */ 1; ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'delimiter.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'comment.php' },
-		{ startIndex:33, type: '' },
-		{ startIndex:34, type: 'number.php' },
-		{ startIndex:35, type: 'delimiter.php' },
-		{ startIndex:36, type: '' },
-		{ startIndex:37, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $x = /* comment */ 1; */ ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'delimiter.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'comment.php' },
-		{ startIndex:24, type: '' },
-		{ startIndex:25, type: 'number.php' },
-		{ startIndex:26, type: 'delimiter.php' },
-		{ startIndex:27, type: '' },
-		{ startIndex:28, type: 'delimiter.php' },
-		{ startIndex:30, type: '' },
-		{ startIndex:31, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $x = /**/; ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'delimiter.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'comment.php' },
-		{ startIndex:15, type: 'delimiter.php' },
-		{ startIndex:16, type: '' },
-		{ startIndex:17, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $x = /*/;',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'delimiter.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'comment.php' }
-	]}],
+		line: '<?php /* a simple comment */ ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.php' },
+			{ startIndex: 28, type: '' },
+			{ startIndex: 29, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $x = /* a simple comment */ 1; ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'comment.php' },
+			{ startIndex: 33, type: '' },
+			{ startIndex: 34, type: 'number.php' },
+			{ startIndex: 35, type: 'delimiter.php' },
+			{ startIndex: 36, type: '' },
+			{ startIndex: 37, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $x = /* comment */ 1; */ ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'comment.php' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'number.php' },
+			{ startIndex: 26, type: 'delimiter.php' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'delimiter.php' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $x = /**/; ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'comment.php' },
+			{ startIndex: 15, type: 'delimiter.php' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $x = /*/;',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'comment.php' }
+		]
+	}],
 
 	// Comments - range comment, multi lines
 	[{
-	line: '<?php /* a multiline comment',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'comment.php' }
-	]}, {
-	line: 'can actually span',
-	tokens: [
-		{ startIndex:0, type: 'comment.php' }
-	]}, {
-	line: 'multiple lines */',
-	tokens: [
-		{ startIndex:0, type: 'comment.php' }
-	]}],
-
-	[{
-	line: '<?php $x = /* start a comment',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'delimiter.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'comment.php' }
-	]}, {
-	line: ' a ',
-	tokens: [
-		{ startIndex:0, type: 'comment.php' }
-	]}, {
-	line: 'and end it */ var a = 2;',
-	tokens: [
-		{ startIndex:0, type: 'comment.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'keyword.php' },
-		{ startIndex:17, type: '' },
-		{ startIndex:18, type: 'identifier.php' },
-		{ startIndex:19, type: '' },
-		{ startIndex:20, type: 'delimiter.php' },
-		{ startIndex:21, type: '' },
-		{ startIndex:22, type: 'number.php' },
-		{ startIndex:23, type: 'delimiter.php' }
-	]}],
+		line: '<?php /* a multiline comment',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.php' }
+		]
+	}, {
+		line: 'can actually span',
+		tokens: [
+			{ startIndex: 0, type: 'comment.php' }
+		]
+	}, {
+		line: 'multiple lines */',
+		tokens: [
+			{ startIndex: 0, type: 'comment.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $x = /* start a comment',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'comment.php' }
+		]
+	}, {
+		line: ' a ',
+		tokens: [
+			{ startIndex: 0, type: 'comment.php' }
+		]
+	}, {
+		line: 'and end it */ var a = 2;',
+		tokens: [
+			{ startIndex: 0, type: 'comment.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'keyword.php' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'identifier.php' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'delimiter.php' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'number.php' },
+			{ startIndex: 23, type: 'delimiter.php' }
+		]
+	}],
 
 	// Strings
 	[{
-	line: '<?php $a = \'a\'; ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'delimiter.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'string.php' },
-		{ startIndex:14, type: 'delimiter.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php \'use strict\'; ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'string.php' },
-		{ startIndex:18, type: 'delimiter.php' },
-		{ startIndex:19, type: '' },
-		{ startIndex:20, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php $b = $a + " \'cool\'  " ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'delimiter.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'variable.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'delimiter.php' },
-		{ startIndex:15, type: '' },
-		{ startIndex:16, type: 'string.php' },
-		{ startIndex:27, type: '' },
-		{ startIndex:28, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php \'\'\'',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'string.php' },
-	]}],
-
-	[{
-	line: '<?php "multiline',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'string.php' }
-	]}, {
-	line: 'strings";',
-	tokens: [
-		{ startIndex:0, type: 'string.php' },
-		{ startIndex:8, type: 'delimiter.php' }
-	]}],
+		line: '<?php $a = \'a\'; ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'string.php' },
+			{ startIndex: 14, type: 'delimiter.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php \'use strict\'; ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'string.php' },
+			{ startIndex: 18, type: 'delimiter.php' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $b = $a + " \'cool\'  " ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'variable.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'delimiter.php' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'string.php' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php \'\'\'',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'string.php' },
+		]
+	}],
+
+	[{
+		line: '<?php "multiline',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'string.php' }
+		]
+	}, {
+		line: 'strings";',
+		tokens: [
+			{ startIndex: 0, type: 'string.php' },
+			{ startIndex: 8, type: 'delimiter.php' }
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '<?php 0 ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'number.php' },
-		{ startIndex:7, type: '' },
-		{ startIndex:8, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php 0+0 ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'number.php' },
-		{ startIndex:7, type: 'delimiter.php' },
-		{ startIndex:8, type: 'number.php' },
-		{ startIndex:9, type: '' },
-		{ startIndex:10, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php 100+10 ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'number.php' },
-		{ startIndex:9, type: 'delimiter.php' },
-		{ startIndex:10, type: 'number.php' },
-		{ startIndex:12, type: '' },
-		{ startIndex:13, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php 0 + 0 ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'number.php' },
-		{ startIndex:7, type: '' },
-		{ startIndex:8, type: 'delimiter.php' },
-		{ startIndex:9, type: '' },
-		{ startIndex:10, type: 'number.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php 0123 ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'number.octal.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php 01239 ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'number.octal.php' },
-		{ startIndex:10, type: 'number.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php 0x ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'number.php' },
-		{ startIndex:7, type: 'identifier.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php 0x123 ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'number.hex.php' },
-		{ startIndex:11, type: '' },
-		{ startIndex:12, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php 0b1 ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'number.binary.php' },
-		{ startIndex:9, type: '' },
-		{ startIndex:10, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php { } ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'delimiter.bracket.php' },
-		{ startIndex:7, type: '' },
-		{ startIndex:8, type: 'delimiter.bracket.php' },
-		{ startIndex:9, type: '' },
-		{ startIndex:10, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php [1,2,3] ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'delimiter.array.php' },
-		{ startIndex:7, type: 'number.php' },
-		{ startIndex:8, type: 'delimiter.php' },
-		{ startIndex:9, type: 'number.php' },
-		{ startIndex:10, type: 'delimiter.php' },
-		{ startIndex:11, type: 'number.php' },
-		{ startIndex:12, type: 'delimiter.array.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php foo(123);',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'identifier.php' },
-		{ startIndex:9, type: 'delimiter.parenthesis.php' },
-		{ startIndex:10, type: 'number.php' },
-		{ startIndex:13, type: 'delimiter.parenthesis.php' },
-		{ startIndex:14, type: 'delimiter.php' }
-	]}],
-
-	[{
-	line: '<?php $x = "[{()}]" ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'delimiter.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'string.php' },
-		{ startIndex:19, type: '' },
-		{ startIndex:20, type: 'metatag.php' }
-	]}],
+		line: '<?php 0 ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'number.php' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php 0+0 ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'number.php' },
+			{ startIndex: 7, type: 'delimiter.php' },
+			{ startIndex: 8, type: 'number.php' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php 100+10 ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'number.php' },
+			{ startIndex: 9, type: 'delimiter.php' },
+			{ startIndex: 10, type: 'number.php' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php 0 + 0 ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'number.php' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.php' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'number.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php 0123 ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'number.octal.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php 01239 ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'number.octal.php' },
+			{ startIndex: 10, type: 'number.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php 0x ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'number.php' },
+			{ startIndex: 7, type: 'identifier.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php 0x123 ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'number.hex.php' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php 0b1 ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'number.binary.php' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php { } ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.bracket.php' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.bracket.php' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php [1,2,3] ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.array.php' },
+			{ startIndex: 7, type: 'number.php' },
+			{ startIndex: 8, type: 'delimiter.php' },
+			{ startIndex: 9, type: 'number.php' },
+			{ startIndex: 10, type: 'delimiter.php' },
+			{ startIndex: 11, type: 'number.php' },
+			{ startIndex: 12, type: 'delimiter.array.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php foo(123);',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.php' },
+			{ startIndex: 9, type: 'delimiter.parenthesis.php' },
+			{ startIndex: 10, type: 'number.php' },
+			{ startIndex: 13, type: 'delimiter.parenthesis.php' },
+			{ startIndex: 14, type: 'delimiter.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $x = "[{()}]" ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'string.php' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'metatag.php' }
+		]
+	}],
 
 	// Comments - comment with sharp
 	[{
-	line: '<?php # a',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'comment.php' }
-	]}],
-
-	[{
-	line: '<?php ## a',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'comment.php' }
-	]}],
-
-	[{
-	line: '<?php    # a comment',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:9, type: 'comment.php' }
-	]}],
-
-	[{
-	line: '<?php #sticky comment',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'comment.php' }
-	]}],
-
-	[{
-	line: '<?php $x = 1; # my comment // is a nice one',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'variable.php' },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'delimiter.php' },
-		{ startIndex:10, type: '' },
-		{ startIndex:11, type: 'number.php' },
-		{ startIndex:12, type: 'delimiter.php' },
-		{ startIndex:13, type: '' },
-		{ startIndex:14, type: 'comment.php' }
-	]}],
-
-	[{
-	line: '<?php # comment?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'comment.php' },
-		{ startIndex:15, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<?php # comment? ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'comment.php' },
-		{ startIndex:17, type: 'metatag.php' }
-	]}],
+		line: '<?php # a',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.php' }
+		]
+	}],
+
+	[{
+		line: '<?php ## a',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.php' }
+		]
+	}],
+
+	[{
+		line: '<?php    # a comment',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 9, type: 'comment.php' }
+		]
+	}],
+
+	[{
+		line: '<?php #sticky comment',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.php' }
+		]
+	}],
+
+	[{
+		line: '<?php $x = 1; # my comment // is a nice one',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'variable.php' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.php' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'number.php' },
+			{ startIndex: 12, type: 'delimiter.php' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'comment.php' }
+		]
+	}],
+
+	[{
+		line: '<?php # comment?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.php' },
+			{ startIndex: 15, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<?php # comment? ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.php' },
+			{ startIndex: 17, type: 'metatag.php' }
+		]
+	}],
 
 	// 3-languages parser
 
 	// php
 	[{
-	line: '<?=\'hi\'?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:3, type: 'string.php' },
-		{ startIndex:7, type: 'metatag.php' }
-	]}],
+		line: '<?=\'hi\'?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 3, type: 'string.php' },
+			{ startIndex: 7, type: 'metatag.php' }
+		]
+	}],
 
 	// php/html/php
 	[{
-	line: '<?php5+3?><br/><?=1?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: 'number.php' },
-		{ startIndex:6, type: 'delimiter.php' },
-		{ startIndex:7, type: 'number.php' },
-		{ startIndex:8, type: 'metatag.php' },
-		{ startIndex:10, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:11, type: htmlTokenTypes.getTag('br') },
-		{ startIndex:13, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:15, type: 'metatag.php' },
-		{ startIndex:18, type: 'number.php' },
-		{ startIndex:19, type: 'metatag.php' }
-	]}],
+		line: '<?php5+3?><br/><?=1?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: 'number.php' },
+			{ startIndex: 6, type: 'delimiter.php' },
+			{ startIndex: 7, type: 'number.php' },
+			{ startIndex: 8, type: 'metatag.php' },
+			{ startIndex: 10, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 11, type: htmlTokenTypes.getTag('br') },
+			{ startIndex: 13, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 15, type: 'metatag.php' },
+			{ startIndex: 18, type: 'number.php' },
+			{ startIndex: 19, type: 'metatag.php' }
+		]
+	}],
 
 	// php/html/php
 	[{
-	line: '<?php5+3?><abc><?=1?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: 'number.php' },
-		{ startIndex:6, type: 'delimiter.php' },
-		{ startIndex:7, type: 'number.php' },
-		{ startIndex:8, type: 'metatag.php' },
-		{ startIndex:10, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:11, type: htmlTokenTypes.getTag('abc') },
-		{ startIndex:14, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:15, type: 'metatag.php' },
-		{ startIndex:18, type: 'number.php' },
-		{ startIndex:19, type: 'metatag.php' }
-	]}],
+		line: '<?php5+3?><abc><?=1?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: 'number.php' },
+			{ startIndex: 6, type: 'delimiter.php' },
+			{ startIndex: 7, type: 'number.php' },
+			{ startIndex: 8, type: 'metatag.php' },
+			{ startIndex: 10, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 11, type: htmlTokenTypes.getTag('abc') },
+			{ startIndex: 14, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 15, type: 'metatag.php' },
+			{ startIndex: 18, type: 'number.php' },
+			{ startIndex: 19, type: 'metatag.php' }
+		]
+	}],
 
 	// html/php/html
 	[{
-	line: '<abc><?php5+3?><abc>',
-	tokens: [
-		{ startIndex:0, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:1, type: htmlTokenTypes.getTag('abc') },
-		{ startIndex:4, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:5, type: 'metatag.php' },
-		{ startIndex:10, type: 'number.php' },
-		{ startIndex:11, type: 'delimiter.php' },
-		{ startIndex:12, type: 'number.php' },
-		{ startIndex:13, type: 'metatag.php' },
-		{ startIndex:15, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:16, type: htmlTokenTypes.getTag('abc') },
-		{ startIndex:19, type: htmlTokenTypes.DELIM_END }
-	]}],
+		line: '<abc><?php5+3?><abc>',
+		tokens: [
+			{ startIndex: 0, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 1, type: htmlTokenTypes.getTag('abc') },
+			{ startIndex: 4, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 5, type: 'metatag.php' },
+			{ startIndex: 10, type: 'number.php' },
+			{ startIndex: 11, type: 'delimiter.php' },
+			{ startIndex: 12, type: 'number.php' },
+			{ startIndex: 13, type: 'metatag.php' },
+			{ startIndex: 15, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 16, type: htmlTokenTypes.getTag('abc') },
+			{ startIndex: 19, type: htmlTokenTypes.DELIM_END }
+		]
+	}],
 
 	// html/js/php/html
 	[{
-	line: '<abc><script>var i= 10;</script><?php5+3?><abc>',
-	tokens: [
-		{ startIndex:0, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:1, type: htmlTokenTypes.getTag('abc') },
-		{ startIndex:4, type: htmlTokenTypes.DELIM_END },
-		// { startIndex:5, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:6, type: htmlTokenTypes.getTag('script') },
-		{ startIndex:12, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:13, type: '' },
-		{ startIndex:23, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:25, type: htmlTokenTypes.getTag('script') },
-		{ startIndex:31, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:32, type: 'metatag.php' },
-		{ startIndex:37, type: 'number.php' },
-		{ startIndex:38, type: 'delimiter.php' },
-		{ startIndex:39, type: 'number.php' },
-		{ startIndex:40, type: 'metatag.php' },
-		{ startIndex:42, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:43, type: htmlTokenTypes.getTag('abc') },
-		{ startIndex:46, type: htmlTokenTypes.DELIM_END }
-	]}],
+		line: '<abc><script>var i= 10;</script><?php5+3?><abc>',
+		tokens: [
+			{ startIndex: 0, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 1, type: htmlTokenTypes.getTag('abc') },
+			{ startIndex: 4, type: htmlTokenTypes.DELIM_END },
+			// { startIndex:5, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 6, type: htmlTokenTypes.getTag('script') },
+			{ startIndex: 12, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 23, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 25, type: htmlTokenTypes.getTag('script') },
+			{ startIndex: 31, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 32, type: 'metatag.php' },
+			{ startIndex: 37, type: 'number.php' },
+			{ startIndex: 38, type: 'delimiter.php' },
+			{ startIndex: 39, type: 'number.php' },
+			{ startIndex: 40, type: 'metatag.php' },
+			{ startIndex: 42, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 43, type: htmlTokenTypes.getTag('abc') },
+			{ startIndex: 46, type: htmlTokenTypes.DELIM_END }
+		]
+	}],
 
 	// html/js/php/js/
 	[{
-	line: '<abc><script>var i= 10;</script><?php5+3?><script>var x= 15;</script>',
-	tokens: [
-		{ startIndex:0, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:1, type: htmlTokenTypes.getTag('abc') },
-		{ startIndex:4, type: htmlTokenTypes.DELIM_END },
-		// { startIndex:5, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:6, type: htmlTokenTypes.getTag('script') },
-		{ startIndex:12, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:13, type: '' },
-		{ startIndex:23, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:25, type: htmlTokenTypes.getTag('script') },
-		{ startIndex:31, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:32, type: 'metatag.php' },
-		{ startIndex:37, type: 'number.php' },
-		{ startIndex:38, type: 'delimiter.php' },
-		{ startIndex:39, type: 'number.php' },
-		{ startIndex:40, type: 'metatag.php' },
-		{ startIndex:42, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:43, type: htmlTokenTypes.getTag('script') },
-		{ startIndex:49, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:50, type: '' },
-		{ startIndex:60, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:62, type: htmlTokenTypes.getTag('script') },
-		{ startIndex:68, type: htmlTokenTypes.DELIM_END }
-	]}],
+		line: '<abc><script>var i= 10;</script><?php5+3?><script>var x= 15;</script>',
+		tokens: [
+			{ startIndex: 0, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 1, type: htmlTokenTypes.getTag('abc') },
+			{ startIndex: 4, type: htmlTokenTypes.DELIM_END },
+			// { startIndex:5, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 6, type: htmlTokenTypes.getTag('script') },
+			{ startIndex: 12, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 23, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 25, type: htmlTokenTypes.getTag('script') },
+			{ startIndex: 31, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 32, type: 'metatag.php' },
+			{ startIndex: 37, type: 'number.php' },
+			{ startIndex: 38, type: 'delimiter.php' },
+			{ startIndex: 39, type: 'number.php' },
+			{ startIndex: 40, type: 'metatag.php' },
+			{ startIndex: 42, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 43, type: htmlTokenTypes.getTag('script') },
+			{ startIndex: 49, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 50, type: '' },
+			{ startIndex: 60, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 62, type: htmlTokenTypes.getTag('script') },
+			{ startIndex: 68, type: htmlTokenTypes.DELIM_END }
+		]
+	}],
 
 	// Multiline test
 	[{
-	line: '<html>',
-	tokens: [
-		{ startIndex:0, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:1, type: htmlTokenTypes.getTag('html') },
-		{ startIndex:5, type: htmlTokenTypes.DELIM_END }
-	]}, {
-	line: '<style><?="div"?>{ color:blue; }</style>',
-	tokens: [
-		{ startIndex:0, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:1, type: htmlTokenTypes.getTag('style') },
-		{ startIndex:6, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:7, type: 'metatag.php' },
-		{ startIndex:10, type: 'string.php' },
-		{ startIndex:15, type: 'metatag.php' },
-		{ startIndex:17, type: 'delimiter.bracket.css' },
-		{ startIndex:18, type: '' },
-		{ startIndex:19, type: 'attribute.name.css' },
-		{ startIndex:25, type: 'attribute.value.css' },
-		{ startIndex:29, type: 'delimiter.css' },
-		{ startIndex:30, type: '' },
-		{ startIndex:31, type: 'delimiter.bracket.css' },
-		{ startIndex:32, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:34, type: htmlTokenTypes.getTag('style') },
-		{ startIndex:39, type: htmlTokenTypes.DELIM_END }
-	]}],
+		line: '<html>',
+		tokens: [
+			{ startIndex: 0, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 1, type: htmlTokenTypes.getTag('html') },
+			{ startIndex: 5, type: htmlTokenTypes.DELIM_END }
+		]
+	}, {
+		line: '<style><?="div"?>{ color:blue; }</style>',
+		tokens: [
+			{ startIndex: 0, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 1, type: htmlTokenTypes.getTag('style') },
+			{ startIndex: 6, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 7, type: 'metatag.php' },
+			{ startIndex: 10, type: 'string.php' },
+			{ startIndex: 15, type: 'metatag.php' },
+			{ startIndex: 17, type: 'delimiter.bracket.css' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'attribute.name.css' },
+			{ startIndex: 25, type: 'attribute.value.css' },
+			{ startIndex: 29, type: 'delimiter.css' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'delimiter.bracket.css' },
+			{ startIndex: 32, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 34, type: htmlTokenTypes.getTag('style') },
+			{ startIndex: 39, type: htmlTokenTypes.DELIM_END }
+		]
+	}],
 
 	// HTML (CSS (PHP)), HTML ( PHP, JS (PHP), PHP)
 	[{
-	line: '<html><style><?="div"?> { color:blue; }</style><!--<?="HTML Comment"?>--><script>var x = 3;/* <?="JS Comment"/*</script>*/?> */var y = 4;</script></html><? $x = 3;?>',
-	tokens: [
-		{ startIndex:0, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:1, type: htmlTokenTypes.getTag('html') },
-		{ startIndex:5, type: htmlTokenTypes.DELIM_END },
-		// { startIndex:6, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:7, type: htmlTokenTypes.getTag('style') },
-		{ startIndex:12, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:13, type: 'metatag.php' },
-		{ startIndex:16, type: 'string.php' },
-		{ startIndex:21, type: 'metatag.php' },
-		{ startIndex:23, type: '' },
-		{ startIndex:24, type: 'delimiter.bracket.css' },
-		{ startIndex:25, type: '' },
-		{ startIndex:26, type: 'attribute.name.css' },
-		{ startIndex:32, type: 'attribute.value.css' },
-		{ startIndex:36, type: 'delimiter.css' },
-		{ startIndex:37, type: '' },
-		{ startIndex:38, type: 'delimiter.bracket.css' },
-		{ startIndex:39, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:41, type: htmlTokenTypes.getTag('style') },
-		{ startIndex:46, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:47, type: htmlTokenTypes.DELIM_COMMENT },
-		{ startIndex:51, type: 'metatag.php' },
-		{ startIndex:54, type: 'string.php' },
-		{ startIndex:68, type: 'metatag.php' },
-		{ startIndex:70, type: htmlTokenTypes.DELIM_COMMENT },
-		{ startIndex:73, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:74, type: htmlTokenTypes.getTag('script') },
-		{ startIndex:80, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:81, type: '' },
-		{ startIndex:94, type: 'metatag.php' },
-		{ startIndex:97, type: 'string.php' },
-		{ startIndex:109, type: 'comment.php' },
-		{ startIndex:122, type: 'metatag.php' },
-		{ startIndex:124, type: '' },
-		{ startIndex:137, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:139, type: htmlTokenTypes.getTag('script') },
-		{ startIndex:145, type: htmlTokenTypes.DELIM_END },
-		// { startIndex:146, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:148, type: htmlTokenTypes.getTag('html') },
-		{ startIndex:152, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:153, type: 'metatag.php' },
-		{ startIndex:155, type: '' },
-		{ startIndex:156, type: 'variable.php' },
-		{ startIndex:158, type: '' },
-		{ startIndex:159, type: 'delimiter.php' },
-		{ startIndex:160, type: '' },
-		{ startIndex:161, type: 'number.php' },
-		{ startIndex:162, type: 'delimiter.php' },
-		{ startIndex:163, type: 'metatag.php' }
-	]}],
+		line: '<html><style><?="div"?> { color:blue; }</style><!--<?="HTML Comment"?>--><script>var x = 3;/* <?="JS Comment"/*</script>*/?> */var y = 4;</script></html><? $x = 3;?>',
+		tokens: [
+			{ startIndex: 0, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 1, type: htmlTokenTypes.getTag('html') },
+			{ startIndex: 5, type: htmlTokenTypes.DELIM_END },
+			// { startIndex:6, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 7, type: htmlTokenTypes.getTag('style') },
+			{ startIndex: 12, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 13, type: 'metatag.php' },
+			{ startIndex: 16, type: 'string.php' },
+			{ startIndex: 21, type: 'metatag.php' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'delimiter.bracket.css' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'attribute.name.css' },
+			{ startIndex: 32, type: 'attribute.value.css' },
+			{ startIndex: 36, type: 'delimiter.css' },
+			{ startIndex: 37, type: '' },
+			{ startIndex: 38, type: 'delimiter.bracket.css' },
+			{ startIndex: 39, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 41, type: htmlTokenTypes.getTag('style') },
+			{ startIndex: 46, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 47, type: htmlTokenTypes.DELIM_COMMENT },
+			{ startIndex: 51, type: 'metatag.php' },
+			{ startIndex: 54, type: 'string.php' },
+			{ startIndex: 68, type: 'metatag.php' },
+			{ startIndex: 70, type: htmlTokenTypes.DELIM_COMMENT },
+			{ startIndex: 73, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 74, type: htmlTokenTypes.getTag('script') },
+			{ startIndex: 80, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 81, type: '' },
+			{ startIndex: 94, type: 'metatag.php' },
+			{ startIndex: 97, type: 'string.php' },
+			{ startIndex: 109, type: 'comment.php' },
+			{ startIndex: 122, type: 'metatag.php' },
+			{ startIndex: 124, type: '' },
+			{ startIndex: 137, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 139, type: htmlTokenTypes.getTag('script') },
+			{ startIndex: 145, type: htmlTokenTypes.DELIM_END },
+			// { startIndex:146, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 148, type: htmlTokenTypes.getTag('html') },
+			{ startIndex: 152, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 153, type: 'metatag.php' },
+			{ startIndex: 155, type: '' },
+			{ startIndex: 156, type: 'variable.php' },
+			{ startIndex: 158, type: '' },
+			{ startIndex: 159, type: 'delimiter.php' },
+			{ startIndex: 160, type: '' },
+			{ startIndex: 161, type: 'number.php' },
+			{ startIndex: 162, type: 'delimiter.php' },
+			{ startIndex: 163, type: 'metatag.php' }
+		]
+	}],
 
 	// PHP-tag detection
 	[{
-	line: '<!--c--><?',
-	tokens: [
-		{ startIndex:0, type: htmlTokenTypes.DELIM_COMMENT },
-		{ startIndex:4, type: htmlTokenTypes.COMMENT },
-		{ startIndex:5, type: htmlTokenTypes.DELIM_COMMENT },
-		{ startIndex:8, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<script>//<?',
-	tokens: [
-		{ startIndex:0, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:1, type: htmlTokenTypes.getTag('script') },
-		{ startIndex:7, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:8, type: '' },
-		{ startIndex:10, type: 'metatag.php' }
-	]}],
-
-	[{
-	line: '<script>"<?php5+3?>"',
-	tokens: [
-		{ startIndex:0, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:1, type: htmlTokenTypes.getTag('script') },
-		{ startIndex:7, type: htmlTokenTypes.DELIM_END },
-		{ startIndex:8, type: '' },
-		{ startIndex:9, type: 'metatag.php' },
-		{ startIndex:14, type: 'number.php' },
-		{ startIndex:15, type: 'delimiter.php' },
-		{ startIndex:16, type: 'number.php' },
-		{ startIndex:17, type: 'metatag.php' },
-		{ startIndex:19, type: '' }
-	]}],
-
-	[{
-	line: '<?php toString(); ?>',
-	tokens: [
-		{ startIndex:0, type: 'metatag.php' },
-		{ startIndex:5, type: '' },
-		{ startIndex:6, type: 'identifier.php' },
-		{ startIndex:14, type: 'delimiter.parenthesis.php' },
-		{ startIndex:16, type: 'delimiter.php' },
-		{ startIndex:17, type: '' },
-		{ startIndex:18, type: 'metatag.php' }
-	]}]
-]);
+		line: '<!--c--><?',
+		tokens: [
+			{ startIndex: 0, type: htmlTokenTypes.DELIM_COMMENT },
+			{ startIndex: 4, type: htmlTokenTypes.COMMENT },
+			{ startIndex: 5, type: htmlTokenTypes.DELIM_COMMENT },
+			{ startIndex: 8, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<script>//<?',
+		tokens: [
+			{ startIndex: 0, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 1, type: htmlTokenTypes.getTag('script') },
+			{ startIndex: 7, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 10, type: 'metatag.php' }
+		]
+	}],
+
+	[{
+		line: '<script>"<?php5+3?>"',
+		tokens: [
+			{ startIndex: 0, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 1, type: htmlTokenTypes.getTag('script') },
+			{ startIndex: 7, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'metatag.php' },
+			{ startIndex: 14, type: 'number.php' },
+			{ startIndex: 15, type: 'delimiter.php' },
+			{ startIndex: 16, type: 'number.php' },
+			{ startIndex: 17, type: 'metatag.php' },
+			{ startIndex: 19, type: '' }
+		]
+	}],
+
+	[{
+		line: '<?php toString(); ?>',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.php' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.php' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.php' },
+			{ startIndex: 16, type: 'delimiter.php' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'metatag.php' }
+		]
+	}]
+]);

+ 927 - 835
test/postiats.test.ts

@@ -5,911 +5,1003 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('postiats', [
 	// Keywords
 	[{
-	line: 'implement main(argc, argv) =',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pats' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'identifier.pats' },
-		{ startIndex: 14, type: 'delimiter.parenthesis.pats' },
-		{ startIndex: 15, type: 'identifier.pats' },
-		{ startIndex: 19, type: 'delimiter.comma.pats' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'identifier.pats' },
-		{ startIndex: 25, type: 'delimiter.parenthesis.pats' },
-		{ startIndex: 26, type: '' },
-        { startIndex: 27, type: 'keyword.pats'}
-	]}],
+		line: 'implement main(argc, argv) =',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.pats' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 15, type: 'identifier.pats' },
+			{ startIndex: 19, type: 'delimiter.comma.pats' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'identifier.pats' },
+			{ startIndex: 25, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 26, type: '' },
+			{ startIndex: 27, type: 'keyword.pats' }
+		]
+	}],
 
 	// Comments - single line
 	[{
-	line: '//',
-	tokens: [
-		{ startIndex: 0, type: 'comment.pats' }
-	]}],
-
-	[{
-	line: '    // a comment',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'comment.pats' }
-	]}],
-
-	[{
-	line: '// a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.pats' }
-	]}],
-
-	[{
-	line: '//sticky comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.pats' }
-	]}],
-
-	[{
-	line: '/almost a comment',
-	tokens: [
-		{ startIndex: 0, type: 'operator.pats' },
-		{ startIndex: 1, type: 'identifier.pats' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.pats' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'identifier.pats' }
-	]}],
-
-	[{
-	line: '/* //*/ a',
-	tokens: [
-		{ startIndex: 0, type: 'comment.pats' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.pats' }
-	]}],
-
-	[{
-	line: '1 / 2; /* comment',
-	tokens: [
-		{ startIndex: 0, type: 'number.decimal.pats' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'operator.pats' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.decimal.pats' },
-		{ startIndex: 5, type: 'delimiter.semicolon.pats' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'comment.pats' }
-	]}],
-
-	[{
-	line: 'val x:int = 1; // my comment // is a nice one',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pats' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.pats' },
-        { startIndex: 5, type: 'keyword.pats'},
-		{ startIndex: 6, type: 'type.pats' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'keyword.pats' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'number.decimal.pats' },
-        { startIndex: 13, type: 'delimiter.semicolon.pats'},
-        { startIndex: 14, type: ''},
-		{ startIndex: 15, type: 'comment.pats' }
-	]}],
+		line: '//',
+		tokens: [
+			{ startIndex: 0, type: 'comment.pats' }
+		]
+	}],
+
+	[{
+		line: '    // a comment',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'comment.pats' }
+		]
+	}],
+
+	[{
+		line: '// a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.pats' }
+		]
+	}],
+
+	[{
+		line: '//sticky comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.pats' }
+		]
+	}],
+
+	[{
+		line: '/almost a comment',
+		tokens: [
+			{ startIndex: 0, type: 'operator.pats' },
+			{ startIndex: 1, type: 'identifier.pats' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.pats' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.pats' }
+		]
+	}],
+
+	[{
+		line: '/* //*/ a',
+		tokens: [
+			{ startIndex: 0, type: 'comment.pats' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.pats' }
+		]
+	}],
+
+	[{
+		line: '1 / 2; /* comment',
+		tokens: [
+			{ startIndex: 0, type: 'number.decimal.pats' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'operator.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.decimal.pats' },
+			{ startIndex: 5, type: 'delimiter.semicolon.pats' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'comment.pats' }
+		]
+	}],
+
+	[{
+		line: 'val x:int = 1; // my comment // is a nice one',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.pats' },
+			{ startIndex: 5, type: 'keyword.pats' },
+			{ startIndex: 6, type: 'type.pats' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'keyword.pats' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'number.decimal.pats' },
+			{ startIndex: 13, type: 'delimiter.semicolon.pats' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'comment.pats' }
+		]
+	}],
 
 	// Comments - range comment, single line
 	[{
-	line: '/* a simple comment */',
-	tokens: [
-		{ startIndex: 0, type: 'comment.pats' }
-	]}],
-
-	[{
-	line: 'var x : int = /* a simple comment */ 1;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pats' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.pats' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'keyword.pats' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'type.pats' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'keyword.pats' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'comment.pats' },
-		{ startIndex: 36, type: '' },
-		{ startIndex: 37, type: 'number.decimal.pats' },
-		{ startIndex: 38, type: 'delimiter.semicolon.pats' }
-	]}],
-
-	[{
-	line: 'val x = /* comment */ 1; */',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pats' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.pats' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'keyword.pats' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.pats' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'number.decimal.pats' },
-		{ startIndex: 23, type: 'delimiter.semicolon.pats' },
-		{ startIndex: 24, type: '' },
-		{ startIndex: 25, type: 'operator.pats' }
-	]}],
-
-	[{
-	line: 'x = /**/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.pats' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'keyword.pats' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.pats' },
-		{ startIndex: 8, type: 'delimiter.semicolon.pats' }
-	]}],
-
-	[{
-	line: 'x = /*/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.pats' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'keyword.pats' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.pats' }
-	]}],
-
-    // block comments, single line
-	[{
-	line: '(* a simple comment *)',
-	tokens: [
-		{ startIndex: 0, type: 'comment.pats' }
-	]}],
-
-	[{
-	line: '(* a simple (* nested *) comment *)',
-	tokens: [
-		{ startIndex: 0, type: 'comment.pats' }
-	]}],
-
-	[{
-	line: '(* ****** ****** *)',
-	tokens: [
-		{ startIndex: 0, type: 'comment.pats' }
-	]}],
-
-	[{
-	line: 'var x : int = (* a simple comment *) 1;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pats' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.pats' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'keyword.pats' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'type.pats' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'keyword.pats' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'comment.pats' },
-		{ startIndex: 36, type: '' },
-		{ startIndex: 37, type: 'number.decimal.pats' },
-		{ startIndex: 38, type: 'delimiter.semicolon.pats' }
-	]}],
-
-	[{
-	line: 'val x = (* comment *) 1; *)',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pats' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.pats' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'keyword.pats' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.pats' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'number.decimal.pats' },
-		{ startIndex: 23, type: 'delimiter.semicolon.pats' },
-		{ startIndex: 24, type: '' },
-		{ startIndex: 25, type: 'operator.pats' },
-		{ startIndex: 26, type: 'delimiter.parenthesis.pats' },
-	]}],
-
-	[{
-	line: 'x = (**);',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.pats' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'keyword.pats' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.pats' },
-		{ startIndex: 8, type: 'delimiter.semicolon.pats' }
-	]}],
-
-	[{
-	line: '(*)',
-	tokens: [
-		{ startIndex: 0, type: 'invalid.pats' }, // not a comment!
-	]}],
+		line: '/* a simple comment */',
+		tokens: [
+			{ startIndex: 0, type: 'comment.pats' }
+		]
+	}],
+
+	[{
+		line: 'var x : int = /* a simple comment */ 1;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.pats' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.pats' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'type.pats' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'keyword.pats' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'comment.pats' },
+			{ startIndex: 36, type: '' },
+			{ startIndex: 37, type: 'number.decimal.pats' },
+			{ startIndex: 38, type: 'delimiter.semicolon.pats' }
+		]
+	}],
+
+	[{
+		line: 'val x = /* comment */ 1; */',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.pats' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.pats' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.pats' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'number.decimal.pats' },
+			{ startIndex: 23, type: 'delimiter.semicolon.pats' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'operator.pats' }
+		]
+	}],
+
+	[{
+		line: 'x = /**/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.pats' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.pats' },
+			{ startIndex: 8, type: 'delimiter.semicolon.pats' }
+		]
+	}],
+
+	[{
+		line: 'x = /*/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.pats' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.pats' }
+		]
+	}],
+
+	// block comments, single line
+	[{
+		line: '(* a simple comment *)',
+		tokens: [
+			{ startIndex: 0, type: 'comment.pats' }
+		]
+	}],
+
+	[{
+		line: '(* a simple (* nested *) comment *)',
+		tokens: [
+			{ startIndex: 0, type: 'comment.pats' }
+		]
+	}],
+
+	[{
+		line: '(* ****** ****** *)',
+		tokens: [
+			{ startIndex: 0, type: 'comment.pats' }
+		]
+	}],
+
+	[{
+		line: 'var x : int = (* a simple comment *) 1;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.pats' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.pats' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'type.pats' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'keyword.pats' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'comment.pats' },
+			{ startIndex: 36, type: '' },
+			{ startIndex: 37, type: 'number.decimal.pats' },
+			{ startIndex: 38, type: 'delimiter.semicolon.pats' }
+		]
+	}],
+
+	[{
+		line: 'val x = (* comment *) 1; *)',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.pats' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.pats' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.pats' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'number.decimal.pats' },
+			{ startIndex: 23, type: 'delimiter.semicolon.pats' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'operator.pats' },
+			{ startIndex: 26, type: 'delimiter.parenthesis.pats' },
+		]
+	}],
+
+	[{
+		line: 'x = (**);',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.pats' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.pats' },
+			{ startIndex: 8, type: 'delimiter.semicolon.pats' }
+		]
+	}],
+
+	[{
+		line: '(*)',
+		tokens: [
+			{ startIndex: 0, type: 'invalid.pats' }, // not a comment!
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '0',
-	tokens: [
-		{ startIndex: 0, type: 'number.decimal.pats' }
-	]}],
+		line: '0',
+		tokens: [
+			{ startIndex: 0, type: 'number.decimal.pats' }
+		]
+	}],
 
 	[{
-	line: '12l',
-	tokens: [
-		{ startIndex: 0, type: 'number.decimal.pats' }
-	]}],
+		line: '12l',
+		tokens: [
+			{ startIndex: 0, type: 'number.decimal.pats' }
+		]
+	}],
 
 	[{
-	line: '34U',
-	tokens: [
-		{ startIndex: 0, type: 'number.decimal.pats' }
-	]}],
+		line: '34U',
+		tokens: [
+			{ startIndex: 0, type: 'number.decimal.pats' }
+		]
+	}],
 
 	[{
-	line: '55LL',
-	tokens: [
-		{ startIndex: 0, type: 'number.decimal.pats' }
-	]}],
+		line: '55LL',
+		tokens: [
+			{ startIndex: 0, type: 'number.decimal.pats' }
+		]
+	}],
 
 	[{
-	line: '34ul',
-	tokens: [
-		{ startIndex: 0, type: 'number.decimal.pats' }
-	]}],
+		line: '34ul',
+		tokens: [
+			{ startIndex: 0, type: 'number.decimal.pats' }
+		]
+	}],
 
 	[{
-	line: '55llU',
-	tokens: [
-		{ startIndex: 0, type: 'number.decimal.pats' }
-	]}],
+		line: '55llU',
+		tokens: [
+			{ startIndex: 0, type: 'number.decimal.pats' }
+		]
+	}],
 
-/*
-	[{
-	line: '5\'5llU',
-	tokens: [
-		{ startIndex: 0, type: 'number.pats' }
-	]}],
+	/*
+		[{
+		line: '5\'5llU',
+		tokens: [
+			{ startIndex: 0, type: 'number.pats' }
+		]}],
 
+		[{
+		line: '100\'000\'000',
+		tokens: [
+			{ startIndex: 0, type: 'number.pats' }
+		]}],
+	*/
 	[{
-	line: '100\'000\'000',
-	tokens: [
-		{ startIndex: 0, type: 'number.pats' }
-	]}],
-*/
-	[{
-	line: '0x100aafllU',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.pats' }
-	]}],
+		line: '0x100aafllU',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.pats' }
+		]
+	}],
 
 	[{
-	line: '0342325',
-	tokens: [
-		{ startIndex: 0, type: 'number.octal.pats' }
-	]}],
+		line: '0342325',
+		tokens: [
+			{ startIndex: 0, type: 'number.octal.pats' }
+		]
+	}],
 
 	[{
-	line: '0x123',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.pats' }
-	]}],
+		line: '0x123',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.pats' }
+		]
+	}],
 
 	[{
-	line: '23.5',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '23.5',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '23.5e3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '23.5e3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '23.5E3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '23.5E3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '23.5F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '23.5F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '23.5f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '23.5f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '1.72E3F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '1.72E3F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '1.72E3f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '1.72E3f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '1.72e3F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '1.72e3F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '1.72e3f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '1.72e3f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '23.5L',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '23.5L',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '23.5l',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '23.5l',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '1.72E3L',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '1.72E3L',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '1.72E3l',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '1.72E3l',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '1.72e3L',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '1.72e3L',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '1.72e3l',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.pats' }
-	]}],
+		line: '1.72e3l',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.pats' }
+		]
+	}],
 
 	[{
-	line: '0+0',
-	tokens: [
-		{ startIndex: 0, type: 'number.decimal.pats' },
-		{ startIndex: 1, type: 'operator.pats' },
-		{ startIndex: 2, type: 'number.decimal.pats' }
-	]}],
+		line: '0+0',
+		tokens: [
+			{ startIndex: 0, type: 'number.decimal.pats' },
+			{ startIndex: 1, type: 'operator.pats' },
+			{ startIndex: 2, type: 'number.decimal.pats' }
+		]
+	}],
 
 	[{
-	line: '100+10',
-	tokens: [
-		{ startIndex: 0, type: 'number.decimal.pats' },
-		{ startIndex: 3, type: 'operator.pats' },
-		{ startIndex: 4, type: 'number.decimal.pats' }
-	]}],
+		line: '100+10',
+		tokens: [
+			{ startIndex: 0, type: 'number.decimal.pats' },
+			{ startIndex: 3, type: 'operator.pats' },
+			{ startIndex: 4, type: 'number.decimal.pats' }
+		]
+	}],
 
 	[{
-	line: '0 + 0',
-	tokens: [
-		{ startIndex: 0, type: 'number.decimal.pats' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'operator.pats' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.decimal.pats' }
-	]}],
+		line: '0 + 0',
+		tokens: [
+			{ startIndex: 0, type: 'number.decimal.pats' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'operator.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.decimal.pats' }
+		]
+	}],
 
 	// hi-lighting of variables in staload/dynload
 	[{
-	line: '"{$LIBATSCC2JS}/staloadall.hats"',
-	tokens: [
-		{ startIndex: 0, type: 'string.quote.pats' },
-		{ startIndex: 1, type: 'string.escape.pats' },
-		{ startIndex: 3, type: 'identifier.pats' },
-		{ startIndex: 14, type: 'string.escape.pats' },
-		{ startIndex: 15, type: 'string.pats' },
-		{ startIndex: 31, type: 'string.quote.pats' }
-	]}],
+		line: '"{$LIBATSCC2JS}/staloadall.hats"',
+		tokens: [
+			{ startIndex: 0, type: 'string.quote.pats' },
+			{ startIndex: 1, type: 'string.escape.pats' },
+			{ startIndex: 3, type: 'identifier.pats' },
+			{ startIndex: 14, type: 'string.escape.pats' },
+			{ startIndex: 15, type: 'string.pats' },
+			{ startIndex: 31, type: 'string.quote.pats' }
+		]
+	}],
 
 	// Monarch Generated
 	[{
-	line: '#include "/path/to/my/file.h"',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.srp.pats' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'string.quote.pats' },
-		{ startIndex: 10, type: 'string.pats' },
-		{ startIndex: 28, type: 'string.quote.pats' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '#ifdef VAR #then',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.srp.pats' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.pats' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'keyword.srp.pats' }
-	]}, {
-	line: '#define SUM(A,B) (A) + (B)',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.srp.pats' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.pats' },
-		{ startIndex: 11, type: 'delimiter.parenthesis.pats' },
-		{ startIndex: 12, type: 'identifier.pats' },
-		{ startIndex: 13, type: 'delimiter.comma.pats' },
-		{ startIndex: 14, type: 'identifier.pats' },
-		{ startIndex: 15, type: 'delimiter.parenthesis.pats' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'delimiter.parenthesis.pats' },
-		{ startIndex: 18, type: 'identifier.pats' },
-		{ startIndex: 19, type: 'delimiter.parenthesis.pats' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'operator.pats' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'delimiter.parenthesis.pats' },
-		{ startIndex: 24, type: 'identifier.pats' },
-		{ startIndex: 25, type: 'delimiter.parenthesis.pats' }
-	]}, {
-	line: 'staload Asdf_CDE = "./myfile.sats"',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pats' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.pats' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'keyword.pats' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'string.quote.pats' },
-		{ startIndex: 20, type: 'string.pats' },
-		{ startIndex: 33, type: 'string.quote.pats' },
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'implement main(argc, argv)',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pats' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'identifier.pats' },
-		{ startIndex: 14, type: 'delimiter.parenthesis.pats' },
-		{ startIndex: 15, type: 'identifier.pats' },
-		{ startIndex: 19, type: 'delimiter.comma.pats' },
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'identifier.pats' },
-		{ startIndex: 25, type: 'delimiter.parenthesis.pats' }
-	]}, {
-	line: ' = begin',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'keyword.pats' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'keyword.pats' }
-	]}, {
-	line: '0',
-	tokens: [
-		{ startIndex: 0, type: 'number.decimal.pats' },
-	]}, {
-	line: 'end',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pats' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'dataprop FACT (int, int) =',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pats' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'identifier.pats' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'delimiter.parenthesis.pats' },
-		{ startIndex: 15, type: 'type.pats' },
-		{ startIndex: 18, type: 'delimiter.comma.pats' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'type.pats' },
-		{ startIndex: 23, type: 'delimiter.parenthesis.pats' },
-		{ startIndex: 24, type: '' },
-		{ startIndex: 25, type: 'keyword.pats' }
-	]}, {
-	line: ' | FACTbas (0, 1) of ()',
-	tokens: [
-        { startIndex: 0, type: '' },
-        { startIndex: 1, type: 'keyword.pats' },
-        { startIndex: 2, type: '' },
-        { startIndex: 3, type: 'identifier.pats' },
-        { startIndex: 10, type: '' },
-        { startIndex: 11, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 12, type: 'number.decimal.pats' },
-        { startIndex: 13, type: 'delimiter.comma.pats' },
-        { startIndex: 14, type: '' },
-        { startIndex: 15, type: 'number.decimal.pats' },
-        { startIndex: 16, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 17, type: '' },
-        { startIndex: 18, type: 'keyword.pats' },
-        { startIndex: 20, type: '' },
-        { startIndex: 21, type: 'delimiter.parenthesis.pats' }
-	]}, {
-	line: ' | {n:pos}{r:int} FACTind (n, n*r) of FACT (n-1, r)',
-	tokens: [
-        { startIndex: 0, type: '' },
-        { startIndex: 1, type: 'keyword.pats' },
-        { startIndex: 2, type: '' },
-        { startIndex: 3,  type: 'delimiter.curly.pats' },
-        { startIndex: 4, type: 'identifier.pats' },
-        { startIndex: 5, type: 'keyword.pats' },
-        { startIndex: 6, type: 'identifier.pats' },
-        { startIndex: 9, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 10, type: 'delimiter.curly.pats' },
-	    { startIndex: 11, type: 'identifier.pats' },
-        { startIndex: 12, type: 'keyword.pats' },
-        { startIndex: 13, type: 'type.pats' },
-        { startIndex: 16, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 17, type: '' },
-        { startIndex: 18, type: 'identifier.pats' },
-        { startIndex: 25, type: '' },
-        { startIndex: 26, type: 'delimiter.parenthesis.pats' },
-		{ startIndex: 27, type: 'identifier.pats' },
-        { startIndex: 28, type: 'delimiter.comma.pats' },
-        { startIndex: 29, type: '' },
-        { startIndex: 30, type: 'identifier.pats' },
-        { startIndex: 31, type: 'operator.pats' },
-        { startIndex: 32, type: 'identifier.pats' },
-        { startIndex: 33, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 34, type: '' },
-        { startIndex: 35, type: 'keyword.pats' },
-        { startIndex: 37, type: '' },
-        { startIndex: 38, type: 'identifier.pats' },
-        { startIndex: 42, type: '' },
-		{ startIndex: 43, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 44, type: 'identifier.pats' },
-        { startIndex: 45, type: 'operator.pats' },
-        { startIndex: 46, type: 'number.decimal.pats' },
-        { startIndex: 47, type: 'delimiter.comma.pats' },
-        { startIndex: 48, type: '' },
-        { startIndex: 49, type: 'identifier.pats' },
-        { startIndex: 50, type: 'delimiter.parenthesis.pats' },
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'fun fact {n:nat} .<n>. (x: int n) : [r:int] (FACT(n, r) | int(r)) = (',
-	tokens: [
-        { startIndex: 0, type: 'keyword.pats' },
-        { startIndex: 3, type: '' },
-        { startIndex: 4, type: 'identifier.pats' },
-        { startIndex: 8, type: '' },
-        { startIndex: 9, type: 'delimiter.curly.pats' },
-        { startIndex: 10, type: 'identifier.pats' },
-        { startIndex: 11, type: 'keyword.pats' },
-        { startIndex: 12, type: 'identifier.pats' },
-        { startIndex: 15, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'identifier.sym.pats' },
-        { startIndex: 19, type: 'identifier.pats' },
-        { startIndex: 20, type: 'keyword.pats' },
-        { startIndex: 22, type: '' },
-        { startIndex: 23, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 24, type: 'identifier.pats' },
-        { startIndex: 25, type: 'keyword.pats' },
-        { startIndex: 26, type: '' },
-	    { startIndex: 27, type: 'type.pats' },
-        { startIndex: 30, type: '' },
-        { startIndex: 31, type: 'identifier.pats' },
-        { startIndex: 32, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 33,  type: '' },
-	    { startIndex: 34, type: 'keyword.pats' },
-        { startIndex: 35, type: '' },
-        { startIndex: 36, type: 'delimiter.square.pats' },
-        { startIndex: 37, type: 'identifier.pats' },
-        { startIndex: 38, type: 'keyword.pats' },
-        { startIndex: 39, type: 'type.pats' },
-        { startIndex: 42, type: 'delimiter.square.pats' },
-        { startIndex: 43, type: '' },
-        { startIndex: 44, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 45, type: 'identifier.pats' },
-	    { startIndex: 49, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 50, type: 'identifier.pats' },
-        { startIndex: 51, type: 'delimiter.comma.pats' },
-        { startIndex: 52, type: '' },
-        { startIndex: 53, type: 'identifier.pats' },
-		{ startIndex: 54, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 55, type: '' },
-		{ startIndex: 56, type: 'keyword.pats' },
-        { startIndex: 57, type: '' },
-        { startIndex: 58, type: 'type.pats' },
-        { startIndex: 61, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 62, type: 'identifier.pats' },
-		{ startIndex: 63, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 65, type: '' },
-        { startIndex: 66, type: 'keyword.pats' },
-        { startIndex: 67, type: '' },
-        { startIndex: 68, type: 'delimiter.parenthesis.pats' },
-	]}, {
-	line: 'if x > 0 then let',
-	tokens: [
-        { startIndex: 0, type: 'keyword.pats' },
-        { startIndex: 2, type: '' },
-        { startIndex: 3, type: 'identifier.pats' },
-        { startIndex: 4, type: '' },
-        { startIndex: 5, type: 'keyword.pats' },
-        { startIndex: 6, type: '' },
-        { startIndex: 7, type: 'number.decimal.pats' },
-        { startIndex: 8, type: '' },
-        { startIndex: 9, type: 'keyword.pats' },
-        { startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'keyword.pats' },
-	]}, {
-	line: '  val [r1:int] (pf1 | r1) = fact (x-1)',
-	tokens: [
-        { startIndex: 0, type: '' },
-	    { startIndex: 2, type: 'keyword.pats' },
-        { startIndex: 5, type: '' },
-        { startIndex: 6, type: 'delimiter.square.pats' },
-        { startIndex: 7, type: 'identifier.pats' },
-		{ startIndex: 9, type: 'keyword.pats' },
-        { startIndex: 10, type: 'type.pats' },
-        { startIndex: 13, type: 'delimiter.square.pats' },
-        { startIndex: 14, type: '' },
-	    { startIndex: 15, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 16, type: 'identifier.pats' },
-        { startIndex: 19, type: '' },
-        { startIndex: 20, type: 'keyword.pats' },
-        { startIndex: 21, type: '' },
-        { startIndex: 22, type: 'identifier.pats' },
-        { startIndex: 24, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 25, type: '' },
-        { startIndex: 26, type: 'keyword.pats' },
-		{ startIndex: 27, type: '' },
-        { startIndex: 28, type: 'identifier.pats' },
-        { startIndex: 32, type: '' },
-  		{ startIndex: 33, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 34, type: 'identifier.pats' },
-        { startIndex: 35, type: 'operator.pats' },
-        { startIndex: 36, type: 'number.decimal.pats' },
-        { startIndex: 37, type: 'delimiter.parenthesis.pats' },
-	]}, {
-	line: '  prval pf = FACTind {n}{r1} (pf1)',
-	tokens: [
-        { startIndex: 0, type: '' },
-        { startIndex: 2, type: 'keyword.pats' },
-        { startIndex: 7, type: '' },
-        { startIndex: 8, type: 'identifier.pats' },
-        { startIndex: 10, type: '' },
-        { startIndex: 11, type: 'keyword.pats' },
-        { startIndex: 12, type: '' },
-        { startIndex: 13, type: 'identifier.pats' },
-        { startIndex: 20, type: '' },
-        { startIndex: 21, type: 'delimiter.curly.pats' },
-        { startIndex: 22, type: 'identifier.pats' },
-        { startIndex: 23, type: 'delimiter.parenthesis.pats' },
-		{ startIndex: 24, type: 'delimiter.curly.pats' },
-        { startIndex: 25, type: 'identifier.pats' },
-        { startIndex: 27, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 28, type: '' },
-        { startIndex: 29, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 30, type: 'identifier.pats' },
-        { startIndex: 33, type: 'delimiter.parenthesis.pats' }
-	]}, {
-	line: '  val r = x * r1',
-	tokens: [
-		{startIndex: 0, type: ''},
-		{startIndex: 2, type: 'keyword.pats'},
-		{startIndex: 5, type: ''},
-		{startIndex: 6, type: 'identifier.pats'},
-		{startIndex: 7, type: ''},
-		{startIndex: 8, type: 'keyword.pats'},
-		{startIndex: 9, type: ''},
-		{startIndex: 10, type: 'identifier.pats'},
-		{startIndex: 11, type: ''},
-		{startIndex: 12, type: 'operator.pats'},
-		{startIndex: 13, type: ''},
-		{startIndex: 14, type: 'identifier.pats'}
-	]}, {
-	line: 'in',
-	tokens: [
-		{startIndex: 0, type: 'keyword.pats'}
-	]}, {
-	line: '  (pf | r)',
-	tokens: [
-        { startIndex: 0, type: '' },
-        { startIndex: 2, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 3, type: 'identifier.pats' },
-        { startIndex: 5, type: '' },
-        { startIndex: 6, type: 'keyword.pats' },
-        { startIndex: 7, type: '' },
-        { startIndex: 8, type: 'identifier.pats' },
-        { startIndex: 9, type: 'delimiter.parenthesis.pats' }
-	]}, {
-	line: 'end // end of [then]',
-	tokens: [
-		{startIndex: 0, type: 'keyword.pats'},
-		{startIndex: 3, type: ''},
-		{startIndex: 4, type: 'comment.pats'}
-	]}, {
-	line: 'else (FACTbas () | 1)',
-	tokens: [
-        { startIndex: 0, type: 'keyword.pats' },
-        { startIndex: 4, type: '' },
-        { startIndex: 5, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 6, type: 'identifier.pats' },
-        { startIndex: 13, type: '' },
-        { startIndex: 14, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'keyword.pats' },
-        { startIndex: 18, type: '' },
-        { startIndex: 19, type: 'number.decimal.pats' },
-        { startIndex: 20, type: 'delimiter.parenthesis.pats' }
-	]}, {
-	line: ') (* end of [fact] *)',
-	tokens: [
-		{startIndex: 0, type: 'delimiter.parenthesis.pats'},
-		{startIndex: 1, type: ''},
-		{startIndex: 2, type: 'comment.pats'}
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'local',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pats' }
-	]}, {
-	line: 'var __count: int = 0 // it is statically allocated',
-	tokens: [
-        { startIndex: 0, type: 'keyword.pats' },
-		{ startIndex: 3, type: '' },
-        { startIndex: 4, type: 'identifier.pats' },
-        { startIndex: 11, type: 'keyword.pats' },
-        { startIndex: 12, type: '' },
-        { startIndex: 13, type: 'type.pats' },
-        { startIndex: 16, type: '' },
-        { startIndex: 17, type: 'keyword.pats' },
-        { startIndex: 18, type: '' },
-        { startIndex: 19, type: 'number.decimal.pats' },
-        { startIndex: 20, type: '' },
-        { startIndex: 21, type: 'comment.pats' }
-	]}, {
-	line: '',
-	tokens: [
-	]}, {
-	line: 'val theCount =',
-	tokens: [
-        { startIndex: 0, type: 'keyword.pats' },
-        { startIndex: 3, type: '' },
-        { startIndex: 4, type: 'identifier.pats' },
-		{ startIndex: 12, type: '' },
-        { startIndex: 13, type: 'keyword.pats' }
-	]}, {
-	line: '  ref_make_viewptr{int}(view@(__count) | addr@(__count))',
-	tokens: [
-        { startIndex: 0, type: '' },
-        { startIndex: 2, type: 'identifier.pats' },
-        { startIndex: 18, type: 'delimiter.curly.pats' },
-        { startIndex: 19, type: 'type.pats' },
-        { startIndex: 22, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 24, type: 'keyword.pats' },
-        { startIndex: 29, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 30, type: 'identifier.pats' },
-        { startIndex: 37, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 38, type: '' },
-        { startIndex: 39, type: 'keyword.pats' },
-        { startIndex: 40, type: '' },
-        { startIndex: 41, type: 'keyword.pats' },
-		{ startIndex: 46, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 47, type: 'identifier.pats' },
-        { startIndex: 54, type: 'delimiter.parenthesis.pats' },
-	]}, {
-	line: '// end of [val]',
-	tokens: [
-		{ startIndex: 0, type: 'comment.pats' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'in (* in of [local] *)',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pats' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'comment.pats' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'fun theCount_get (): int = !theCount',
-	tokens: [
-        { startIndex: 0, type: 'keyword.pats' },
-        { startIndex: 3, type: '' },
-        { startIndex: 4, type: 'identifier.pats' },
-        { startIndex: 16, type: '' },
-        { startIndex: 17, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 19, type: 'keyword.pats' },
-        { startIndex: 20, type: '' },
-        { startIndex: 21, type: 'type.pats' },
-        { startIndex: 24, type: '' },
-        { startIndex: 25, type: 'keyword.pats' },
-		{ startIndex: 26, type: '' },
-        { startIndex: 27, type: 'keyword.pats' },
-        { startIndex: 28, type: 'identifier.pats' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'fun theCount_inc (): void = !theCount := !theCount + 1',
-	tokens: [
-        { startIndex: 0, type: 'keyword.pats' },
-        { startIndex: 3, type: '' },
-        { startIndex: 4, type: 'identifier.pats' },
-        { startIndex: 16, type: '' },
-        { startIndex: 17, type: 'delimiter.parenthesis.pats' },
-        { startIndex: 19, type: 'keyword.pats' },
-		{ startIndex: 20, type: '' },
-        { startIndex: 21, type: 'type.pats' },
-        { startIndex: 25, type: '' },
-        { startIndex: 26, type: 'keyword.pats' },
-        { startIndex: 27, type: '' },
-        { startIndex: 28, type: 'keyword.pats' },
-        { startIndex: 29, type: 'identifier.pats' },
-        { startIndex: 37, type: '' },
-        { startIndex: 38, type: 'operator.pats' },
-        { startIndex: 40, type: '' },
-        { startIndex: 41, type: 'keyword.pats' },
-		{ startIndex: 42, type: 'identifier.pats' },
-        { startIndex: 50, type: '' },
-        { startIndex: 51, type: 'operator.pats' },
-        { startIndex: 52, type: '' },
-        { startIndex: 53, type: 'number.decimal.pats' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: 'end // end of [local]',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pats' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.pats' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '#endif',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.srp.pats' }
-	]}]
+		line: '#include "/path/to/my/file.h"',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.srp.pats' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'string.quote.pats' },
+			{ startIndex: 10, type: 'string.pats' },
+			{ startIndex: 28, type: 'string.quote.pats' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '#ifdef VAR #then',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.srp.pats' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.pats' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'keyword.srp.pats' }
+		]
+	}, {
+		line: '#define SUM(A,B) (A) + (B)',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.srp.pats' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.pats' },
+			{ startIndex: 11, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 12, type: 'identifier.pats' },
+			{ startIndex: 13, type: 'delimiter.comma.pats' },
+			{ startIndex: 14, type: 'identifier.pats' },
+			{ startIndex: 15, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 18, type: 'identifier.pats' },
+			{ startIndex: 19, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'operator.pats' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 24, type: 'identifier.pats' },
+			{ startIndex: 25, type: 'delimiter.parenthesis.pats' }
+		]
+	}, {
+		line: 'staload Asdf_CDE = "./myfile.sats"',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.pats' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'keyword.pats' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'string.quote.pats' },
+			{ startIndex: 20, type: 'string.pats' },
+			{ startIndex: 33, type: 'string.quote.pats' },
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'implement main(argc, argv)',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.pats' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 15, type: 'identifier.pats' },
+			{ startIndex: 19, type: 'delimiter.comma.pats' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'identifier.pats' },
+			{ startIndex: 25, type: 'delimiter.parenthesis.pats' }
+		]
+	}, {
+		line: ' = begin',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'keyword.pats' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'keyword.pats' }
+		]
+	}, {
+		line: '0',
+		tokens: [
+			{ startIndex: 0, type: 'number.decimal.pats' },
+		]
+	}, {
+		line: 'end',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'dataprop FACT (int, int) =',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'identifier.pats' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 15, type: 'type.pats' },
+			{ startIndex: 18, type: 'delimiter.comma.pats' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'type.pats' },
+			{ startIndex: 23, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'keyword.pats' }
+		]
+	}, {
+		line: ' | FACTbas (0, 1) of ()',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'keyword.pats' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'identifier.pats' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 12, type: 'number.decimal.pats' },
+			{ startIndex: 13, type: 'delimiter.comma.pats' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'number.decimal.pats' },
+			{ startIndex: 16, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'keyword.pats' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'delimiter.parenthesis.pats' }
+		]
+	}, {
+		line: ' | {n:pos}{r:int} FACTind (n, n*r) of FACT (n-1, r)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'keyword.pats' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'delimiter.curly.pats' },
+			{ startIndex: 4, type: 'identifier.pats' },
+			{ startIndex: 5, type: 'keyword.pats' },
+			{ startIndex: 6, type: 'identifier.pats' },
+			{ startIndex: 9, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 10, type: 'delimiter.curly.pats' },
+			{ startIndex: 11, type: 'identifier.pats' },
+			{ startIndex: 12, type: 'keyword.pats' },
+			{ startIndex: 13, type: 'type.pats' },
+			{ startIndex: 16, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'identifier.pats' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 27, type: 'identifier.pats' },
+			{ startIndex: 28, type: 'delimiter.comma.pats' },
+			{ startIndex: 29, type: '' },
+			{ startIndex: 30, type: 'identifier.pats' },
+			{ startIndex: 31, type: 'operator.pats' },
+			{ startIndex: 32, type: 'identifier.pats' },
+			{ startIndex: 33, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 34, type: '' },
+			{ startIndex: 35, type: 'keyword.pats' },
+			{ startIndex: 37, type: '' },
+			{ startIndex: 38, type: 'identifier.pats' },
+			{ startIndex: 42, type: '' },
+			{ startIndex: 43, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 44, type: 'identifier.pats' },
+			{ startIndex: 45, type: 'operator.pats' },
+			{ startIndex: 46, type: 'number.decimal.pats' },
+			{ startIndex: 47, type: 'delimiter.comma.pats' },
+			{ startIndex: 48, type: '' },
+			{ startIndex: 49, type: 'identifier.pats' },
+			{ startIndex: 50, type: 'delimiter.parenthesis.pats' },
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'fun fact {n:nat} .<n>. (x: int n) : [r:int] (FACT(n, r) | int(r)) = (',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.pats' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.curly.pats' },
+			{ startIndex: 10, type: 'identifier.pats' },
+			{ startIndex: 11, type: 'keyword.pats' },
+			{ startIndex: 12, type: 'identifier.pats' },
+			{ startIndex: 15, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'identifier.sym.pats' },
+			{ startIndex: 19, type: 'identifier.pats' },
+			{ startIndex: 20, type: 'keyword.pats' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 24, type: 'identifier.pats' },
+			{ startIndex: 25, type: 'keyword.pats' },
+			{ startIndex: 26, type: '' },
+			{ startIndex: 27, type: 'type.pats' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'identifier.pats' },
+			{ startIndex: 32, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 33, type: '' },
+			{ startIndex: 34, type: 'keyword.pats' },
+			{ startIndex: 35, type: '' },
+			{ startIndex: 36, type: 'delimiter.square.pats' },
+			{ startIndex: 37, type: 'identifier.pats' },
+			{ startIndex: 38, type: 'keyword.pats' },
+			{ startIndex: 39, type: 'type.pats' },
+			{ startIndex: 42, type: 'delimiter.square.pats' },
+			{ startIndex: 43, type: '' },
+			{ startIndex: 44, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 45, type: 'identifier.pats' },
+			{ startIndex: 49, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 50, type: 'identifier.pats' },
+			{ startIndex: 51, type: 'delimiter.comma.pats' },
+			{ startIndex: 52, type: '' },
+			{ startIndex: 53, type: 'identifier.pats' },
+			{ startIndex: 54, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 55, type: '' },
+			{ startIndex: 56, type: 'keyword.pats' },
+			{ startIndex: 57, type: '' },
+			{ startIndex: 58, type: 'type.pats' },
+			{ startIndex: 61, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 62, type: 'identifier.pats' },
+			{ startIndex: 63, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 65, type: '' },
+			{ startIndex: 66, type: 'keyword.pats' },
+			{ startIndex: 67, type: '' },
+			{ startIndex: 68, type: 'delimiter.parenthesis.pats' },
+		]
+	}, {
+		line: 'if x > 0 then let',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'identifier.pats' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'keyword.pats' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'number.decimal.pats' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'keyword.pats' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'keyword.pats' },
+		]
+	}, {
+		line: '  val [r1:int] (pf1 | r1) = fact (x-1)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.pats' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.square.pats' },
+			{ startIndex: 7, type: 'identifier.pats' },
+			{ startIndex: 9, type: 'keyword.pats' },
+			{ startIndex: 10, type: 'type.pats' },
+			{ startIndex: 13, type: 'delimiter.square.pats' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 16, type: 'identifier.pats' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'keyword.pats' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'identifier.pats' },
+			{ startIndex: 24, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'keyword.pats' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'identifier.pats' },
+			{ startIndex: 32, type: '' },
+			{ startIndex: 33, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 34, type: 'identifier.pats' },
+			{ startIndex: 35, type: 'operator.pats' },
+			{ startIndex: 36, type: 'number.decimal.pats' },
+			{ startIndex: 37, type: 'delimiter.parenthesis.pats' },
+		]
+	}, {
+		line: '  prval pf = FACTind {n}{r1} (pf1)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.pats' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.pats' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'keyword.pats' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'identifier.pats' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'delimiter.curly.pats' },
+			{ startIndex: 22, type: 'identifier.pats' },
+			{ startIndex: 23, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 24, type: 'delimiter.curly.pats' },
+			{ startIndex: 25, type: 'identifier.pats' },
+			{ startIndex: 27, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 28, type: '' },
+			{ startIndex: 29, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 30, type: 'identifier.pats' },
+			{ startIndex: 33, type: 'delimiter.parenthesis.pats' }
+		]
+	}, {
+		line: '  val r = x * r1',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.pats' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'identifier.pats' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'keyword.pats' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.pats' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'operator.pats' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'identifier.pats' }
+		]
+	}, {
+		line: 'in',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' }
+		]
+	}, {
+		line: '  (pf | r)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 3, type: 'identifier.pats' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.pats' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.pats' },
+			{ startIndex: 9, type: 'delimiter.parenthesis.pats' }
+		]
+	}, {
+		line: 'end // end of [then]',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.pats' }
+		]
+	}, {
+		line: 'else (FACTbas () | 1)',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 6, type: 'identifier.pats' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'keyword.pats' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'number.decimal.pats' },
+			{ startIndex: 20, type: 'delimiter.parenthesis.pats' }
+		]
+	}, {
+		line: ') (* end of [fact] *)',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'comment.pats' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'local',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' }
+		]
+	}, {
+		line: 'var __count: int = 0 // it is statically allocated',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.pats' },
+			{ startIndex: 11, type: 'keyword.pats' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'type.pats' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'keyword.pats' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'number.decimal.pats' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'comment.pats' }
+		]
+	}, {
+		line: '',
+		tokens: [
+		]
+	}, {
+		line: 'val theCount =',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.pats' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'keyword.pats' }
+		]
+	}, {
+		line: '  ref_make_viewptr{int}(view@(__count) | addr@(__count))',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'identifier.pats' },
+			{ startIndex: 18, type: 'delimiter.curly.pats' },
+			{ startIndex: 19, type: 'type.pats' },
+			{ startIndex: 22, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 24, type: 'keyword.pats' },
+			{ startIndex: 29, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 30, type: 'identifier.pats' },
+			{ startIndex: 37, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 38, type: '' },
+			{ startIndex: 39, type: 'keyword.pats' },
+			{ startIndex: 40, type: '' },
+			{ startIndex: 41, type: 'keyword.pats' },
+			{ startIndex: 46, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 47, type: 'identifier.pats' },
+			{ startIndex: 54, type: 'delimiter.parenthesis.pats' },
+		]
+	}, {
+		line: '// end of [val]',
+		tokens: [
+			{ startIndex: 0, type: 'comment.pats' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'in (* in of [local] *)',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'comment.pats' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'fun theCount_get (): int = !theCount',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.pats' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 19, type: 'keyword.pats' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'type.pats' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'keyword.pats' },
+			{ startIndex: 26, type: '' },
+			{ startIndex: 27, type: 'keyword.pats' },
+			{ startIndex: 28, type: 'identifier.pats' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'fun theCount_inc (): void = !theCount := !theCount + 1',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.pats' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'delimiter.parenthesis.pats' },
+			{ startIndex: 19, type: 'keyword.pats' },
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'type.pats' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'keyword.pats' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'keyword.pats' },
+			{ startIndex: 29, type: 'identifier.pats' },
+			{ startIndex: 37, type: '' },
+			{ startIndex: 38, type: 'operator.pats' },
+			{ startIndex: 40, type: '' },
+			{ startIndex: 41, type: 'keyword.pats' },
+			{ startIndex: 42, type: 'identifier.pats' },
+			{ startIndex: 50, type: '' },
+			{ startIndex: 51, type: 'operator.pats' },
+			{ startIndex: 52, type: '' },
+			{ startIndex: 53, type: 'number.decimal.pats' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'end // end of [local]',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pats' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.pats' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '#endif',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.srp.pats' }
+		]
+	}]
 ]);

+ 781 - 682
test/powershell.test.ts

@@ -5,733 +5,832 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('powershell', [
 	// Comments - single line
 	[{
-	line: '#',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}],
-
-	[{
-	line: '    # a comment',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'comment.ps1' }
-	]}],
-
-	[{
-	line: '# a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}],
-
-	[{
-	line: '#sticky comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}],
-
-	[{
-	line: '##still a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}],
-
-	[{
-	line: '1 / 2 /# comment',
-	tokens: [
-		{ startIndex: 0, type: 'number.ps1' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.ps1' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.ps1' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.ps1' },
-		{ startIndex: 7, type: 'comment.ps1' }
-	]}],
-
-	[{
-	line: '$x = 1 # my comment # is a nice one',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'delimiter.ps1' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'number.ps1' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'comment.ps1' }
-	]}],
+		line: '#',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}],
+
+	[{
+		line: '    # a comment',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'comment.ps1' }
+		]
+	}],
+
+	[{
+		line: '# a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}],
+
+	[{
+		line: '#sticky comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}],
+
+	[{
+		line: '##still a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}],
+
+	[{
+		line: '1 / 2 /# comment',
+		tokens: [
+			{ startIndex: 0, type: 'number.ps1' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.ps1' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.ps1' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.ps1' },
+			{ startIndex: 7, type: 'comment.ps1' }
+		]
+	}],
+
+	[{
+		line: '$x = 1 # my comment # is a nice one',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'delimiter.ps1' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'number.ps1' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'comment.ps1' }
+		]
+	}],
 
 	// Comments - range comment, single line
 	[{
-	line: '<# a simple comment #>',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}],
-
-	[{
-	line: '$x = <# a simple comment #> 1',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'delimiter.ps1' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'comment.ps1' },
-		{ startIndex: 27, type: '' },
-		{ startIndex: 28, type: 'number.ps1' }
-	]}],
-
-	[{
-	line: '$yy = <# comment #> 14',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.ps1' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'comment.ps1' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'number.ps1' }
-	]}],
-
-	[{
-	line: '$x = <##>7',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'delimiter.ps1' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'comment.ps1' },
-		{ startIndex: 9, type: 'number.ps1' }
-	]}],
-
-	[{
-	line: '$x = <#<85',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'delimiter.ps1' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'comment.ps1' }
-	]}],
+		line: '<# a simple comment #>',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}],
+
+	[{
+		line: '$x = <# a simple comment #> 1',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'delimiter.ps1' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'comment.ps1' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'number.ps1' }
+		]
+	}],
+
+	[{
+		line: '$yy = <# comment #> 14',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.ps1' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.ps1' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'number.ps1' }
+		]
+	}],
+
+	[{
+		line: '$x = <##>7',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'delimiter.ps1' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'comment.ps1' },
+			{ startIndex: 9, type: 'number.ps1' }
+		]
+	}],
+
+	[{
+		line: '$x = <#<85',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'delimiter.ps1' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'comment.ps1' }
+		]
+	}],
 
 	// Comments - range comment, multiple lines
 	[{
-	line: '<# start of multiline comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}, {
-	line: 'a comment between',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}, {
-	line: 'end of multiline comment#>',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}],
-
-	[{
-	line: '$x = <# start a comment',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'delimiter.ps1' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'comment.ps1' }
-	]}, {
-	line: ' a ',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}, {
-	line: 'and end it #> 2',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'number.ps1' }
-	]}],
+		line: '<# start of multiline comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}, {
+		line: 'a comment between',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}, {
+		line: 'end of multiline comment#>',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}],
+
+	[{
+		line: '$x = <# start a comment',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'delimiter.ps1' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'comment.ps1' }
+		]
+	}, {
+		line: ' a ',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}, {
+		line: 'and end it #> 2',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'number.ps1' }
+		]
+	}],
 
 	// Keywords
 	[{
-	line: 'foreach($i in $b) {if (7) continue}',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.foreach.ps1' },
-		{ startIndex: 7, type: 'delimiter.parenthesis.ps1' },
-		{ startIndex: 8, type: 'variable.ps1' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'keyword.in.ps1' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'variable.ps1' },
-		{ startIndex: 16, type: 'delimiter.parenthesis.ps1' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: 'delimiter.curly.ps1' },
-		{ startIndex: 19, type: 'keyword.if.ps1' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'delimiter.parenthesis.ps1' },
-		{ startIndex: 23, type: 'number.ps1' },
-		{ startIndex: 24, type: 'delimiter.parenthesis.ps1' },
-		{ startIndex: 25, type: '' },
-		{ startIndex: 26, type: 'keyword.continue.ps1' },
-		{ startIndex: 34, type: 'delimiter.curly.ps1' }
-	]}],
+		line: 'foreach($i in $b) {if (7) continue}',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.foreach.ps1' },
+			{ startIndex: 7, type: 'delimiter.parenthesis.ps1' },
+			{ startIndex: 8, type: 'variable.ps1' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'keyword.in.ps1' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'variable.ps1' },
+			{ startIndex: 16, type: 'delimiter.parenthesis.ps1' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'delimiter.curly.ps1' },
+			{ startIndex: 19, type: 'keyword.if.ps1' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'delimiter.parenthesis.ps1' },
+			{ startIndex: 23, type: 'number.ps1' },
+			{ startIndex: 24, type: 'delimiter.parenthesis.ps1' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'keyword.continue.ps1' },
+			{ startIndex: 34, type: 'delimiter.curly.ps1' }
+		]
+	}],
 
 	// Redirect operand
 	[{
-	line: '$i > output1.txt',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'delimiter.ps1' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 12, type: 'delimiter.ps1' },
-		{ startIndex: 13, type: '' }
-	]}],
+		line: '$i > output1.txt',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'delimiter.ps1' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 12, type: 'delimiter.ps1' },
+			{ startIndex: 13, type: '' }
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '0',
-	tokens: [
-		{ startIndex: 0, type: 'number.ps1' }
-	]}],
+		line: '0',
+		tokens: [
+			{ startIndex: 0, type: 'number.ps1' }
+		]
+	}],
 
 	[{
-	line: '0.10',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.ps1' }
-	]}],
+		line: '0.10',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.ps1' }
+		]
+	}],
 
 	[{
-	line: '0X123',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.ps1' }
-	]}],
+		line: '0X123',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.ps1' }
+		]
+	}],
 
 	[{
-	line: '0x123',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.ps1' }
-	]}],
+		line: '0x123',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.ps1' }
+		]
+	}],
 
 	[{
-	line: '23.5e3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.ps1' }
-	]}],
+		line: '23.5e3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.ps1' }
+		]
+	}],
 
 	[{
-	line: '23.5e-3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.ps1' }
-	]}],
+		line: '23.5e-3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.ps1' }
+		]
+	}],
 
 	[{
-	line: '23.5E3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.ps1' }
-	]}],
+		line: '23.5E3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.ps1' }
+		]
+	}],
 
 	[{
-	line: '23.5E-3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.ps1' }
-	]}],
+		line: '23.5E-3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.ps1' }
+		]
+	}],
 
 	[{
-	line: '23.5',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.ps1' }
-	]}],
+		line: '23.5',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.ps1' }
+		]
+	}],
 
 	[{
-	line: '0+0',
-	tokens: [
-		{ startIndex: 0, type: 'number.ps1' },
-		{ startIndex: 1, type: 'delimiter.ps1' },
-		{ startIndex: 2, type: 'number.ps1' }
-	]}],
+		line: '0+0',
+		tokens: [
+			{ startIndex: 0, type: 'number.ps1' },
+			{ startIndex: 1, type: 'delimiter.ps1' },
+			{ startIndex: 2, type: 'number.ps1' }
+		]
+	}],
 
 	[{
-	line: '100+10',
-	tokens: [
-		{ startIndex: 0, type: 'number.ps1' },
-		{ startIndex: 3, type: 'delimiter.ps1' },
-		{ startIndex: 4, type: 'number.ps1' }
-	]}],
+		line: '100+10',
+		tokens: [
+			{ startIndex: 0, type: 'number.ps1' },
+			{ startIndex: 3, type: 'delimiter.ps1' },
+			{ startIndex: 4, type: 'number.ps1' }
+		]
+	}],
 
 	[{
-	line: '10 + 0',
-	tokens: [
-		{ startIndex: 0, type: 'number.ps1' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'delimiter.ps1' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'number.ps1' }
-	]}],
+		line: '10 + 0',
+		tokens: [
+			{ startIndex: 0, type: 'number.ps1' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'delimiter.ps1' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'number.ps1' }
+		]
+	}],
 
 	// Strings
 	[{
-	line: '$s = "I am a String"',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'delimiter.ps1' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'string.ps1' }
-	]}],
-
-	[{
-	line: '\'I am also a ( String\'',
-	tokens: [
-		{ startIndex: 0, type: 'string.ps1' }
-	]}],
-
-	[{
-	line: '$s = "concatenated" + " String"',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'delimiter.ps1' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'string.ps1' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'delimiter.ps1' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'string.ps1' }
-	]}],
-
-	[{
-	line: '"escaping `"quotes`" is cool"',
-	tokens: [
-		{ startIndex: 0, type: 'string.ps1' },
-		{ startIndex: 10, type: 'string.escape.ps1' },
-		{ startIndex: 12, type: 'string.ps1' },
-		{ startIndex: 18, type: 'string.escape.ps1' },
-		{ startIndex: 20, type: 'string.ps1' }
-	]}],
-
-	[{
-	line: '\'`\'end of the string',
-	tokens: [
-		{ startIndex: 0, type: 'string.ps1' },
-		{ startIndex: 1, type: 'string.escape.ps1' },
-		{ startIndex: 3, type: 'string.ps1' }
-	]}],
-
-	[{
-	line: '@"I am an expandable String"@',
-	tokens: [
-		{ startIndex: 0, type: 'string.ps1' }
-	]}],
-
-	[{
-	line: '@\'I am also an expandable String\'@',
-	tokens: [
-		{ startIndex: 0, type: 'string.ps1' }
-	]}],
-
-	[{
-	line: '$s = @\'I am also an expandable String\'@',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'delimiter.ps1' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'string.ps1' }
-	]}],
-
-	[{
-	line: '$s = @\'I am also an expandable String\'@+7',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'delimiter.ps1' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'string.ps1' }
-	]}],
-
-	[{
-	line: '@\'I am a multiline string,',
-	tokens: [
-		{ startIndex: 0, type: 'string.ps1' }
-	]}, {
-	line: 'and this is the middle line,',
-	tokens: [
-		{ startIndex: 0, type: 'string.ps1' }
-	]}, {
-	line: 'and this is NOT the end of the string\'@foreach $i',
-	tokens: [
-		{ startIndex: 0, type: 'string.ps1' }
-	]}, {
-	line: '\'@',
-	tokens: [
-		{ startIndex: 0, type: 'string.ps1' }
-	]}, {
-	line: '${script:foo}',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' }
-	]}, {
-	line: 'foreach $i',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.foreach.ps1' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'variable.ps1' }
-	]}],
+		line: '$s = "I am a String"',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'delimiter.ps1' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'string.ps1' }
+		]
+	}],
+
+	[{
+		line: '\'I am also a ( String\'',
+		tokens: [
+			{ startIndex: 0, type: 'string.ps1' }
+		]
+	}],
+
+	[{
+		line: '$s = "concatenated" + " String"',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'delimiter.ps1' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'string.ps1' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'delimiter.ps1' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'string.ps1' }
+		]
+	}],
+
+	[{
+		line: '"escaping `"quotes`" is cool"',
+		tokens: [
+			{ startIndex: 0, type: 'string.ps1' },
+			{ startIndex: 10, type: 'string.escape.ps1' },
+			{ startIndex: 12, type: 'string.ps1' },
+			{ startIndex: 18, type: 'string.escape.ps1' },
+			{ startIndex: 20, type: 'string.ps1' }
+		]
+	}],
+
+	[{
+		line: '\'`\'end of the string',
+		tokens: [
+			{ startIndex: 0, type: 'string.ps1' },
+			{ startIndex: 1, type: 'string.escape.ps1' },
+			{ startIndex: 3, type: 'string.ps1' }
+		]
+	}],
+
+	[{
+		line: '@"I am an expandable String"@',
+		tokens: [
+			{ startIndex: 0, type: 'string.ps1' }
+		]
+	}],
+
+	[{
+		line: '@\'I am also an expandable String\'@',
+		tokens: [
+			{ startIndex: 0, type: 'string.ps1' }
+		]
+	}],
+
+	[{
+		line: '$s = @\'I am also an expandable String\'@',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'delimiter.ps1' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'string.ps1' }
+		]
+	}],
+
+	[{
+		line: '$s = @\'I am also an expandable String\'@+7',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'delimiter.ps1' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'string.ps1' }
+		]
+	}],
+
+	[{
+		line: '@\'I am a multiline string,',
+		tokens: [
+			{ startIndex: 0, type: 'string.ps1' }
+		]
+	}, {
+		line: 'and this is the middle line,',
+		tokens: [
+			{ startIndex: 0, type: 'string.ps1' }
+		]
+	}, {
+		line: 'and this is NOT the end of the string\'@foreach $i',
+		tokens: [
+			{ startIndex: 0, type: 'string.ps1' }
+		]
+	}, {
+		line: '\'@',
+		tokens: [
+			{ startIndex: 0, type: 'string.ps1' }
+		]
+	}, {
+		line: '${script:foo}',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' }
+		]
+	}, {
+		line: 'foreach $i',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.foreach.ps1' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'variable.ps1' }
+		]
+	}],
 
 	// Generated from sample
 	[{
-	line: '$SelectedObjectNames=@();',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 20, type: 'delimiter.ps1' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'delimiter.parenthesis.ps1' },
-		{ startIndex: 24, type: 'delimiter.ps1' }
-	]}, {
-	line: '$XenCenterNodeSelected = 0;',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'delimiter.ps1' },
-		{ startIndex: 24, type: '' },
-		{ startIndex: 25, type: 'number.ps1' },
-		{ startIndex: 26, type: 'delimiter.ps1' }
-	]}, {
-	line: '#the object info array contains hashmaps, each of which represent a parameter set and describe a target in the XenCenter resource list',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}, {
-	line: 'foreach($parameterSet in $ObjInfoArray)',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.foreach.ps1' },
-		{ startIndex: 7, type: 'delimiter.parenthesis.ps1' },
-		{ startIndex: 8, type: 'variable.ps1' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'keyword.in.ps1' },
-		{ startIndex: 24, type: '' },
-		{ startIndex: 25, type: 'variable.ps1' },
-		{ startIndex: 38, type: 'delimiter.parenthesis.ps1' }
-	]}, {
-	line: '{',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.ps1' }
-	]}, {
-	line: '	if ($parameterSet["class"] -eq "blank")',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'keyword.if.ps1' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'delimiter.parenthesis.ps1' },
-		{ startIndex: 5, type: 'variable.ps1' },
-		{ startIndex: 18, type: 'delimiter.square.ps1' },
-		{ startIndex: 19, type: 'string.ps1' },
-		{ startIndex: 26, type: 'delimiter.square.ps1' },
-		{ startIndex: 27, type: '' },
-		{ startIndex: 28, type: 'delimiter.ps1' },
-		{ startIndex: 29, type: '' },
-		{ startIndex: 32, type: 'string.ps1' },
-		{ startIndex: 39, type: 'delimiter.parenthesis.ps1' }
-	]}, {
-	line: '	{',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.curly.ps1' }
-	]}, {
-	line: '		#When the XenCenter node is selected a parameter set is created for each of your connected servers with the class and objUuid keys marked as blank',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'comment.ps1' }
-	]}, {
-	line: '		if ($XenCenterNodeSelected)',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'keyword.if.ps1' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'delimiter.parenthesis.ps1' },
-		{ startIndex: 6, type: 'variable.ps1' },
-		{ startIndex: 28, type: 'delimiter.parenthesis.ps1' }
-	]}, {
-	line: '		{',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.curly.ps1' }
-	]}, {
-	line: '			continue',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 3, type: 'keyword.continue.ps1' }
-	]}, {
-	line: '		}',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.curly.ps1' }
-	]}, {
-	line: '		$XenCenterNodeSelected = 1;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'variable.ps1' },
-		{ startIndex: 24, type: '' },
-		{ startIndex: 25, type: 'delimiter.ps1' },
-		{ startIndex: 26, type: '' },
-		{ startIndex: 27, type: 'number.ps1' },
-		{ startIndex: 28, type: 'delimiter.ps1' }
-	]}, {
-	line: '		$SelectedObjectNames += "XenCenter"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'variable.ps1' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'delimiter.ps1' },
-		{ startIndex: 25, type: '' },
-		{ startIndex: 26, type: 'string.ps1' }
-	]}, {
-	line: '	}',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.curly.ps1' }
-	]}, {
-	line: '	elseif ($parameterSet["sessionRef"] -eq "null")',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'keyword.elseif.ps1' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'delimiter.parenthesis.ps1' },
-		{ startIndex: 9, type: 'variable.ps1' },
-		{ startIndex: 22, type: 'delimiter.square.ps1' },
-		{ startIndex: 23, type: 'string.ps1' },
-		{ startIndex: 35, type: 'delimiter.square.ps1' },
-		{ startIndex: 36, type: '' },
-		{ startIndex: 37, type: 'delimiter.ps1' },
-		{ startIndex: 38, type: '' },
-		{ startIndex: 41, type: 'string.ps1' },
-		{ startIndex: 47, type: 'delimiter.parenthesis.ps1' }
-	]}, {
-	line: '	{',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.curly.ps1' }
-	]}, {
-	line: '		#When a disconnected server is selected there is no session information, we get null for everything except class',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'comment.ps1' }
-	]}, {
-	line: '	}',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.curly.ps1' }
-	]}, {
-	line: '		$SelectedObjectNames += "a disconnected server"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'variable.ps1' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'delimiter.ps1' },
-		{ startIndex: 25, type: '' },
-		{ startIndex: 26, type: 'string.ps1' }
-	]}, {
-	line: '	else',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'keyword.else.ps1' }
-	]}, {
-	line: '	{',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.curly.ps1' }
-	]}, {
-	line: '		Connect-XenServer -url $parameterSet["url"] -opaqueref $parameterSet["sessionRef"]',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 20, type: 'delimiter.ps1' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 25, type: 'variable.ps1' },
-		{ startIndex: 38, type: 'delimiter.square.ps1' },
-		{ startIndex: 39, type: 'string.ps1' },
-		{ startIndex: 44, type: 'delimiter.square.ps1' },
-		{ startIndex: 45, type: '' },
-		{ startIndex: 46, type: 'delimiter.ps1' },
-		{ startIndex: 47, type: '' },
-		{ startIndex: 57, type: 'variable.ps1' },
-		{ startIndex: 70, type: 'delimiter.square.ps1' },
-		{ startIndex: 71, type: 'string.ps1' },
-		{ startIndex: 83, type: 'delimiter.square.ps1' }
-	]}, {
-	line: '		#Use $class to determine which server objects to get',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'comment.ps1' }
-	]}, {
-	line: '		#-properties allows us to filter the results to just include the selected object',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'comment.ps1' }
-	]}, {
-	line: '		$exp = "Get-XenServer:{0} -properties @{{uuid=\'{1}\'}}" -f $parameterSet["class"], $parameterSet["objUuid"]',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'variable.ps1' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'delimiter.ps1' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'string.ps1' },
-		{ startIndex: 56, type: '' },
-		{ startIndex: 57, type: 'delimiter.ps1' },
-		{ startIndex: 58, type: '' },
-		{ startIndex: 60, type: 'variable.ps1' },
-		{ startIndex: 73, type: 'delimiter.square.ps1' },
-		{ startIndex: 74, type: 'string.ps1' },
-		{ startIndex: 81, type: 'delimiter.square.ps1' },
-		{ startIndex: 82, type: 'delimiter.ps1' },
-		{ startIndex: 83, type: '' },
-		{ startIndex: 84, type: 'variable.ps1' },
-		{ startIndex: 97, type: 'delimiter.square.ps1' },
-		{ startIndex: 98, type: 'string.ps1' },
-		{ startIndex: 107, type: 'delimiter.square.ps1' }
-	]}, {
-	line: '		$obj = Invoke-Expression $exp',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'variable.ps1' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'delimiter.ps1' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 27, type: 'variable.ps1' }
-	]}, {
-	line: '		$SelectedObjectNames += $obj.name_label;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'variable.ps1' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'delimiter.ps1' },
-		{ startIndex: 25, type: '' },
-		{ startIndex: 26, type: 'variable.ps1' },
-		{ startIndex: 30, type: 'delimiter.ps1' },
-		{ startIndex: 31, type: '' },
-		{ startIndex: 41, type: 'delimiter.ps1' }
-	]}, {
-	line: '	} ',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.curly.ps1' },
-		{ startIndex: 2, type: '' }
-	]}, {
-	line: '}',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.curly.ps1' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '$test = "in string var$test"',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.ps1' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'string.ps1' },
-		{ startIndex: 22, type: 'variable.ps1' },
-		{ startIndex: 27, type: 'string.ps1' }
-	]}, {
-	line: '$another = \'not a $var\'',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'delimiter.ps1' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'string.ps1' }
-	]}, {
-	line: '$third = "a $var and not `$var string"',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'delimiter.ps1' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'string.ps1' },
-		{ startIndex: 12, type: 'variable.ps1' },
-		{ startIndex: 16, type: 'string.ps1' },
-		{ startIndex: 25, type: 'string.escape.ps1' },
-		{ startIndex: 27, type: 'string.ps1' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: ':aLabel',
-	tokens: [
-		{ startIndex: 0, type: 'metatag.ps1' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '<#',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}, {
-	line: '.SYNOPSIS',
-	tokens: [
-		{ startIndex: 0, type: 'comment.keyword.synopsis.ps1' }
-	]}, {
-	line: '  some text',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}, {
-	line: '  ',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}, {
-	line: '.LINK',
-	tokens: [
-		{ startIndex: 0, type: 'comment.keyword.link.ps1' }
-	]}, {
-	line: '  some more text',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}, {
-	line: '#>',
-	tokens: [
-		{ startIndex: 0, type: 'comment.ps1' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '$hereString = @"',
-	tokens: [
-		{ startIndex: 0, type: 'variable.ps1' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'delimiter.ps1' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'string.ps1' }
-	]}, {
-	line: '  a string',
-	tokens: [
-		{ startIndex: 0, type: 'string.ps1' }
-	]}, {
-	line: '  still "@ a string $withVar',
-	tokens: [
-		{ startIndex: 0, type: 'string.ps1' },
-		{ startIndex: 20, type: 'variable.ps1' }
-	]}, {
-	line: '  still a string `$noVar',
-	tokens: [
-		{ startIndex: 0, type: 'string.ps1' },
-		{ startIndex: 17, type: 'string.escape.ps1' },
-		{ startIndex: 19, type: 'string.ps1' }
-	]}, {
-	line: '',
-	tokens: [
-
-	]}, {
-	line: '"@ still a string',
-	tokens: [
-		{ startIndex: 0, type: 'string.ps1' },
-		{ startIndex: 2, type: '' }
-	]}]
+		line: '$SelectedObjectNames=@();',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 20, type: 'delimiter.ps1' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'delimiter.parenthesis.ps1' },
+			{ startIndex: 24, type: 'delimiter.ps1' }
+		]
+	}, {
+		line: '$XenCenterNodeSelected = 0;',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'delimiter.ps1' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'number.ps1' },
+			{ startIndex: 26, type: 'delimiter.ps1' }
+		]
+	}, {
+		line: '#the object info array contains hashmaps, each of which represent a parameter set and describe a target in the XenCenter resource list',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}, {
+		line: 'foreach($parameterSet in $ObjInfoArray)',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.foreach.ps1' },
+			{ startIndex: 7, type: 'delimiter.parenthesis.ps1' },
+			{ startIndex: 8, type: 'variable.ps1' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'keyword.in.ps1' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'variable.ps1' },
+			{ startIndex: 38, type: 'delimiter.parenthesis.ps1' }
+		]
+	}, {
+		line: '{',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.ps1' }
+		]
+	}, {
+		line: '	if ($parameterSet["class"] -eq "blank")',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'keyword.if.ps1' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'delimiter.parenthesis.ps1' },
+			{ startIndex: 5, type: 'variable.ps1' },
+			{ startIndex: 18, type: 'delimiter.square.ps1' },
+			{ startIndex: 19, type: 'string.ps1' },
+			{ startIndex: 26, type: 'delimiter.square.ps1' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'delimiter.ps1' },
+			{ startIndex: 29, type: '' },
+			{ startIndex: 32, type: 'string.ps1' },
+			{ startIndex: 39, type: 'delimiter.parenthesis.ps1' }
+		]
+	}, {
+		line: '	{',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.curly.ps1' }
+		]
+	}, {
+		line: '		#When the XenCenter node is selected a parameter set is created for each of your connected servers with the class and objUuid keys marked as blank',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'comment.ps1' }
+		]
+	}, {
+		line: '		if ($XenCenterNodeSelected)',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'keyword.if.ps1' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'delimiter.parenthesis.ps1' },
+			{ startIndex: 6, type: 'variable.ps1' },
+			{ startIndex: 28, type: 'delimiter.parenthesis.ps1' }
+		]
+	}, {
+		line: '		{',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.curly.ps1' }
+		]
+	}, {
+		line: '			continue',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 3, type: 'keyword.continue.ps1' }
+		]
+	}, {
+		line: '		}',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.curly.ps1' }
+		]
+	}, {
+		line: '		$XenCenterNodeSelected = 1;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'variable.ps1' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'delimiter.ps1' },
+			{ startIndex: 26, type: '' },
+			{ startIndex: 27, type: 'number.ps1' },
+			{ startIndex: 28, type: 'delimiter.ps1' }
+		]
+	}, {
+		line: '		$SelectedObjectNames += "XenCenter"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'variable.ps1' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'delimiter.ps1' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'string.ps1' }
+		]
+	}, {
+		line: '	}',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.curly.ps1' }
+		]
+	}, {
+		line: '	elseif ($parameterSet["sessionRef"] -eq "null")',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'keyword.elseif.ps1' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.parenthesis.ps1' },
+			{ startIndex: 9, type: 'variable.ps1' },
+			{ startIndex: 22, type: 'delimiter.square.ps1' },
+			{ startIndex: 23, type: 'string.ps1' },
+			{ startIndex: 35, type: 'delimiter.square.ps1' },
+			{ startIndex: 36, type: '' },
+			{ startIndex: 37, type: 'delimiter.ps1' },
+			{ startIndex: 38, type: '' },
+			{ startIndex: 41, type: 'string.ps1' },
+			{ startIndex: 47, type: 'delimiter.parenthesis.ps1' }
+		]
+	}, {
+		line: '	{',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.curly.ps1' }
+		]
+	}, {
+		line: '		#When a disconnected server is selected there is no session information, we get null for everything except class',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'comment.ps1' }
+		]
+	}, {
+		line: '	}',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.curly.ps1' }
+		]
+	}, {
+		line: '		$SelectedObjectNames += "a disconnected server"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'variable.ps1' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'delimiter.ps1' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'string.ps1' }
+		]
+	}, {
+		line: '	else',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'keyword.else.ps1' }
+		]
+	}, {
+		line: '	{',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.curly.ps1' }
+		]
+	}, {
+		line: '		Connect-XenServer -url $parameterSet["url"] -opaqueref $parameterSet["sessionRef"]',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 20, type: 'delimiter.ps1' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 25, type: 'variable.ps1' },
+			{ startIndex: 38, type: 'delimiter.square.ps1' },
+			{ startIndex: 39, type: 'string.ps1' },
+			{ startIndex: 44, type: 'delimiter.square.ps1' },
+			{ startIndex: 45, type: '' },
+			{ startIndex: 46, type: 'delimiter.ps1' },
+			{ startIndex: 47, type: '' },
+			{ startIndex: 57, type: 'variable.ps1' },
+			{ startIndex: 70, type: 'delimiter.square.ps1' },
+			{ startIndex: 71, type: 'string.ps1' },
+			{ startIndex: 83, type: 'delimiter.square.ps1' }
+		]
+	}, {
+		line: '		#Use $class to determine which server objects to get',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'comment.ps1' }
+		]
+	}, {
+		line: '		#-properties allows us to filter the results to just include the selected object',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'comment.ps1' }
+		]
+	}, {
+		line: '		$exp = "Get-XenServer:{0} -properties @{{uuid=\'{1}\'}}" -f $parameterSet["class"], $parameterSet["objUuid"]',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'variable.ps1' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'delimiter.ps1' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'string.ps1' },
+			{ startIndex: 56, type: '' },
+			{ startIndex: 57, type: 'delimiter.ps1' },
+			{ startIndex: 58, type: '' },
+			{ startIndex: 60, type: 'variable.ps1' },
+			{ startIndex: 73, type: 'delimiter.square.ps1' },
+			{ startIndex: 74, type: 'string.ps1' },
+			{ startIndex: 81, type: 'delimiter.square.ps1' },
+			{ startIndex: 82, type: 'delimiter.ps1' },
+			{ startIndex: 83, type: '' },
+			{ startIndex: 84, type: 'variable.ps1' },
+			{ startIndex: 97, type: 'delimiter.square.ps1' },
+			{ startIndex: 98, type: 'string.ps1' },
+			{ startIndex: 107, type: 'delimiter.square.ps1' }
+		]
+	}, {
+		line: '		$obj = Invoke-Expression $exp',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'variable.ps1' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'delimiter.ps1' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 27, type: 'variable.ps1' }
+		]
+	}, {
+		line: '		$SelectedObjectNames += $obj.name_label;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'variable.ps1' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'delimiter.ps1' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'variable.ps1' },
+			{ startIndex: 30, type: 'delimiter.ps1' },
+			{ startIndex: 31, type: '' },
+			{ startIndex: 41, type: 'delimiter.ps1' }
+		]
+	}, {
+		line: '	} ',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.curly.ps1' },
+			{ startIndex: 2, type: '' }
+		]
+	}, {
+		line: '}',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.curly.ps1' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '$test = "in string var$test"',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.ps1' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'string.ps1' },
+			{ startIndex: 22, type: 'variable.ps1' },
+			{ startIndex: 27, type: 'string.ps1' }
+		]
+	}, {
+		line: '$another = \'not a $var\'',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.ps1' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'string.ps1' }
+		]
+	}, {
+		line: '$third = "a $var and not `$var string"',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'delimiter.ps1' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'string.ps1' },
+			{ startIndex: 12, type: 'variable.ps1' },
+			{ startIndex: 16, type: 'string.ps1' },
+			{ startIndex: 25, type: 'string.escape.ps1' },
+			{ startIndex: 27, type: 'string.ps1' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: ':aLabel',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.ps1' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '<#',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}, {
+		line: '.SYNOPSIS',
+		tokens: [
+			{ startIndex: 0, type: 'comment.keyword.synopsis.ps1' }
+		]
+	}, {
+		line: '  some text',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}, {
+		line: '  ',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}, {
+		line: '.LINK',
+		tokens: [
+			{ startIndex: 0, type: 'comment.keyword.link.ps1' }
+		]
+	}, {
+		line: '  some more text',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}, {
+		line: '#>',
+		tokens: [
+			{ startIndex: 0, type: 'comment.ps1' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '$hereString = @"',
+		tokens: [
+			{ startIndex: 0, type: 'variable.ps1' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'delimiter.ps1' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'string.ps1' }
+		]
+	}, {
+		line: '  a string',
+		tokens: [
+			{ startIndex: 0, type: 'string.ps1' }
+		]
+	}, {
+		line: '  still "@ a string $withVar',
+		tokens: [
+			{ startIndex: 0, type: 'string.ps1' },
+			{ startIndex: 20, type: 'variable.ps1' }
+		]
+	}, {
+		line: '  still a string `$noVar',
+		tokens: [
+			{ startIndex: 0, type: 'string.ps1' },
+			{ startIndex: 17, type: 'string.escape.ps1' },
+			{ startIndex: 19, type: 'string.ps1' }
+		]
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: '"@ still a string',
+		tokens: [
+			{ startIndex: 0, type: 'string.ps1' },
+			{ startIndex: 2, type: '' }
+		]
+	}]
 ]);

+ 80 - 68
test/python.test.ts

@@ -5,101 +5,113 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('python', [
 	// Keywords
 	[{
-	line: 'def func():',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.python' },
-		{ startIndex: 3, type: 'white.python' },
-		{ startIndex: 4, type: 'identifier.python' },
-		{ startIndex: 8, type: 'delimiter.parenthesis.python' },
-		{ startIndex: 10, type: 'delimiter.python' }
-	]}],
+		line: 'def func():',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.python' },
+			{ startIndex: 3, type: 'white.python' },
+			{ startIndex: 4, type: 'identifier.python' },
+			{ startIndex: 8, type: 'delimiter.parenthesis.python' },
+			{ startIndex: 10, type: 'delimiter.python' }
+		]
+	}],
 
 	[{
-	line: 'func(str Y3)',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.python' },
-		{ startIndex: 4, type: 'delimiter.parenthesis.python' },
-		{ startIndex: 5, type: 'keyword.python' },
-		{ startIndex: 8, type: 'white.python' },
-		{ startIndex: 9, type: 'identifier.python' },
-		{ startIndex: 11, type: 'delimiter.parenthesis.python' }
-	]}],
+		line: 'func(str Y3)',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.python' },
+			{ startIndex: 4, type: 'delimiter.parenthesis.python' },
+			{ startIndex: 5, type: 'keyword.python' },
+			{ startIndex: 8, type: 'white.python' },
+			{ startIndex: 9, type: 'identifier.python' },
+			{ startIndex: 11, type: 'delimiter.parenthesis.python' }
+		]
+	}],
 
 	[{
-	line: '@Dec0_rator:',
-	tokens: [
-		{ startIndex: 0, type: 'tag.python' },
-		{ startIndex: 11, type: 'delimiter.python' }
-	]}],
+		line: '@Dec0_rator:',
+		tokens: [
+			{ startIndex: 0, type: 'tag.python' },
+			{ startIndex: 11, type: 'delimiter.python' }
+		]
+	}],
 
 	// Comments
 	[{
-	line: ' # Comments! ## "jfkd" ',
-	tokens: [
-		{ startIndex: 0, type: 'white.python' },
-		{ startIndex: 1, type: 'comment.python' }
-	]}],
+		line: ' # Comments! ## "jfkd" ',
+		tokens: [
+			{ startIndex: 0, type: 'white.python' },
+			{ startIndex: 1, type: 'comment.python' }
+		]
+	}],
 
 	// Strings
 	[{
-	line: '\'s0\'',
-	tokens: [
-		{ startIndex: 0, type: 'string.escape.python' },
-		{ startIndex: 1, type: 'string.python' },
-		{ startIndex: 3, type: 'string.escape.python' }
-	]}],
+		line: '\'s0\'',
+		tokens: [
+			{ startIndex: 0, type: 'string.escape.python' },
+			{ startIndex: 1, type: 'string.python' },
+			{ startIndex: 3, type: 'string.escape.python' }
+		]
+	}],
 
 	[{
-	line: '"\' " "',
-	tokens: [
-		{ startIndex: 0, type: 'string.escape.python' },
-		{ startIndex: 1, type: 'string.python' },
-		{ startIndex: 3, type: 'string.escape.python' },
-		{ startIndex: 4, type: 'white.python' },
-		{ startIndex: 5, type: 'string.escape.python' }
-	]}],
+		line: '"\' " "',
+		tokens: [
+			{ startIndex: 0, type: 'string.escape.python' },
+			{ startIndex: 1, type: 'string.python' },
+			{ startIndex: 3, type: 'string.escape.python' },
+			{ startIndex: 4, type: 'white.python' },
+			{ startIndex: 5, type: 'string.escape.python' }
+		]
+	}],
 
 	[{
-	line: '\'\'\'Lots of string\'\'\'',
-	tokens: [
-		{ startIndex: 0, type: 'string.python' }
-	]}],
+		line: '\'\'\'Lots of string\'\'\'',
+		tokens: [
+			{ startIndex: 0, type: 'string.python' }
+		]
+	}],
 
 	[{
-	line: '"""Lots \'\'\'     \'\'\'"""',
-	tokens: [
-		{ startIndex: 0, type: 'string.python' }
-	]}],
+		line: '"""Lots \'\'\'     \'\'\'"""',
+		tokens: [
+			{ startIndex: 0, type: 'string.python' }
+		]
+	}],
 
 	[{
-	line: '\'\'\'Lots \'\'\'0.3e-5',
-	tokens: [
-		{ startIndex: 0, type: 'string.python' },
-		{ startIndex: 11, type: 'number.python' }
-	]}],
+		line: '\'\'\'Lots \'\'\'0.3e-5',
+		tokens: [
+			{ startIndex: 0, type: 'string.python' },
+			{ startIndex: 11, type: 'number.python' }
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '0xAcBFd',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.python' }
-	]}],
+		line: '0xAcBFd',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.python' }
+		]
+	}],
 
 	[{
-	line: '0x0cH',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.python' },
-		{ startIndex: 4, type: 'identifier.python' }
-	]}],
+		line: '0x0cH',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.python' },
+			{ startIndex: 4, type: 'identifier.python' }
+		]
+	}],
 
 	[{
-	line: '456.7e-7j',
-	tokens: [
-		{ startIndex: 0, type: 'number.python' }
-	]}]
+		line: '456.7e-7j',
+		tokens: [
+			{ startIndex: 0, type: 'number.python' }
+		]
+	}]
 ]);

+ 460 - 410
test/r.test.ts

@@ -5,467 +5,517 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('r', [
 	// Keywords
 	[{
-	line: 'function(a) { a }',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.r' },
-		{ startIndex: 8, type: 'delimiter.parenthesis.r' },
-		{ startIndex: 9, type: 'identifier.r' },
-		{ startIndex: 10, type: 'delimiter.parenthesis.r' },
-		{ startIndex: 11, type: 'white.r' },
-		{ startIndex: 12, type: 'delimiter.curly.r' },
-		{ startIndex: 13, type: 'white.r' },
-		{ startIndex: 14, type: 'identifier.r' },
-		{ startIndex: 15, type: 'white.r' },
-		{ startIndex: 16, type: 'delimiter.curly.r' }
-	]}],
-
-	[{
-	line: 'while(FALSE) { break }',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.r' },
-		{ startIndex: 5, type: 'delimiter.parenthesis.r' },
-		{ startIndex: 6, type: 'constant.r' },
-		{ startIndex: 11, type: 'delimiter.parenthesis.r' },
-		{ startIndex: 12, type: 'white.r' },
-		{ startIndex: 13, type: 'delimiter.curly.r' },
-		{ startIndex: 14, type: 'white.r' },
-		{ startIndex: 15, type: 'keyword.r' },
-		{ startIndex: 20, type: 'white.r' },
-		{ startIndex: 21, type: 'delimiter.curly.r' }
-	]}],
-
-	[{
-	line: 'if (a) { b } else { d }',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.r' },
-		{ startIndex: 2, type: 'white.r' },
-		{ startIndex: 3, type: 'delimiter.parenthesis.r' },
-		{ startIndex: 4, type: 'identifier.r' },
-		{ startIndex: 5, type: 'delimiter.parenthesis.r' },
-		{ startIndex: 6, type: 'white.r' },
-		{ startIndex: 7, type: 'delimiter.curly.r' },
-		{ startIndex: 8, type: 'white.r' },
-		{ startIndex: 9, type: 'identifier.r' },
-		{ startIndex: 10, type: 'white.r' },
-		{ startIndex: 11, type: 'delimiter.curly.r' },
-		{ startIndex: 12, type: 'white.r' },
-		{ startIndex: 13, type: 'keyword.r' },
-		{ startIndex: 17, type: 'white.r' },
-		{ startIndex: 18, type: 'delimiter.curly.r' },
-		{ startIndex: 19, type: 'white.r' },
-		{ startIndex: 20, type: 'identifier.r' },
-		{ startIndex: 21, type: 'white.r' },
-		{ startIndex: 22, type: 'delimiter.curly.r' }
-	]}],
+		line: 'function(a) { a }',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.r' },
+			{ startIndex: 8, type: 'delimiter.parenthesis.r' },
+			{ startIndex: 9, type: 'identifier.r' },
+			{ startIndex: 10, type: 'delimiter.parenthesis.r' },
+			{ startIndex: 11, type: 'white.r' },
+			{ startIndex: 12, type: 'delimiter.curly.r' },
+			{ startIndex: 13, type: 'white.r' },
+			{ startIndex: 14, type: 'identifier.r' },
+			{ startIndex: 15, type: 'white.r' },
+			{ startIndex: 16, type: 'delimiter.curly.r' }
+		]
+	}],
+
+	[{
+		line: 'while(FALSE) { break }',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.r' },
+			{ startIndex: 5, type: 'delimiter.parenthesis.r' },
+			{ startIndex: 6, type: 'constant.r' },
+			{ startIndex: 11, type: 'delimiter.parenthesis.r' },
+			{ startIndex: 12, type: 'white.r' },
+			{ startIndex: 13, type: 'delimiter.curly.r' },
+			{ startIndex: 14, type: 'white.r' },
+			{ startIndex: 15, type: 'keyword.r' },
+			{ startIndex: 20, type: 'white.r' },
+			{ startIndex: 21, type: 'delimiter.curly.r' }
+		]
+	}],
+
+	[{
+		line: 'if (a) { b } else { d }',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.r' },
+			{ startIndex: 2, type: 'white.r' },
+			{ startIndex: 3, type: 'delimiter.parenthesis.r' },
+			{ startIndex: 4, type: 'identifier.r' },
+			{ startIndex: 5, type: 'delimiter.parenthesis.r' },
+			{ startIndex: 6, type: 'white.r' },
+			{ startIndex: 7, type: 'delimiter.curly.r' },
+			{ startIndex: 8, type: 'white.r' },
+			{ startIndex: 9, type: 'identifier.r' },
+			{ startIndex: 10, type: 'white.r' },
+			{ startIndex: 11, type: 'delimiter.curly.r' },
+			{ startIndex: 12, type: 'white.r' },
+			{ startIndex: 13, type: 'keyword.r' },
+			{ startIndex: 17, type: 'white.r' },
+			{ startIndex: 18, type: 'delimiter.curly.r' },
+			{ startIndex: 19, type: 'white.r' },
+			{ startIndex: 20, type: 'identifier.r' },
+			{ startIndex: 21, type: 'white.r' },
+			{ startIndex: 22, type: 'delimiter.curly.r' }
+		]
+	}],
 
 	// Identifiers
 	[{
-	line: 'a',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' }
-	]}],
+		line: 'a',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' }
+		]
+	}],
 
 	// Comments
 	[{
-	line: ' # comment #',
-	tokens: [
-		{ startIndex: 0, type: 'white.r' },
-		{ startIndex: 1, type: 'comment.r' }
-	]}],
+		line: ' # comment #',
+		tokens: [
+			{ startIndex: 0, type: 'white.r' },
+			{ startIndex: 1, type: 'comment.r' }
+		]
+	}],
 
 	// Roxygen comments
 	[{
-	line: ' #\' @author: me ',
-	tokens: [
-		{ startIndex: 0, type: 'white.r' },
-		{ startIndex: 1, type: 'comment.doc.r' },
-		{ startIndex: 4, type: 'tag.r' },
-		{ startIndex: 11, type: 'comment.doc.r' }
-	]}],
+		line: ' #\' @author: me ',
+		tokens: [
+			{ startIndex: 0, type: 'white.r' },
+			{ startIndex: 1, type: 'comment.doc.r' },
+			{ startIndex: 4, type: 'tag.r' },
+			{ startIndex: 11, type: 'comment.doc.r' }
+		]
+	}],
 
 	// Strings
 	[{
-	line: '"a\\n"',
-	tokens: [
-		{ startIndex: 0, type: 'string.escape.r' },
-		{ startIndex: 1, type: 'string.r' },
-		{ startIndex: 4, type: 'string.escape.r' }
-	]}],
+		line: '"a\\n"',
+		tokens: [
+			{ startIndex: 0, type: 'string.escape.r' },
+			{ startIndex: 1, type: 'string.r' },
+			{ startIndex: 4, type: 'string.escape.r' }
+		]
+	}],
 
 	// '\\s' is not a special character
 	[{
-	line: '"a\\s"',
-	tokens: [
-		{ startIndex: 0, type: 'string.escape.r' },
-		{ startIndex: 1, type: 'string.r' },
-		{ startIndex: 2, type: 'error-token.r' },
-		{ startIndex: 4, type: 'string.escape.r' }
-	]}],
+		line: '"a\\s"',
+		tokens: [
+			{ startIndex: 0, type: 'string.escape.r' },
+			{ startIndex: 1, type: 'string.r' },
+			{ startIndex: 2, type: 'error-token.r' },
+			{ startIndex: 4, type: 'string.escape.r' }
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '0',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '0',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '1',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '1',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '-1',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '-1',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '1.1',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '1.1',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '-1.1',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '-1.1',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '.1',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '.1',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '-.1',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '-.1',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '1e10',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '1e10',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '1e-10',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '1e-10',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '-1e10',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '-1e10',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '-1e-10',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '-1e-10',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '1E10',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '1E10',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '1E-10',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '1E-10',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '-1E10',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '-1E10',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	[{
-	line: '-1E-10',
-	tokens: [
-		{ startIndex: 0, type: 'number.r' }
-	]}],
+		line: '-1E-10',
+		tokens: [
+			{ startIndex: 0, type: 'number.r' }
+		]
+	}],
 
 	// Operators
 	[{
-	line: 'a & b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a - b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a * b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a + b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a = b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a | b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a ! b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a < b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a > b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a ^ b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a ~ b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a / b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a : b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a %in% b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 6, type: 'white.r' },
-		{ startIndex: 7, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a %->% b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 6, type: 'white.r' },
-		{ startIndex: 7, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a == b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 4, type: 'white.r' },
-		{ startIndex: 5, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a != b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 4, type: 'white.r' },
-		{ startIndex: 5, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a %% b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 4, type: 'white.r' },
-		{ startIndex: 5, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a && b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 4, type: 'white.r' },
-		{ startIndex: 5, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a || b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 4, type: 'white.r' },
-		{ startIndex: 5, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a <- b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 4, type: 'white.r' },
-		{ startIndex: 5, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a <<- b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 5, type: 'white.r' },
-		{ startIndex: 6, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a -> b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 4, type: 'white.r' },
-		{ startIndex: 5, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a ->> b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 5, type: 'white.r' },
-		{ startIndex: 6, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a $ b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 3, type: 'white.r' },
-		{ startIndex: 4, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a << b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 4, type: 'white.r' },
-		{ startIndex: 5, type: 'identifier.r' }
-	]}],
-
-	[{
-	line: 'a >> b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.r' },
-		{ startIndex: 1, type: 'white.r' },
-		{ startIndex: 2, type: 'operator.r' },
-		{ startIndex: 4, type: 'white.r' },
-		{ startIndex: 5, type: 'identifier.r' }
-	]}]
+		line: 'a & b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a - b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a * b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a + b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a = b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a | b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a ! b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a < b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a > b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a ^ b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a ~ b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a / b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a : b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a %in% b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 6, type: 'white.r' },
+			{ startIndex: 7, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a %->% b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 6, type: 'white.r' },
+			{ startIndex: 7, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a == b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 4, type: 'white.r' },
+			{ startIndex: 5, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a != b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 4, type: 'white.r' },
+			{ startIndex: 5, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a %% b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 4, type: 'white.r' },
+			{ startIndex: 5, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a && b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 4, type: 'white.r' },
+			{ startIndex: 5, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a || b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 4, type: 'white.r' },
+			{ startIndex: 5, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a <- b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 4, type: 'white.r' },
+			{ startIndex: 5, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a <<- b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 5, type: 'white.r' },
+			{ startIndex: 6, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a -> b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 4, type: 'white.r' },
+			{ startIndex: 5, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a ->> b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 5, type: 'white.r' },
+			{ startIndex: 6, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a $ b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 3, type: 'white.r' },
+			{ startIndex: 4, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a << b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 4, type: 'white.r' },
+			{ startIndex: 5, type: 'identifier.r' }
+		]
+	}],
+
+	[{
+		line: 'a >> b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.r' },
+			{ startIndex: 1, type: 'white.r' },
+			{ startIndex: 2, type: 'operator.r' },
+			{ startIndex: 4, type: 'white.r' },
+			{ startIndex: 5, type: 'identifier.r' }
+		]
+	}]
 ]);

+ 108 - 99
test/razor.test.ts

@@ -5,8 +5,8 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
-import {htmlTokenTypes} from '../src/php';
+import { testTokenization } from './testRunner';
+import { htmlTokenTypes } from '../src/php';
 
 const EMBED_CS = 'metatag.cs';
 
@@ -14,65 +14,68 @@ testTokenization('razor', [
 
 	// Embedding - embedded html
 	[{
-	line: '@{ var x; <b>x</b> }',
-	tokens: [
-		{ startIndex: 0, type: EMBED_CS },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'keyword.cs' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.cs' },
-		{ startIndex: 8, type: 'delimiter.cs' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: htmlTokenTypes.DELIM_START },
-		{ startIndex: 11, type: htmlTokenTypes.getTag('b') },
-		{ startIndex: 12, type: htmlTokenTypes.DELIM_END },
-		{ startIndex: 13, type: 'identifier.cs' },
-		{ startIndex: 14, type: htmlTokenTypes.DELIM_START },
-		{ startIndex: 16, type: htmlTokenTypes.getTag('b') },
-		{ startIndex: 17, type: htmlTokenTypes.DELIM_END },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: EMBED_CS }
-	]}],
+		line: '@{ var x; <b>x</b> }',
+		tokens: [
+			{ startIndex: 0, type: EMBED_CS },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'keyword.cs' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.cs' },
+			{ startIndex: 8, type: 'delimiter.cs' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 11, type: htmlTokenTypes.getTag('b') },
+			{ startIndex: 12, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 13, type: 'identifier.cs' },
+			{ startIndex: 14, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 16, type: htmlTokenTypes.getTag('b') },
+			{ startIndex: 17, type: htmlTokenTypes.DELIM_END },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: EMBED_CS }
+		]
+	}],
 
 	// Comments - razor comment inside csharp
 	[{
-	line: '@{ var x; @* comment *@ x= 0; }',
-	tokens: [
-		{ startIndex: 0, type: EMBED_CS },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'keyword.cs' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.cs' },
-		{ startIndex: 8, type: 'delimiter.cs' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'comment.cs' },
-		{ startIndex: 23, type: '' },
-		{ startIndex: 24, type: 'identifier.cs' },
-		{ startIndex: 25, type: 'delimiter.cs' },
-		{ startIndex: 26, type: '' },
-		{ startIndex: 27, type: 'number.cs' },
-		{ startIndex: 28, type: 'delimiter.cs' },
-		{ startIndex: 29, type: '' },
-		{ startIndex: 30, type: EMBED_CS }
-	]}],
+		line: '@{ var x; @* comment *@ x= 0; }',
+		tokens: [
+			{ startIndex: 0, type: EMBED_CS },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'keyword.cs' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.cs' },
+			{ startIndex: 8, type: 'delimiter.cs' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'comment.cs' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'identifier.cs' },
+			{ startIndex: 25, type: 'delimiter.cs' },
+			{ startIndex: 26, type: '' },
+			{ startIndex: 27, type: 'number.cs' },
+			{ startIndex: 28, type: 'delimiter.cs' },
+			{ startIndex: 29, type: '' },
+			{ startIndex: 30, type: EMBED_CS }
+		]
+	}],
 
 	// Blocks - simple
 	[{
-	line: '@{ var total = 0; }',
-	tokens: [
-		{ startIndex: 0, type: EMBED_CS },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'keyword.cs' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.cs' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'delimiter.cs' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'number.cs' },
-		{ startIndex: 16, type: 'delimiter.cs' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: EMBED_CS }
-	]}],
+		line: '@{ var total = 0; }',
+		tokens: [
+			{ startIndex: 0, type: EMBED_CS },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'keyword.cs' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.cs' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'delimiter.cs' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'number.cs' },
+			{ startIndex: 16, type: 'delimiter.cs' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: EMBED_CS }
+		]
+	}],
 
 	// [{
 	// line: '@if(true){ var total = 0; }',
@@ -98,59 +101,65 @@ testTokenization('razor', [
 
 	// Expressions - csharp expressions in html
 	[{
-	line: 'test@xyz<br>',
-	tokens: [
-		{ startIndex:0, type: '' },
-		{ startIndex:4, type: EMBED_CS },
-		{ startIndex:5, type: 'identifier.cs' },
-		{ startIndex:8, type: htmlTokenTypes.DELIM_START },
-		{ startIndex:9, type: htmlTokenTypes.getTag('br') },
-		{ startIndex:11, type: htmlTokenTypes.DELIM_END }
-	]}],
+		line: 'test@xyz<br>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: EMBED_CS },
+			{ startIndex: 5, type: 'identifier.cs' },
+			{ startIndex: 8, type: htmlTokenTypes.DELIM_START },
+			{ startIndex: 9, type: htmlTokenTypes.getTag('br') },
+			{ startIndex: 11, type: htmlTokenTypes.DELIM_END }
+		]
+	}],
 
 	[{
-	line: 'test@xyz',
-	tokens: [
-		{ startIndex:0, type: '' },
-		{ startIndex:4, type: EMBED_CS },
-		{ startIndex:5, type: 'identifier.cs' }
-	]}],
+		line: 'test@xyz',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: EMBED_CS },
+			{ startIndex: 5, type: 'identifier.cs' }
+		]
+	}],
 
 	[{
-	line: 'test @ xyz',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 5, type: EMBED_CS },
-		{ startIndex: 6, type: 'identifier.cs' }
-	]}],
+		line: 'test @ xyz',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: EMBED_CS },
+			{ startIndex: 6, type: 'identifier.cs' }
+		]
+	}],
 
 	[{
-	line: 'test @(foo) xyz',
-	tokens: [
-		{ startIndex:0, type: '' },
-		{ startIndex:5, type: EMBED_CS },
-		{ startIndex:7, type: 'identifier.cs' },
-		{ startIndex:10, type: EMBED_CS },
-		{ startIndex:11, type: '' }
-	]}],
+		line: 'test @(foo) xyz',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: EMBED_CS },
+			{ startIndex: 7, type: 'identifier.cs' },
+			{ startIndex: 10, type: EMBED_CS },
+			{ startIndex: 11, type: '' }
+		]
+	}],
 
 	[{
-	line: 'test @(foo(\")\")) xyz',
-	tokens: [
-		{ startIndex:0, type: '' },
-		{ startIndex:5, type: EMBED_CS },
-		{ startIndex:7, type: 'identifier.cs' },
-		{ startIndex:10, type: 'delimiter.parenthesis.cs' },
-		{ startIndex:11, type: 'string.cs' },
-		{ startIndex:14, type: 'delimiter.parenthesis.cs' },
-		{ startIndex:15, type: EMBED_CS },
-		{ startIndex:16, type: '' }
-	]}],
+		line: 'test @(foo(\")\")) xyz',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 5, type: EMBED_CS },
+			{ startIndex: 7, type: 'identifier.cs' },
+			{ startIndex: 10, type: 'delimiter.parenthesis.cs' },
+			{ startIndex: 11, type: 'string.cs' },
+			{ startIndex: 14, type: 'delimiter.parenthesis.cs' },
+			{ startIndex: 15, type: EMBED_CS },
+			{ startIndex: 16, type: '' }
+		]
+	}],
 
 	// Escaping - escaped at character
 	[{
-	line: 'test@@xyz',
-	tokens: [
-		{ startIndex:0, type: '' }
-	]}]
+		line: 'test@@xyz',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}]
 ]);

+ 106 - 93
test/ruby.test.ts

@@ -5,121 +5,134 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('ruby', [
 	// Keywords
 	[{
-	line: 'class Klass def init() end',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.class.ruby' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'constructor.identifier.ruby' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'keyword.def.ruby' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'identifier.ruby' },
-		{ startIndex: 20, type: 'delimiter.parenthesis.ruby' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'keyword.def.ruby' }
-	]}],
+		line: 'class Klass def init() end',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.class.ruby' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'constructor.identifier.ruby' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'keyword.def.ruby' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'identifier.ruby' },
+			{ startIndex: 20, type: 'delimiter.parenthesis.ruby' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'keyword.def.ruby' }
+		]
+	}],
 
 	// Single digit
 	[{
-	line: 'x == 1 ',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.ruby' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'operator.ruby' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'number.ruby' },
-		{ startIndex: 6, type: '' }
-	]}],
+		line: 'x == 1 ',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.ruby' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'operator.ruby' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'number.ruby' },
+			{ startIndex: 6, type: '' }
+		]
+	}],
 
 	// Regex
 	[{
-	line: 'text =~ /Ruby/',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.ruby' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'operator.ruby' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'regexp.delim.ruby' },
-		{ startIndex: 9, type: 'regexp.ruby' },
-		{ startIndex: 13, type: 'regexp.delim.ruby' }
-	]}],
+		line: 'text =~ /Ruby/',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.ruby' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'operator.ruby' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'regexp.delim.ruby' },
+			{ startIndex: 9, type: 'regexp.ruby' },
+			{ startIndex: 13, type: 'regexp.delim.ruby' }
+		]
+	}],
 
 	[{
-	line: 'text.sub!(/Rbuy/, "Ruby")',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.ruby' },
-		{ startIndex: 4, type: '' },
-		{ startIndex: 5, type: 'identifier.ruby' },
-		{ startIndex: 9, type: 'delimiter.parenthesis.ruby' },
-		{ startIndex: 10, type: 'regexp.delim.ruby' },
-		{ startIndex: 11, type: 'regexp.ruby' },
-		{ startIndex: 15, type: 'regexp.delim.ruby' },
-		{ startIndex: 16, type: 'delimiter.ruby' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: 'string.d.delim.ruby' },
-		{ startIndex: 19, type: 'string.$S2.ruby' },
-		{ startIndex: 23, type: 'string.d.delim.ruby' },
-		{ startIndex: 24, type: 'delimiter.parenthesis.ruby' }
-	]}],
+		line: 'text.sub!(/Rbuy/, "Ruby")',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.ruby' },
+			{ startIndex: 4, type: '' },
+			{ startIndex: 5, type: 'identifier.ruby' },
+			{ startIndex: 9, type: 'delimiter.parenthesis.ruby' },
+			{ startIndex: 10, type: 'regexp.delim.ruby' },
+			{ startIndex: 11, type: 'regexp.ruby' },
+			{ startIndex: 15, type: 'regexp.delim.ruby' },
+			{ startIndex: 16, type: 'delimiter.ruby' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'string.d.delim.ruby' },
+			{ startIndex: 19, type: 'string.$S2.ruby' },
+			{ startIndex: 23, type: 'string.d.delim.ruby' },
+			{ startIndex: 24, type: 'delimiter.parenthesis.ruby' }
+		]
+	}],
 
 	// make sure that division does not match regex
 	[{
-	line: 'a / b',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.ruby' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'operator.ruby' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.ruby' }
-	]}],
+		line: 'a / b',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.ruby' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'operator.ruby' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.ruby' }
+		]
+	}],
 
 	// Heredoc
 	[{
-	line: '<<HERE',
-	tokens: [
-		{ startIndex: 0, type: 'string.heredoc.delimiter.ruby' }
-	]}, {
-	line: 'do some string',
-	tokens: [
-		{ startIndex: 0, type: 'string.heredoc.ruby' }
-	]}, {
-	line: 'HERE',
-	tokens: [
-		{ startIndex: 0, type: 'string.heredoc.delimiter.ruby' }
-	]}],
+		line: '<<HERE',
+		tokens: [
+			{ startIndex: 0, type: 'string.heredoc.delimiter.ruby' }
+		]
+	}, {
+		line: 'do some string',
+		tokens: [
+			{ startIndex: 0, type: 'string.heredoc.ruby' }
+		]
+	}, {
+		line: 'HERE',
+		tokens: [
+			{ startIndex: 0, type: 'string.heredoc.delimiter.ruby' }
+		]
+	}],
 
 	[{
-	line: 'x <<HERE',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.ruby' },
-		{ startIndex: 1, type: 'string.heredoc.delimiter.ruby' }
-	]}, {
-	line: 'do some string',
-	tokens: [
-		{ startIndex: 0, type: 'string.heredoc.ruby' }
-	]}, {
-	line: 'HERE',
-	tokens: [
-		{ startIndex: 0, type: 'string.heredoc.delimiter.ruby' }
-	]}],
+		line: 'x <<HERE',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.ruby' },
+			{ startIndex: 1, type: 'string.heredoc.delimiter.ruby' }
+		]
+	}, {
+		line: 'do some string',
+		tokens: [
+			{ startIndex: 0, type: 'string.heredoc.ruby' }
+		]
+	}, {
+		line: 'HERE',
+		tokens: [
+			{ startIndex: 0, type: 'string.heredoc.delimiter.ruby' }
+		]
+	}],
 
 	[{
-	line: 'x<<HERE',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.ruby' },
-		{ startIndex: 1, type: 'operator.ruby' },
-		{ startIndex: 3, type: 'constructor.identifier.ruby' }
-	]}],
+		line: 'x<<HERE',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.ruby' },
+			{ startIndex: 1, type: 'operator.ruby' },
+			{ startIndex: 3, type: 'constructor.identifier.ruby' }
+		]
+	}],
 
 	[{
-	line: 'x<<-HERE',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.ruby' },
-		{ startIndex: 1, type: 'string.heredoc.delimiter.ruby' }
-	]}]
+		line: 'x<<-HERE',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.ruby' },
+			{ startIndex: 1, type: 'string.heredoc.delimiter.ruby' }
+		]
+	}]
 ]);

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 640 - 627
test/scss.test.ts


+ 224 - 204
test/solidity.test.ts

@@ -1,218 +1,238 @@
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('sol', [
 	// Keywords
 	[{
-	line: 'pragma solidity ^0.4.0;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.pragma.sol' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'keyword.solidity.sol' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'delimiter.sol' },
-		{ startIndex: 17, type: 'number.float.sol' },
-		{ startIndex: 22, type: 'delimiter.sol' },
-	]}],
-
-	[{
-	line: 'contract Ballot {',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.contract.sol' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'identifier.sol' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'delimiter.curly.sol' }
-	]}],
-
-	[{
-	line: 'struct Voter {',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.struct.sol' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.sol' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'delimiter.curly.sol' }
-	]}],
-
-	[{
-	line: 'address chairperson;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.address.sol' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.sol' },
-		{ startIndex: 19, type: 'delimiter.sol' }
-	]}],
-
-	[{
-	line: 'int weight;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.int.sol' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.sol' },
-		{ startIndex: 10, type: 'delimiter.sol' },
-	]}],
-
-	[{
-	line: 'mapping(address => Voter) voters;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.mapping.sol' },
-		{ startIndex: 7, type: 'delimiter.parenthesis.sol' },
-		{ startIndex: 8, type: 'keyword.address.sol' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 19, type: 'identifier.sol' },
-		{ startIndex: 24, type: 'delimiter.parenthesis.sol' },
-		{ startIndex: 25, type: '' },
-		{ startIndex: 26, type: 'identifier.sol' },
-		{ startIndex: 32, type: 'delimiter.sol' },
-	]}],
-
-	[{
-	line: 'function Ballot(uint8 _numProposals) {',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.function.sol' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'identifier.sol' },
-		{ startIndex: 15, type: 'delimiter.parenthesis.sol' },
-		{ startIndex: 16, type: 'keyword.uint8.sol' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'identifier.sol' },
-		{ startIndex: 35, type: 'delimiter.parenthesis.sol' },
-		{ startIndex: 36, type: '' },
-		{ startIndex: 37, type: 'delimiter.curly.sol' },
-	]}],
+		line: 'pragma solidity ^0.4.0;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.pragma.sol' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'keyword.solidity.sol' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'delimiter.sol' },
+			{ startIndex: 17, type: 'number.float.sol' },
+			{ startIndex: 22, type: 'delimiter.sol' },
+		]
+	}],
+
+	[{
+		line: 'contract Ballot {',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.contract.sol' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'identifier.sol' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'delimiter.curly.sol' }
+		]
+	}],
+
+	[{
+		line: 'struct Voter {',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.struct.sol' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.sol' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'delimiter.curly.sol' }
+		]
+	}],
+
+	[{
+		line: 'address chairperson;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.address.sol' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.sol' },
+			{ startIndex: 19, type: 'delimiter.sol' }
+		]
+	}],
+
+	[{
+		line: 'int weight;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.int.sol' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.sol' },
+			{ startIndex: 10, type: 'delimiter.sol' },
+		]
+	}],
+
+	[{
+		line: 'mapping(address => Voter) voters;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.mapping.sol' },
+			{ startIndex: 7, type: 'delimiter.parenthesis.sol' },
+			{ startIndex: 8, type: 'keyword.address.sol' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 19, type: 'identifier.sol' },
+			{ startIndex: 24, type: 'delimiter.parenthesis.sol' },
+			{ startIndex: 25, type: '' },
+			{ startIndex: 26, type: 'identifier.sol' },
+			{ startIndex: 32, type: 'delimiter.sol' },
+		]
+	}],
+
+	[{
+		line: 'function Ballot(uint8 _numProposals) {',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.function.sol' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'identifier.sol' },
+			{ startIndex: 15, type: 'delimiter.parenthesis.sol' },
+			{ startIndex: 16, type: 'keyword.uint8.sol' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'identifier.sol' },
+			{ startIndex: 35, type: 'delimiter.parenthesis.sol' },
+			{ startIndex: 36, type: '' },
+			{ startIndex: 37, type: 'delimiter.curly.sol' },
+		]
+	}],
 
 	// Comments - single line
 	[{
-	line: '//',
-	tokens: [
-		{ startIndex: 0, type: 'comment.sol' }
-	]}],
-
-	[{
-	line: '    // a comment',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'comment.sol' }
-	]}],
-
-	[{
-	line: '// a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.sol' }
-	]}],
-
-	[{
-	line: '//sticky comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.sol' }
-	]}],
-
-	[{
-	line: '/almost a comment',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.sol' },
-		{ startIndex: 1, type: 'identifier.sol' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.sol' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'identifier.sol' }
-	]}],
-
-	[{
-	line: '/* //*/ a',
-	tokens: [
-		{ startIndex: 0, type: 'comment.sol' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.sol' }
-	]}],
-
-	[{
-	line: '1 / 2; /* comment',
-	tokens: [
-		{ startIndex: 0, type: 'number.sol' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.sol' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.sol' },
-		{ startIndex: 5, type: 'delimiter.sol' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'comment.sol' }
-	]}],
-
-	[{
-	line: 'int x = 1; // my comment // is a nice one',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.int.sol' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.sol' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.sol' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.sol' },
-		{ startIndex: 9, type: 'delimiter.sol' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'comment.sol' }
-	]}],
+		line: '//',
+		tokens: [
+			{ startIndex: 0, type: 'comment.sol' }
+		]
+	}],
+
+	[{
+		line: '    // a comment',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'comment.sol' }
+		]
+	}],
+
+	[{
+		line: '// a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.sol' }
+		]
+	}],
+
+	[{
+		line: '//sticky comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.sol' }
+		]
+	}],
+
+	[{
+		line: '/almost a comment',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.sol' },
+			{ startIndex: 1, type: 'identifier.sol' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.sol' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.sol' }
+		]
+	}],
+
+	[{
+		line: '/* //*/ a',
+		tokens: [
+			{ startIndex: 0, type: 'comment.sol' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.sol' }
+		]
+	}],
+
+	[{
+		line: '1 / 2; /* comment',
+		tokens: [
+			{ startIndex: 0, type: 'number.sol' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.sol' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.sol' },
+			{ startIndex: 5, type: 'delimiter.sol' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'comment.sol' }
+		]
+	}],
+
+	[{
+		line: 'int x = 1; // my comment // is a nice one',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.int.sol' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.sol' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.sol' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.sol' },
+			{ startIndex: 9, type: 'delimiter.sol' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'comment.sol' }
+		]
+	}],
 
 	// Comments - range comment, single line
 	[{
-	line: '/* a simple comment */',
-	tokens: [
-		{ startIndex: 0, type: 'comment.sol' }
-	]}],
-
-	[{
-	line: 'int x = /* a simple comment */ 1;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.int.sol' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.sol' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.sol' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.sol' },
-		{ startIndex: 30, type: '' },
-		{ startIndex: 31, type: 'number.sol' },
-		{ startIndex: 32, type: 'delimiter.sol' }
-	]}],
-
-	[{
-	line: 'int x = /* comment */ 1; */',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.int.sol' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.sol' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.sol' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'comment.sol' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'number.sol' },
-		{ startIndex: 23, type: 'delimiter.sol' },
-		{ startIndex: 24, type: '' }
-	]}],
-
-	[{
-	line: 'x = /**/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sol' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.sol' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.sol' },
-		{ startIndex: 8, type: 'delimiter.sol' }
-	]}],
-
-	[{
-	line: 'x = /*/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sol' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.sol' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'comment.sol' }
-	]}],
+		line: '/* a simple comment */',
+		tokens: [
+			{ startIndex: 0, type: 'comment.sol' }
+		]
+	}],
+
+	[{
+		line: 'int x = /* a simple comment */ 1;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.int.sol' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.sol' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.sol' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.sol' },
+			{ startIndex: 30, type: '' },
+			{ startIndex: 31, type: 'number.sol' },
+			{ startIndex: 32, type: 'delimiter.sol' }
+		]
+	}],
+
+	[{
+		line: 'int x = /* comment */ 1; */',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.int.sol' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.sol' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.sol' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'comment.sol' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'number.sol' },
+			{ startIndex: 23, type: 'delimiter.sol' },
+			{ startIndex: 24, type: '' }
+		]
+	}],
+
+	[{
+		line: 'x = /**/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sol' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.sol' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.sol' },
+			{ startIndex: 8, type: 'delimiter.sol' }
+		]
+	}],
+
+	[{
+		line: 'x = /*/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sol' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.sol' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'comment.sol' }
+		]
+	}],
 
 ]);

+ 515 - 445
test/sql.test.ts

@@ -5,572 +5,642 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('sql', [
 	// Comments
 	[{
-	line: '-- a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.sql' }
-	]}],
-
-	[{
-	line: '---sticky -- comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.sql' }
-	]}],
-
-	[{
-	line: '-almost a comment',
-	tokens: [
-		{ startIndex: 0, type: 'operator.sql' },
-		{ startIndex: 1, type: 'identifier.sql' },
-		{ startIndex: 7, type: 'white.sql' },
-		{ startIndex: 8, type: 'identifier.sql' },
-		{ startIndex: 9, type: 'white.sql' },
-		{ startIndex: 10, type: 'identifier.sql' }
-	]}],
-
-	[{
-	line: '/* a full line comment */',
-	tokens: [
-		{ startIndex: 0, type: 'comment.quote.sql' },
-		{ startIndex: 2, type: 'comment.sql' },
-		{ startIndex: 23, type: 'comment.quote.sql' }
-	]}],
-
-	[{
-	line: '/* /// *** /// */',
-	tokens: [
-		{ startIndex: 0, type: 'comment.quote.sql' },
-		{ startIndex: 2, type: 'comment.sql' },
-		{ startIndex: 15, type: 'comment.quote.sql' }
-	]}],
-
-	[{
-	line: 'declare @x int = /* a simple comment */ 1;',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.sql' },
-		{ startIndex: 7, type: 'white.sql' },
-		{ startIndex: 8, type: 'identifier.sql' },
-		{ startIndex: 10, type: 'white.sql' },
-		{ startIndex: 11, type: 'keyword.sql' },
-		{ startIndex: 14, type: 'white.sql' },
-		{ startIndex: 15, type: 'operator.sql' },
-		{ startIndex: 16, type: 'white.sql' },
-		{ startIndex: 17, type: 'comment.quote.sql' },
-		{ startIndex: 19, type: 'comment.sql' },
-		{ startIndex: 37, type: 'comment.quote.sql' },
-		{ startIndex: 39, type: 'white.sql' },
-		{ startIndex: 40, type: 'number.sql' },
-		{ startIndex: 41, type: 'delimiter.sql' }
-	]}],
+		line: '-- a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.sql' }
+		]
+	}],
+
+	[{
+		line: '---sticky -- comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.sql' }
+		]
+	}],
+
+	[{
+		line: '-almost a comment',
+		tokens: [
+			{ startIndex: 0, type: 'operator.sql' },
+			{ startIndex: 1, type: 'identifier.sql' },
+			{ startIndex: 7, type: 'white.sql' },
+			{ startIndex: 8, type: 'identifier.sql' },
+			{ startIndex: 9, type: 'white.sql' },
+			{ startIndex: 10, type: 'identifier.sql' }
+		]
+	}],
+
+	[{
+		line: '/* a full line comment */',
+		tokens: [
+			{ startIndex: 0, type: 'comment.quote.sql' },
+			{ startIndex: 2, type: 'comment.sql' },
+			{ startIndex: 23, type: 'comment.quote.sql' }
+		]
+	}],
+
+	[{
+		line: '/* /// *** /// */',
+		tokens: [
+			{ startIndex: 0, type: 'comment.quote.sql' },
+			{ startIndex: 2, type: 'comment.sql' },
+			{ startIndex: 15, type: 'comment.quote.sql' }
+		]
+	}],
+
+	[{
+		line: 'declare @x int = /* a simple comment */ 1;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.sql' },
+			{ startIndex: 7, type: 'white.sql' },
+			{ startIndex: 8, type: 'identifier.sql' },
+			{ startIndex: 10, type: 'white.sql' },
+			{ startIndex: 11, type: 'keyword.sql' },
+			{ startIndex: 14, type: 'white.sql' },
+			{ startIndex: 15, type: 'operator.sql' },
+			{ startIndex: 16, type: 'white.sql' },
+			{ startIndex: 17, type: 'comment.quote.sql' },
+			{ startIndex: 19, type: 'comment.sql' },
+			{ startIndex: 37, type: 'comment.quote.sql' },
+			{ startIndex: 39, type: 'white.sql' },
+			{ startIndex: 40, type: 'number.sql' },
+			{ startIndex: 41, type: 'delimiter.sql' }
+		]
+	}],
 
 	// Not supporting nested comments, as nested comments seem to not be standard?
 	// i.e. http://stackoverflow.com/questions/728172/are-there-multiline-comment-delimiters-in-sql-that-are-vendor-agnostic
 	[{
-	line: '@x=/* a /* nested comment  1*/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sql' },
-		{ startIndex: 2, type: 'operator.sql' },
-		{ startIndex: 3, type: 'comment.quote.sql' },
-		{ startIndex: 5, type: 'comment.sql' },
-		{ startIndex: 28, type: 'comment.quote.sql' },
-		{ startIndex: 30, type: 'delimiter.sql' }
-	]}],
-
-	[{
-	line: '@x=/* another comment */ 1*/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sql' },
-		{ startIndex: 2, type: 'operator.sql' },
-		{ startIndex: 3, type: 'comment.quote.sql' },
-		{ startIndex: 5, type: 'comment.sql' },
-		{ startIndex: 22, type: 'comment.quote.sql' },
-		{ startIndex: 24, type: 'white.sql' },
-		{ startIndex: 25, type: 'number.sql' },
-		{ startIndex: 26, type: 'operator.sql' },
-		{ startIndex: 28, type: 'delimiter.sql' }
-	]}],
-
-	[{
-	line: '@x=/*/;',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sql' },
-		{ startIndex: 2, type: 'operator.sql' },
-		{ startIndex: 3, type: 'comment.quote.sql' },
-		{ startIndex: 5, type: 'comment.sql' }
-	]}],
+		line: '@x=/* a /* nested comment  1*/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sql' },
+			{ startIndex: 2, type: 'operator.sql' },
+			{ startIndex: 3, type: 'comment.quote.sql' },
+			{ startIndex: 5, type: 'comment.sql' },
+			{ startIndex: 28, type: 'comment.quote.sql' },
+			{ startIndex: 30, type: 'delimiter.sql' }
+		]
+	}],
+
+	[{
+		line: '@x=/* another comment */ 1*/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sql' },
+			{ startIndex: 2, type: 'operator.sql' },
+			{ startIndex: 3, type: 'comment.quote.sql' },
+			{ startIndex: 5, type: 'comment.sql' },
+			{ startIndex: 22, type: 'comment.quote.sql' },
+			{ startIndex: 24, type: 'white.sql' },
+			{ startIndex: 25, type: 'number.sql' },
+			{ startIndex: 26, type: 'operator.sql' },
+			{ startIndex: 28, type: 'delimiter.sql' }
+		]
+	}],
+
+	[{
+		line: '@x=/*/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sql' },
+			{ startIndex: 2, type: 'operator.sql' },
+			{ startIndex: 3, type: 'comment.quote.sql' },
+			{ startIndex: 5, type: 'comment.sql' }
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '123',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '123',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '-123',
-	tokens: [
-		{ startIndex: 0, type: 'operator.sql' },
-		{ startIndex: 1, type: 'number.sql' }
-	]}],
+		line: '-123',
+		tokens: [
+			{ startIndex: 0, type: 'operator.sql' },
+			{ startIndex: 1, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '0xaBc123',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '0xaBc123',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '0XaBc123',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '0XaBc123',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '0x',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '0x',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '0x0',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '0x0',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '0xAB_CD',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' },
-		{ startIndex: 4, type: 'identifier.sql' }
-	]}],
+		line: '0xAB_CD',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' },
+			{ startIndex: 4, type: 'identifier.sql' }
+		]
+	}],
 
 	[{
-	line: '$',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '$',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '$-123',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '$-123',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '$-+-123',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '$-+-123',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '$123.5678',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '$123.5678',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '$0.99',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '$0.99',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '$.99',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '$.99',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '$99.',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '$99.',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '$0.',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '$0.',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '$.0',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '$.0',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '.',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.sql' }
-	]}],
+		line: '.',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.sql' }
+		]
+	}],
 
 	[{
-	line: '123',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '123',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '123.5678',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '123.5678',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '0.99',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '0.99',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '.99',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '.99',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '99.',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '99.',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '0.',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '0.',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '.0',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '.0',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '1E-2',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '1E-2',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '1E+2',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '1E+2',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '1E2',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '1E2',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '0.1E2',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '0.1E2',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '1.E2',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '1.E2',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	[{
-	line: '.1E2',
-	tokens: [
-		{ startIndex: 0, type: 'number.sql' }
-	]}],
+		line: '.1E2',
+		tokens: [
+			{ startIndex: 0, type: 'number.sql' }
+		]
+	}],
 
 	// Identifiers
 	[{
-	line: '_abc$01',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sql' }
-	]}],
+		line: '_abc$01',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sql' }
+		]
+	}],
 
 	[{
-	line: '#abc$01',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sql' }
-	]}],
+		line: '#abc$01',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sql' }
+		]
+	}],
 
 	[{
-	line: '##abc$01',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sql' }
-	]}],
+		line: '##abc$01',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sql' }
+		]
+	}],
 
 	[{
-	line: '@abc$01',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sql' }
-	]}],
+		line: '@abc$01',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sql' }
+		]
+	}],
 
 	[{
-	line: '@@abc$01',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sql' }
-	]}],
+		line: '@@abc$01',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sql' }
+		]
+	}],
 
 	[{
-	line: '$abc',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sql' }
-	]}],
+		line: '$abc',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sql' }
+		]
+	}],
 
 	[{
-	line: '$action',
-	tokens: [
-		{ startIndex: 0, type: 'predefined.sql' }
-	]}],
+		line: '$action',
+		tokens: [
+			{ startIndex: 0, type: 'predefined.sql' }
+		]
+	}],
 
 	[{
-	line: '$nonexistent',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sql' }
-	]}],
+		line: '$nonexistent',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sql' }
+		]
+	}],
 
 	[{
-	line: '@@DBTS',
-	tokens: [
-		{ startIndex: 0, type: 'predefined.sql' }
-	]}],
+		line: '@@DBTS',
+		tokens: [
+			{ startIndex: 0, type: 'predefined.sql' }
+		]
+	}],
 
 	[{
-	line: '@@nonexistent',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sql' }
-	]}],
+		line: '@@nonexistent',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sql' }
+		]
+	}],
 
 	[{
-	line: 'declare [abc 321];',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.sql' },
-		{ startIndex: 7, type: 'white.sql' },
-		{ startIndex: 8, type: 'identifier.quote.sql' },
-		{ startIndex: 9, type: 'identifier.sql' },
-		{ startIndex: 16, type: 'identifier.quote.sql' },
-		{ startIndex: 17, type: 'delimiter.sql' }
-	]}],
+		line: 'declare [abc 321];',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.sql' },
+			{ startIndex: 7, type: 'white.sql' },
+			{ startIndex: 8, type: 'identifier.quote.sql' },
+			{ startIndex: 9, type: 'identifier.sql' },
+			{ startIndex: 16, type: 'identifier.quote.sql' },
+			{ startIndex: 17, type: 'delimiter.sql' }
+		]
+	}],
 
 	[{
-	line: '[abc[[ 321 ]] xyz]',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.quote.sql' },
-		{ startIndex: 1, type: 'identifier.sql' },
-		{ startIndex: 17, type: 'identifier.quote.sql' }
-	]}],
+		line: '[abc[[ 321 ]] xyz]',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.quote.sql' },
+			{ startIndex: 1, type: 'identifier.sql' },
+			{ startIndex: 17, type: 'identifier.quote.sql' }
+		]
+	}],
 
 	[{
-	line: '[abc',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.quote.sql' },
-		{ startIndex: 1, type: 'identifier.sql' }
-	]}],
+		line: '[abc',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.quote.sql' },
+			{ startIndex: 1, type: 'identifier.sql' }
+		]
+	}],
 
 	[{
-	line: 'declare "abc 321";',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.sql' },
-		{ startIndex: 7, type: 'white.sql' },
-		{ startIndex: 8, type: 'identifier.quote.sql' },
-		{ startIndex: 9, type: 'identifier.sql' },
-		{ startIndex: 16, type: 'identifier.quote.sql' },
-		{ startIndex: 17, type: 'delimiter.sql' }
-	]}],
+		line: 'declare "abc 321";',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.sql' },
+			{ startIndex: 7, type: 'white.sql' },
+			{ startIndex: 8, type: 'identifier.quote.sql' },
+			{ startIndex: 9, type: 'identifier.sql' },
+			{ startIndex: 16, type: 'identifier.quote.sql' },
+			{ startIndex: 17, type: 'delimiter.sql' }
+		]
+	}],
 
 	[{
-	line: '"abc"" 321 "" xyz"',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.quote.sql' },
-		{ startIndex: 1, type: 'identifier.sql' },
-		{ startIndex: 17, type: 'identifier.quote.sql' }
-	]}],
+		line: '"abc"" 321 "" xyz"',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.quote.sql' },
+			{ startIndex: 1, type: 'identifier.sql' },
+			{ startIndex: 17, type: 'identifier.quote.sql' }
+		]
+	}],
 
 	[{
-	line: '"abc',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.quote.sql' },
-		{ startIndex: 1, type: 'identifier.sql' }
-	]}],
+		line: '"abc',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.quote.sql' },
+			{ startIndex: 1, type: 'identifier.sql' }
+		]
+	}],
 
-	[{
-	line: 'int',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.sql' }
-	]}],
+	[{
+		line: 'int',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.sql' }
+		]
+	}],
 
-	[{
-	line: '[int]',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.quote.sql' },
-		{ startIndex: 1, type: 'identifier.sql' },
-		{ startIndex: 4, type: 'identifier.quote.sql' }
-	]}],
+	[{
+		line: '[int]',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.quote.sql' },
+			{ startIndex: 1, type: 'identifier.sql' },
+			{ startIndex: 4, type: 'identifier.quote.sql' }
+		]
+	}],
 
 	// Strings
 	[{
-	line: 'declare @x=\'a string\';',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.sql' },
-		{ startIndex: 7, type: 'white.sql' },
-		{ startIndex: 8, type: 'identifier.sql' },
-		{ startIndex: 10, type: 'operator.sql' },
-		{ startIndex: 11, type: 'string.sql' },
-		{ startIndex: 21, type: 'delimiter.sql' }
-	]}],
+		line: 'declare @x=\'a string\';',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.sql' },
+			{ startIndex: 7, type: 'white.sql' },
+			{ startIndex: 8, type: 'identifier.sql' },
+			{ startIndex: 10, type: 'operator.sql' },
+			{ startIndex: 11, type: 'string.sql' },
+			{ startIndex: 21, type: 'delimiter.sql' }
+		]
+	}],
 
 	[{
-	line: '\'a \'\' string with quotes\'',
-	tokens: [
-		{ startIndex: 0, type: 'string.sql' },
-	]}],
+		line: '\'a \'\' string with quotes\'',
+		tokens: [
+			{ startIndex: 0, type: 'string.sql' },
+		]
+	}],
 
 	[{
-	line: '\'a " string with quotes\'',
-	tokens: [
-		{ startIndex: 0, type: 'string.sql' },
-	]}],
+		line: '\'a " string with quotes\'',
+		tokens: [
+			{ startIndex: 0, type: 'string.sql' },
+		]
+	}],
 
 	[{
-	line: '\'a -- string with comment\'',
-	tokens: [
-		{ startIndex: 0, type: 'string.sql' },
-	]}],
+		line: '\'a -- string with comment\'',
+		tokens: [
+			{ startIndex: 0, type: 'string.sql' },
+		]
+	}],
 
 	[{
-	line: 'N\'a unicode string\'',
-	tokens: [
-		{ startIndex: 0, type: 'string.sql' },
-	]}],
+		line: 'N\'a unicode string\'',
+		tokens: [
+			{ startIndex: 0, type: 'string.sql' },
+		]
+	}],
 
 	[{
-	line: '\'a endless string',
-	tokens: [
-		{ startIndex: 0, type: 'string.sql' },
-	]}],
+		line: '\'a endless string',
+		tokens: [
+			{ startIndex: 0, type: 'string.sql' },
+		]
+	}],
 
 	// Operators
 	[{
-	line: 'SET @x=@x+1',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.sql' },
-		{ startIndex: 3, type: 'white.sql' },
-		{ startIndex: 4, type: 'identifier.sql' },
-		{ startIndex: 6, type: 'operator.sql' },
-		{ startIndex: 7, type: 'identifier.sql' },
-		{ startIndex: 9, type: 'operator.sql' },
-		{ startIndex: 10, type: 'number.sql' }
-	]}],
-
-	[{
-	line: '@x^=@x',
-	tokens: [
-		{ startIndex: 0, type: 'identifier.sql' },
-		{ startIndex: 2, type: 'operator.sql' },
-		{ startIndex: 4, type: 'identifier.sql' }
-	]}],
-
-	[{
-	line: 'WHERE x IS NOT NULL',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.sql' },
-		{ startIndex: 5, type: 'white.sql' },
-		{ startIndex: 6, type: 'identifier.sql' },
-		{ startIndex: 7, type: 'white.sql' },
-		{ startIndex: 8, type: 'operator.sql' },
-		{ startIndex: 10, type: 'white.sql' },
-		{ startIndex: 11, type: 'operator.sql' },
-		{ startIndex: 14, type: 'white.sql' },
-		{ startIndex: 15, type: 'operator.sql' }
-	]}],
-
-	[{
-	line: 'SELECT * FROM dbo.MyTable WHERE MyColumn IN (1,2)',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.sql' },
-		{ startIndex: 6, type: 'white.sql' },
-		{ startIndex: 7, type: 'operator.sql' },
-		{ startIndex: 8, type: 'white.sql' },
-		{ startIndex: 9, type: 'keyword.sql' },
-		{ startIndex: 13, type: 'white.sql' },
-		{ startIndex: 14, type: 'identifier.sql' },
-		{ startIndex: 17, type: 'delimiter.sql' },
-		{ startIndex: 18, type: 'identifier.sql' },
-		{ startIndex: 25, type: 'white.sql' },
-		{ startIndex: 26, type: 'keyword.sql' },
-		{ startIndex: 31, type: 'white.sql' },
-		{ startIndex: 32, type: 'identifier.sql' },
-		{ startIndex: 40, type: 'white.sql' },
-		{ startIndex: 41, type: 'operator.sql' },
-		{ startIndex: 43, type: 'white.sql' },
-		{ startIndex: 44, type: 'delimiter.parenthesis.sql' },
-		{ startIndex: 45, type: 'number.sql' },
-		{ startIndex: 46, type: 'delimiter.sql' },
-		{ startIndex: 47, type: 'number.sql' },
-		{ startIndex: 48, type: 'delimiter.parenthesis.sql' }
-	]}],
+		line: 'SET @x=@x+1',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.sql' },
+			{ startIndex: 3, type: 'white.sql' },
+			{ startIndex: 4, type: 'identifier.sql' },
+			{ startIndex: 6, type: 'operator.sql' },
+			{ startIndex: 7, type: 'identifier.sql' },
+			{ startIndex: 9, type: 'operator.sql' },
+			{ startIndex: 10, type: 'number.sql' }
+		]
+	}],
+
+	[{
+		line: '@x^=@x',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.sql' },
+			{ startIndex: 2, type: 'operator.sql' },
+			{ startIndex: 4, type: 'identifier.sql' }
+		]
+	}],
+
+	[{
+		line: 'WHERE x IS NOT NULL',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.sql' },
+			{ startIndex: 5, type: 'white.sql' },
+			{ startIndex: 6, type: 'identifier.sql' },
+			{ startIndex: 7, type: 'white.sql' },
+			{ startIndex: 8, type: 'operator.sql' },
+			{ startIndex: 10, type: 'white.sql' },
+			{ startIndex: 11, type: 'operator.sql' },
+			{ startIndex: 14, type: 'white.sql' },
+			{ startIndex: 15, type: 'operator.sql' }
+		]
+	}],
+
+	[{
+		line: 'SELECT * FROM dbo.MyTable WHERE MyColumn IN (1,2)',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.sql' },
+			{ startIndex: 6, type: 'white.sql' },
+			{ startIndex: 7, type: 'operator.sql' },
+			{ startIndex: 8, type: 'white.sql' },
+			{ startIndex: 9, type: 'keyword.sql' },
+			{ startIndex: 13, type: 'white.sql' },
+			{ startIndex: 14, type: 'identifier.sql' },
+			{ startIndex: 17, type: 'delimiter.sql' },
+			{ startIndex: 18, type: 'identifier.sql' },
+			{ startIndex: 25, type: 'white.sql' },
+			{ startIndex: 26, type: 'keyword.sql' },
+			{ startIndex: 31, type: 'white.sql' },
+			{ startIndex: 32, type: 'identifier.sql' },
+			{ startIndex: 40, type: 'white.sql' },
+			{ startIndex: 41, type: 'operator.sql' },
+			{ startIndex: 43, type: 'white.sql' },
+			{ startIndex: 44, type: 'delimiter.parenthesis.sql' },
+			{ startIndex: 45, type: 'number.sql' },
+			{ startIndex: 46, type: 'delimiter.sql' },
+			{ startIndex: 47, type: 'number.sql' },
+			{ startIndex: 48, type: 'delimiter.parenthesis.sql' }
+		]
+	}],
 
 	// Scopes
 	[{
-	line: 'WHILE() BEGIN END',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.sql' },
-		{ startIndex: 5, type: 'delimiter.parenthesis.sql' },
-		{ startIndex: 7, type: 'white.sql' },
-		{ startIndex: 8, type: 'keyword.block.sql' },
-		{ startIndex: 13, type: 'white.sql' },
-		{ startIndex: 14, type: 'keyword.block.sql' }
-	]}],
-
-	[{
-	line: 'BEGIN TRAN BEGIN TRY SELECT $ COMMIT END TRY BEGIN CATCH ROLLBACK END CATCH',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.sql' },
-		{ startIndex: 10, type: 'white.sql' },
-		{ startIndex: 11, type: 'keyword.try.sql' },
-		{ startIndex: 20, type: 'white.sql' },
-		{ startIndex: 21, type: 'keyword.sql' },
-		{ startIndex: 27, type: 'white.sql' },
-		{ startIndex: 28, type: 'number.sql' },
-		{ startIndex: 29, type: 'white.sql' },
-		{ startIndex: 30, type: 'keyword.sql' },
-		{ startIndex: 36, type: 'white.sql' },
-		{ startIndex: 37, type: 'keyword.try.sql' },
-		{ startIndex: 44, type: 'white.sql' },
-		{ startIndex: 45, type: 'keyword.catch.sql' },
-		{ startIndex: 56, type: 'white.sql' },
-		{ startIndex: 57, type: 'keyword.sql' },
-		{ startIndex: 65, type: 'white.sql' },
-		{ startIndex: 66, type: 'keyword.catch.sql' }
-	]}],
-
-	[{
-	line: 'SELECT CASE $ WHEN 3 THEN 4 ELSE 5 END',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.sql' },
-		{ startIndex: 6, type: 'white.sql' },
-		{ startIndex: 7, type: 'keyword.block.sql' },
-		{ startIndex: 11, type: 'white.sql' },
-		{ startIndex: 12, type: 'number.sql' },
-		{ startIndex: 13, type: 'white.sql' },
-		{ startIndex: 14, type: 'keyword.choice.sql' },
-		{ startIndex: 18, type: 'white.sql' },
-		{ startIndex: 19, type: 'number.sql' },
-		{ startIndex: 20, type: 'white.sql' },
-		{ startIndex: 21, type: 'keyword.choice.sql' },
-		{ startIndex: 25, type: 'white.sql' },
-		{ startIndex: 26, type: 'number.sql' },
-		{ startIndex: 27, type: 'white.sql' },
-		{ startIndex: 28, type: 'keyword.sql' },
-		{ startIndex: 32, type: 'white.sql' },
-		{ startIndex: 33, type: 'number.sql' },
-		{ startIndex: 34, type: 'white.sql' },
-		{ startIndex: 35, type: 'keyword.block.sql' }
-	]}]
+		line: 'WHILE() BEGIN END',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.sql' },
+			{ startIndex: 5, type: 'delimiter.parenthesis.sql' },
+			{ startIndex: 7, type: 'white.sql' },
+			{ startIndex: 8, type: 'keyword.block.sql' },
+			{ startIndex: 13, type: 'white.sql' },
+			{ startIndex: 14, type: 'keyword.block.sql' }
+		]
+	}],
+
+	[{
+		line: 'BEGIN TRAN BEGIN TRY SELECT $ COMMIT END TRY BEGIN CATCH ROLLBACK END CATCH',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.sql' },
+			{ startIndex: 10, type: 'white.sql' },
+			{ startIndex: 11, type: 'keyword.try.sql' },
+			{ startIndex: 20, type: 'white.sql' },
+			{ startIndex: 21, type: 'keyword.sql' },
+			{ startIndex: 27, type: 'white.sql' },
+			{ startIndex: 28, type: 'number.sql' },
+			{ startIndex: 29, type: 'white.sql' },
+			{ startIndex: 30, type: 'keyword.sql' },
+			{ startIndex: 36, type: 'white.sql' },
+			{ startIndex: 37, type: 'keyword.try.sql' },
+			{ startIndex: 44, type: 'white.sql' },
+			{ startIndex: 45, type: 'keyword.catch.sql' },
+			{ startIndex: 56, type: 'white.sql' },
+			{ startIndex: 57, type: 'keyword.sql' },
+			{ startIndex: 65, type: 'white.sql' },
+			{ startIndex: 66, type: 'keyword.catch.sql' }
+		]
+	}],
+
+	[{
+		line: 'SELECT CASE $ WHEN 3 THEN 4 ELSE 5 END',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.sql' },
+			{ startIndex: 6, type: 'white.sql' },
+			{ startIndex: 7, type: 'keyword.block.sql' },
+			{ startIndex: 11, type: 'white.sql' },
+			{ startIndex: 12, type: 'number.sql' },
+			{ startIndex: 13, type: 'white.sql' },
+			{ startIndex: 14, type: 'keyword.choice.sql' },
+			{ startIndex: 18, type: 'white.sql' },
+			{ startIndex: 19, type: 'number.sql' },
+			{ startIndex: 20, type: 'white.sql' },
+			{ startIndex: 21, type: 'keyword.choice.sql' },
+			{ startIndex: 25, type: 'white.sql' },
+			{ startIndex: 26, type: 'number.sql' },
+			{ startIndex: 27, type: 'white.sql' },
+			{ startIndex: 28, type: 'keyword.sql' },
+			{ startIndex: 32, type: 'white.sql' },
+			{ startIndex: 33, type: 'number.sql' },
+			{ startIndex: 34, type: 'white.sql' },
+			{ startIndex: 35, type: 'keyword.block.sql' }
+		]
+	}]
 ]);

+ 142 - 132
test/swift.test.ts

@@ -5,177 +5,187 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('swift', [
 
 	// Attributes
 	[{
-	line: '@noescape',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.control.swift' } /* '@noescape' */
-	]}],
+		line: '@noescape',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.control.swift' } /* '@noescape' */
+		]
+	}],
 	//Keyword and Type Identifier
 	[{
 		line: 'class App: UI, UIApp, UIView {',
 		tokens: [
-		{ startIndex: 0, type: 'keyword.swift' } /* 'class' */,
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'type.identifier.swift' } /* 'App' */,
-		{ startIndex: 9, type: 'operator.swift' } /* ':' */,
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'type.identifier.swift' } /* 'UI' */,
-		{ startIndex: 13, type: 'operator.swift' } /* ',' */,
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'type.identifier.swift' } /* 'UIApp' */,
-		{ startIndex: 20, type: 'operator.swift' } /* ',' */,
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'type.identifier.swift' } /* 'UIView' */,
-		{ startIndex: 28, type: '' },
-		{ startIndex: 29, type: 'delimiter.curly.swift' } /* '{' */
-	]}],
+			{ startIndex: 0, type: 'keyword.swift' } /* 'class' */,
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'type.identifier.swift' } /* 'App' */,
+			{ startIndex: 9, type: 'operator.swift' } /* ':' */,
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'type.identifier.swift' } /* 'UI' */,
+			{ startIndex: 13, type: 'operator.swift' } /* ',' */,
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'type.identifier.swift' } /* 'UIApp' */,
+			{ startIndex: 20, type: 'operator.swift' } /* ',' */,
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'type.identifier.swift' } /* 'UIView' */,
+			{ startIndex: 28, type: '' },
+			{ startIndex: 29, type: 'delimiter.curly.swift' } /* '{' */
+		]
+	}],
 	// Keyword, Identifier, and Type Identifier
 	[{
 		line: '    var window: UIWindow?',
 		tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.swift' } /* 'var' */,
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.swift' } /* 'window' */,
-		{ startIndex: 14, type: 'operator.swift' } /* ':' */,
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'type.identifier.swift' } /* 'UIWindow' */,
-		{ startIndex: 24, type: 'operator.swift' } /* '?' */
-	]}],
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.swift' } /* 'var' */,
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.swift' } /* 'window' */,
+			{ startIndex: 14, type: 'operator.swift' } /* ':' */,
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'type.identifier.swift' } /* 'UIWindow' */,
+			{ startIndex: 24, type: 'operator.swift' } /* '?' */
+		]
+	}],
 	//Comment
 	[{
 		line: '    // Comment',
 		tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'comment.swift' } /* '// Comment' */
-	]}],
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'comment.swift' } /* '// Comment' */
+		]
+	}],
 	//Block Comment with Embedded Comment followed by code
 	[{
 		line: '    /* Comment //Embedded */ var y = 0b10',
 		tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'comment.swift' }, // /* '/* Comment //Embedded */' */,
-		{ startIndex: 28, type: '' },
-		{ startIndex: 29, type: 'keyword.swift' } /* 'var' */,
-		{ startIndex: 32, type: '' },
-		{ startIndex: 33, type: 'identifier.swift' }	/* 'y' */,
-		{ startIndex: 34, type: '' },
-		{ startIndex: 35, type: 'operator.swift' } /* '=' */,
-		{ startIndex: 36, type: '' },
-		{ startIndex: 37, type: 'number.binary.swift' } /* '0b10' */
-	]}],
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'comment.swift' }, // /* '/* Comment //Embedded */' */,
+			{ startIndex: 28, type: '' },
+			{ startIndex: 29, type: 'keyword.swift' } /* 'var' */,
+			{ startIndex: 32, type: '' },
+			{ startIndex: 33, type: 'identifier.swift' }	/* 'y' */,
+			{ startIndex: 34, type: '' },
+			{ startIndex: 35, type: 'operator.swift' } /* '=' */,
+			{ startIndex: 36, type: '' },
+			{ startIndex: 37, type: 'number.binary.swift' } /* '0b10' */
+		]
+	}],
 	// Method signature (broken on two lines)
 	[{
 		line: '    public func app(app: App, opts:',
-		tokens:[
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'keyword.swift' } /* 'public' */,
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'keyword.swift' } /* 'func' */,
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'identifier.swift' } /* 'app' */,
-		{ startIndex: 19, type: 'delimiter.parenthesis.swift' } /* '(' */,
-		{ startIndex: 20, type: 'identifier.swift' }/* 'app' */,
-		{ startIndex: 23, type: 'operator.swift' } /* ':' */,
-		{ startIndex: 24, type: '' },
-		{ startIndex: 25, type: 'type.identifier.swift' } /* 'App' */,
-		{ startIndex: 28, type: 'operator.swift' } /* ',' */,
-		{ startIndex: 29, type: '' },
-		{ startIndex: 30, type: 'identifier.swift' } /* 'opts' */,
-		{ startIndex: 34, type: 'operator.swift' } /* ':' */,
-	]}],
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'keyword.swift' } /* 'public' */,
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'keyword.swift' } /* 'func' */,
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'identifier.swift' } /* 'app' */,
+			{ startIndex: 19, type: 'delimiter.parenthesis.swift' } /* '(' */,
+			{ startIndex: 20, type: 'identifier.swift' }/* 'app' */,
+			{ startIndex: 23, type: 'operator.swift' } /* ':' */,
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'type.identifier.swift' } /* 'App' */,
+			{ startIndex: 28, type: 'operator.swift' } /* ',' */,
+			{ startIndex: 29, type: '' },
+			{ startIndex: 30, type: 'identifier.swift' } /* 'opts' */,
+			{ startIndex: 34, type: 'operator.swift' } /* ':' */,
+		]
+	}],
 	// Method signature Continued
 	[{
 		line: '        [NSObject: AnyObject]?) -> Bool {',
 		tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'delimiter.square.swift' } /* '[' */,
-		{ startIndex: 9, type: 'type.identifier.swift' } /* 'NSObject' */,
-		{ startIndex: 17, type: 'operator.swift' } /* ':' */,
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'type.identifier.swift' } /* 'AnyObject' */,
-		{ startIndex: 28, type: 'delimiter.square.swift' } /* ']' */,
-		{ startIndex: 29, type: 'operator.swift' } /* '?' */,
-		{ startIndex: 30, type: 'delimiter.parenthesis.swift' } /* ')' */,
-		{ startIndex: 31, type: '' },
-		{ startIndex: 32, type: 'operator.swift' } /* '->' */,
-		{ startIndex: 34, type: '' },
-		{ startIndex: 35, type: 'type.identifier.swift' } /* 'Bool' */,
-		{ startIndex: 39, type: '' },
-		{ startIndex: 40, type: 'delimiter.curly.swift' } /* '{' */
-	]}],
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'delimiter.square.swift' } /* '[' */,
+			{ startIndex: 9, type: 'type.identifier.swift' } /* 'NSObject' */,
+			{ startIndex: 17, type: 'operator.swift' } /* ':' */,
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'type.identifier.swift' } /* 'AnyObject' */,
+			{ startIndex: 28, type: 'delimiter.square.swift' } /* ']' */,
+			{ startIndex: 29, type: 'operator.swift' } /* '?' */,
+			{ startIndex: 30, type: 'delimiter.parenthesis.swift' } /* ')' */,
+			{ startIndex: 31, type: '' },
+			{ startIndex: 32, type: 'operator.swift' } /* '->' */,
+			{ startIndex: 34, type: '' },
+			{ startIndex: 35, type: 'type.identifier.swift' } /* 'Bool' */,
+			{ startIndex: 39, type: '' },
+			{ startIndex: 40, type: 'delimiter.curly.swift' } /* '{' */
+		]
+	}],
 	// String with escapes
 	[{
 		line: '        var `String` = "String w/ \\"escape\\""',
 		tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'keyword.swift' } /* 'var' */,
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'operator.swift' } /* '`' */,
-		{ startIndex: 13, type: 'identifier.swift' } /* 'String' */,
-		{ startIndex: 19, type: 'operator.swift' } /* '`' */,
-		{ startIndex: 20, type: '' },
-		{ startIndex: 21, type: 'operator.swift' } /* '=' */,
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'string.quote.swift' } /* '"' */,
-		{ startIndex: 24, type: 'string.swift' } /* 'String w/ \\"escape\\""' */,
-		{ startIndex: 44, type: 'string.quote.swift' } /* '"' */,
-	]}],
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'keyword.swift' } /* 'var' */,
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'operator.swift' } /* '`' */,
+			{ startIndex: 13, type: 'identifier.swift' } /* 'String' */,
+			{ startIndex: 19, type: 'operator.swift' } /* '`' */,
+			{ startIndex: 20, type: '' },
+			{ startIndex: 21, type: 'operator.swift' } /* '=' */,
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'string.quote.swift' } /* '"' */,
+			{ startIndex: 24, type: 'string.swift' } /* 'String w/ \\"escape\\""' */,
+			{ startIndex: 44, type: 'string.quote.swift' } /* '"' */,
+		]
+	}],
 	// String with interpolated expression
 	[{
 		line: '        let message = "\\(y) times 2.5 is \\(Double(25) * 2.5)"',
 		tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'keyword.swift' } /* 'let' */,
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'identifier.swift' } /* 'message' */,
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'operator.swift' } /* '=' */,
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'string.quote.swift' } /* '"' */,
-		{ startIndex: 23, type: 'operator.swift' } /* '\(' */,
-		{ startIndex: 25, type: 'identifier.swift' },
-		{ startIndex: 26, type: 'operator.swift' } /* ')' */,
-		{ startIndex: 27, type: 'string.swift' } /* ' times 2.5 is ' */,
-		{ startIndex: 41, type: 'operator.swift' } /* '\(' */,
-		{ startIndex: 43, type: 'type.identifier.swift' } /* 'Double' */,
-		{ startIndex: 49, type: 'operator.swift' } /* '(' */,
-		{ startIndex: 50, type: 'number.swift' } /* '25' */,
-		{ startIndex: 52, type: 'operator.swift' } /* ')' */,
-		{ startIndex: 53, type: '' },
-		{ startIndex: 54, type: 'operator.swift' } /* '*' */,
-		{ startIndex: 55, type: '' },
-		{ startIndex: 56, type: 'number.float.swift' } /* '2.5' */,
-		{ startIndex: 59, type: 'operator.swift' } /* ')' */,
-		{ startIndex: 60, type: 'string.quote.swift' } /* '"' */
-	]}],
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'keyword.swift' } /* 'let' */,
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'identifier.swift' } /* 'message' */,
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'operator.swift' } /* '=' */,
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'string.quote.swift' } /* '"' */,
+			{ startIndex: 23, type: 'operator.swift' } /* '\(' */,
+			{ startIndex: 25, type: 'identifier.swift' },
+			{ startIndex: 26, type: 'operator.swift' } /* ')' */,
+			{ startIndex: 27, type: 'string.swift' } /* ' times 2.5 is ' */,
+			{ startIndex: 41, type: 'operator.swift' } /* '\(' */,
+			{ startIndex: 43, type: 'type.identifier.swift' } /* 'Double' */,
+			{ startIndex: 49, type: 'operator.swift' } /* '(' */,
+			{ startIndex: 50, type: 'number.swift' } /* '25' */,
+			{ startIndex: 52, type: 'operator.swift' } /* ')' */,
+			{ startIndex: 53, type: '' },
+			{ startIndex: 54, type: 'operator.swift' } /* '*' */,
+			{ startIndex: 55, type: '' },
+			{ startIndex: 56, type: 'number.float.swift' } /* '2.5' */,
+			{ startIndex: 59, type: 'operator.swift' } /* ')' */,
+			{ startIndex: 60, type: 'string.quote.swift' } /* '"' */
+		]
+	}],
 	// Method invocation/property accessor.
 	[{
 		line: '        let view = self.window!.contr as! UIView',
 		tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 8, type: 'keyword.swift' } /* 'let' */,
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'identifier.swift' } /* 'view' */,
-		{ startIndex: 16, type: '' },
-		{ startIndex: 17, type: 'operator.swift' } /* '=' */,
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'keyword.swift' } /* 'self' */,
-		{ startIndex: 23, type: 'delimeter.swift' } /* '.' */,
-		{ startIndex: 24, type: 'type.identifier.swift' } /* 'window' */,
-		{ startIndex: 30, type: 'operator.swift' } /* '!' */,
-		{ startIndex: 31, type: 'delimeter.swift' } /* '.' */,
-		{ startIndex: 32, type: 'type.identifier.swift' } /* 'contr' */,
-		{ startIndex: 37, type: '' },
-		{ startIndex: 38, type: 'keyword.swift' } /* 'as' */,
-		{ startIndex: 40, type: 'operator.swift' } /* '!' */,
-		{ startIndex: 41, type: '' },
-		{ startIndex: 42, type: 'type.identifier.swift' } /* 'UIView' */
-	]}]
+			{ startIndex: 0, type: '' },
+			{ startIndex: 8, type: 'keyword.swift' } /* 'let' */,
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'identifier.swift' } /* 'view' */,
+			{ startIndex: 16, type: '' },
+			{ startIndex: 17, type: 'operator.swift' } /* '=' */,
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'keyword.swift' } /* 'self' */,
+			{ startIndex: 23, type: 'delimeter.swift' } /* '.' */,
+			{ startIndex: 24, type: 'type.identifier.swift' } /* 'window' */,
+			{ startIndex: 30, type: 'operator.swift' } /* '!' */,
+			{ startIndex: 31, type: 'delimeter.swift' } /* '.' */,
+			{ startIndex: 32, type: 'type.identifier.swift' } /* 'contr' */,
+			{ startIndex: 37, type: '' },
+			{ startIndex: 38, type: 'keyword.swift' } /* 'as' */,
+			{ startIndex: 40, type: 'operator.swift' } /* '!' */,
+			{ startIndex: 41, type: '' },
+			{ startIndex: 42, type: 'type.identifier.swift' } /* 'UIView' */
+		]
+	}]
 ]);
 

+ 371 - 328
test/vb.test.ts

@@ -5,391 +5,434 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('vb', [
 
 	// Comments - single line
 	[{
-	line: '\'',
-	tokens: [
-		{ startIndex: 0, type: 'comment.vb' }
-	]}],
-
-	[{
-	line: '    \' a comment',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'comment.vb' }
-	]}],
-
-	[{
-	line: '\' a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.vb' }
-	]}],
-
-	[{
-	line: '\'sticky comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.vb' }
-	]}],
-
-	[{
-	line: '1 \' 2; \' comment',
-	tokens: [
-		{ startIndex: 0, type: 'number.vb' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'comment.vb' }
-	]}],
-
-	[{
-	line: 'Dim x = 1; \' my comment \'\' is a nice one',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.dim.vb' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.vb' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.vb' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.vb' },
-		{ startIndex: 9, type: 'delimiter.vb' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'comment.vb' }
-	]}],
-
-	[{
-	line: 'REM this is a comment',
-	tokens: [
-		{ startIndex: 0, type: 'comment.vb' }
-	]}],
-
-	[{
-	line: '2 + 5 REM comment starts',
-	tokens: [
-		{ startIndex: 0, type: 'number.vb' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.vb' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.vb' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'comment.vb' }
-	]}],
+		line: '\'',
+		tokens: [
+			{ startIndex: 0, type: 'comment.vb' }
+		]
+	}],
+
+	[{
+		line: '    \' a comment',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'comment.vb' }
+		]
+	}],
+
+	[{
+		line: '\' a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.vb' }
+		]
+	}],
+
+	[{
+		line: '\'sticky comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.vb' }
+		]
+	}],
+
+	[{
+		line: '1 \' 2; \' comment',
+		tokens: [
+			{ startIndex: 0, type: 'number.vb' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'comment.vb' }
+		]
+	}],
+
+	[{
+		line: 'Dim x = 1; \' my comment \'\' is a nice one',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.dim.vb' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.vb' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.vb' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.vb' },
+			{ startIndex: 9, type: 'delimiter.vb' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'comment.vb' }
+		]
+	}],
+
+	[{
+		line: 'REM this is a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.vb' }
+		]
+	}],
+
+	[{
+		line: '2 + 5 REM comment starts',
+		tokens: [
+			{ startIndex: 0, type: 'number.vb' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.vb' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.vb' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'comment.vb' }
+		]
+	}],
 
 	// Numbers
 	[{
-	line: '0',
-	tokens: [
-		{ startIndex: 0, type: 'number.vb' }
-	]}],
+		line: '0',
+		tokens: [
+			{ startIndex: 0, type: 'number.vb' }
+		]
+	}],
 
 	[{
-	line: '0.0',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '0.0',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '&h123',
-	tokens: [
-		{ startIndex: 0, type: 'number.hex.vb' }
-	]}],
+		line: '&h123',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.vb' }
+		]
+	}],
 
 	[{
-	line: '23.5',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '23.5',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '23.5e3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '23.5e3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '23.5E3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '23.5E3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '23.5r',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '23.5r',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '23.5f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '23.5f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '1.72E3r',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '1.72E3r',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '1.72E3r',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '1.72E3r',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '1.72e3f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '1.72e3f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '1.72e3r',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '1.72e3r',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '23.5R',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '23.5R',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '23.5r',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '23.5r',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '1.72E3#',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '1.72E3#',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '1.72E3F',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '1.72E3F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '1.72e3!',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '1.72e3!',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '1.72e3f',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '1.72e3f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '1.72e-3',
-	tokens: [
-		{ startIndex: 0, type: 'number.float.vb' }
-	]}],
+		line: '1.72e-3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.vb' }
+		]
+	}],
 
 	[{
-	line: '0+0',
-	tokens: [
-		{ startIndex: 0, type: 'number.vb' },
-		{ startIndex: 1, type: 'delimiter.vb' },
-		{ startIndex: 2, type: 'number.vb' }
-	]}],
+		line: '0+0',
+		tokens: [
+			{ startIndex: 0, type: 'number.vb' },
+			{ startIndex: 1, type: 'delimiter.vb' },
+			{ startIndex: 2, type: 'number.vb' }
+		]
+	}],
 
 	[{
-	line: '100+10',
-	tokens: [
-		{ startIndex: 0, type: 'number.vb' },
-		{ startIndex: 3, type: 'delimiter.vb' },
-		{ startIndex: 4, type: 'number.vb' }
-	]}],
+		line: '100+10',
+		tokens: [
+			{ startIndex: 0, type: 'number.vb' },
+			{ startIndex: 3, type: 'delimiter.vb' },
+			{ startIndex: 4, type: 'number.vb' }
+		]
+	}],
 
 	[{
-	line: '0 + 0',
-	tokens: [
-		{ startIndex: 0, type: 'number.vb' },
-		{ startIndex: 1, type: '' },
-		{ startIndex: 2, type: 'delimiter.vb' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'number.vb' }
-	]}],
+		line: '0 + 0',
+		tokens: [
+			{ startIndex: 0, type: 'number.vb' },
+			{ startIndex: 1, type: '' },
+			{ startIndex: 2, type: 'delimiter.vb' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'number.vb' }
+		]
+	}],
 
 	// Keywords
 	[{
-	line: 'Imports Microsoft.VisualBasic',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.imports.vb' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'identifier.vb' },
-		{ startIndex: 17, type: 'delimiter.vb' },
-		{ startIndex: 18, type: 'identifier.vb' }
-	]}],
-
-	[{
-	line: 'Private Sub Foo(ByVal sender As String)',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.private.vb' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'keyword.tag-sub.vb' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'identifier.vb' },
-		{ startIndex: 15, type: 'delimiter.parenthesis.vb' },
-		{ startIndex: 16, type: 'keyword.byval.vb' },
-		{ startIndex: 21, type: '' },
-		{ startIndex: 22, type: 'identifier.vb' },
-		{ startIndex: 28, type: '' },
-		{ startIndex: 29, type: 'keyword.as.vb' },
-		{ startIndex: 31, type: '' },
-		{ startIndex: 32, type: 'keyword.string.vb' },
-		{ startIndex: 38, type: 'delimiter.parenthesis.vb' }
-	]}],
+		line: 'Imports Microsoft.VisualBasic',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.imports.vb' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'identifier.vb' },
+			{ startIndex: 17, type: 'delimiter.vb' },
+			{ startIndex: 18, type: 'identifier.vb' }
+		]
+	}],
+
+	[{
+		line: 'Private Sub Foo(ByVal sender As String)',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.private.vb' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'keyword.tag-sub.vb' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'identifier.vb' },
+			{ startIndex: 15, type: 'delimiter.parenthesis.vb' },
+			{ startIndex: 16, type: 'keyword.byval.vb' },
+			{ startIndex: 21, type: '' },
+			{ startIndex: 22, type: 'identifier.vb' },
+			{ startIndex: 28, type: '' },
+			{ startIndex: 29, type: 'keyword.as.vb' },
+			{ startIndex: 31, type: '' },
+			{ startIndex: 32, type: 'keyword.string.vb' },
+			{ startIndex: 38, type: 'delimiter.parenthesis.vb' }
+		]
+	}],
 
 	// Strings
 	[{
-	line: 'String s = "string"',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.string.vb' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'identifier.vb' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'delimiter.vb' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'string.vb' }
-	]}],
-
-	[{
-	line: '"use strict";',
-	tokens: [
-		{ startIndex: 0, type: 'string.vb' },
-		{ startIndex: 12, type: 'delimiter.vb' }
-	]}],
+		line: 'String s = "string"',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.string.vb' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'identifier.vb' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'delimiter.vb' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'string.vb' }
+		]
+	}],
+
+	[{
+		line: '"use strict";',
+		tokens: [
+			{ startIndex: 0, type: 'string.vb' },
+			{ startIndex: 12, type: 'delimiter.vb' }
+		]
+	}],
 
 	// Tags
 	[{
-	line: 'Public Sub ToString()',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.public.vb' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'keyword.tag-sub.vb' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'identifier.vb' },
-		{ startIndex: 19, type: 'delimiter.parenthesis.vb' }
-	]}],
-
-	[{
-	line: 'public sub ToString()',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.public.vb' },
-		{ startIndex: 6, type: '' },
-		{ startIndex: 7, type: 'keyword.tag-sub.vb' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'identifier.vb' },
-		{ startIndex: 19, type: 'delimiter.parenthesis.vb' }
-	]}],
-
-	[{
-	line: 'While Do Continue While End While',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.tag-while.vb' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'keyword.tag-do.vb' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'keyword.tag-continue.vb' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: 'keyword.tag-while.vb' },
-		{ startIndex: 23, type: '' },
-		{ startIndex: 24, type: 'keyword.tag-while.vb' }
-	]}],
-
-	[{
-	line: 'While while WHILE WHile whiLe',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.tag-while.vb' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'keyword.tag-while.vb' },
-		{ startIndex: 11, type: '' },
-		{ startIndex: 12, type: 'keyword.tag-while.vb' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: 'keyword.tag-while.vb' },
-		{ startIndex: 23, type: '' },
-		{ startIndex: 24, type: 'keyword.tag-while.vb' }
-	]}],
-
-	[{
-	line: 'If b(i) = col Then',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.tag-if.vb' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'identifier.vb' },
-		{ startIndex: 4, type: 'delimiter.parenthesis.vb' },
-		{ startIndex: 5, type: 'identifier.vb' },
-		{ startIndex: 6, type: 'delimiter.parenthesis.vb' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'delimiter.vb' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'identifier.vb' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'keyword.then.vb' }
-	]}],
-
-	[{
-	line: 'Do stuff While True Loop',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.tag-do.vb' },
-		{ startIndex: 2, type: '' },
-		{ startIndex: 3, type: 'identifier.vb' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'keyword.tag-while.vb' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'keyword.true.vb' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'keyword.tag-do.vb' }
-	]}],
-
-	[{
-	line: 'For i = 0 To 10 DoStuff Next',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.tag-for.vb' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.vb' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'delimiter.vb' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'number.vb' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'keyword.to.vb' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'number.vb' },
-		{ startIndex: 15, type: '' },
-		{ startIndex: 16, type: 'identifier.vb' },
-		{ startIndex: 23, type: '' },
-		{ startIndex: 24, type: 'keyword.tag-for.vb' }
-	]}],
-
-	[{
-	line: 'For stuff End For',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.tag-for.vb' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.vb' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'keyword.end.vb' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'keyword.tag-for.vb' }
-	]}],
-
-	[{
-	line: 'For stuff end for',
-	tokens: [
-		{ startIndex: 0, type: 'keyword.tag-for.vb' },
-		{ startIndex: 3, type: '' },
-		{ startIndex: 4, type: 'identifier.vb' },
-		{ startIndex: 9, type: '' },
-		{ startIndex: 10, type: 'keyword.end.vb' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'keyword.tag-for.vb' }
-	]}]
+		line: 'Public Sub ToString()',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.public.vb' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'keyword.tag-sub.vb' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'identifier.vb' },
+			{ startIndex: 19, type: 'delimiter.parenthesis.vb' }
+		]
+	}],
+
+	[{
+		line: 'public sub ToString()',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.public.vb' },
+			{ startIndex: 6, type: '' },
+			{ startIndex: 7, type: 'keyword.tag-sub.vb' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'identifier.vb' },
+			{ startIndex: 19, type: 'delimiter.parenthesis.vb' }
+		]
+	}],
+
+	[{
+		line: 'While Do Continue While End While',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.tag-while.vb' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.tag-do.vb' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'keyword.tag-continue.vb' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'keyword.tag-while.vb' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'keyword.tag-while.vb' }
+		]
+	}],
+
+	[{
+		line: 'While while WHILE WHile whiLe',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.tag-while.vb' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'keyword.tag-while.vb' },
+			{ startIndex: 11, type: '' },
+			{ startIndex: 12, type: 'keyword.tag-while.vb' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'keyword.tag-while.vb' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'keyword.tag-while.vb' }
+		]
+	}],
+
+	[{
+		line: 'If b(i) = col Then',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.tag-if.vb' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'identifier.vb' },
+			{ startIndex: 4, type: 'delimiter.parenthesis.vb' },
+			{ startIndex: 5, type: 'identifier.vb' },
+			{ startIndex: 6, type: 'delimiter.parenthesis.vb' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.vb' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'identifier.vb' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'keyword.then.vb' }
+		]
+	}],
+
+	[{
+		line: 'Do stuff While True Loop',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.tag-do.vb' },
+			{ startIndex: 2, type: '' },
+			{ startIndex: 3, type: 'identifier.vb' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'keyword.tag-while.vb' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'keyword.true.vb' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'keyword.tag-do.vb' }
+		]
+	}],
+
+	[{
+		line: 'For i = 0 To 10 DoStuff Next',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.tag-for.vb' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.vb' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'delimiter.vb' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'number.vb' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'keyword.to.vb' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'number.vb' },
+			{ startIndex: 15, type: '' },
+			{ startIndex: 16, type: 'identifier.vb' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'keyword.tag-for.vb' }
+		]
+	}],
+
+	[{
+		line: 'For stuff End For',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.tag-for.vb' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.vb' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'keyword.end.vb' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'keyword.tag-for.vb' }
+		]
+	}],
+
+	[{
+		line: 'For stuff end for',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.tag-for.vb' },
+			{ startIndex: 3, type: '' },
+			{ startIndex: 4, type: 'identifier.vb' },
+			{ startIndex: 9, type: '' },
+			{ startIndex: 10, type: 'keyword.end.vb' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'keyword.tag-for.vb' }
+		]
+	}]
 ]);

+ 552 - 491
test/xml.test.ts

@@ -5,569 +5,630 @@
 
 'use strict';
 
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('xml', [
 	// Complete Start Tag with Whitespace
 	[{
-	line: '<person>',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 7, type: 'delimiter.xml' }
-	]}],
+		line: '<person>',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 7, type: 'delimiter.xml' }
+		]
+	}],
 
 	[{
-	line: '<person/>',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 8, type: 'delimiter.xml' }
-	]}],
+		line: '<person/>',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 8, type: 'delimiter.xml' }
+		]
+	}],
 
 	[{
-	line: '<person >',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'delimiter.xml' }
-	]}],
+		line: '<person >',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'delimiter.xml' }
+		]
+	}],
 
 	[{
-	line: '<person />',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 7, type: '' },
-		{ startIndex: 8, type: 'tag.xml' },
-		{ startIndex: 9, type: 'delimiter.xml' }
-	]}],
+		line: '<person />',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 7, type: '' },
+			{ startIndex: 8, type: 'tag.xml' },
+			{ startIndex: 9, type: 'delimiter.xml' }
+		]
+	}],
 
 	// Incomplete Start Tag
 	[{
-	line: '<',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}],
+		line: '<',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}],
 
 	[{
-	line: '<person',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' }
-	]}],
+		line: '<person',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' }
+		]
+	}],
 
 	[{
-	line: '<input',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' }
-	]}],
+		line: '<input',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' }
+		]
+	}],
 
 	// Invalid Open Start Tag
 	[{
-	line: '< person',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}],
+		line: '< person',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}],
 
 	[{
-	line: '< person>',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}],
+		line: '< person>',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}],
 
 	[{
-	line: 'i <person;',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.xml' },
-		{ startIndex: 3, type: 'tag.xml' },
-		{ startIndex: 9, type: '' }
-	]}],
+		line: 'i <person;',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.xml' },
+			{ startIndex: 3, type: 'tag.xml' },
+			{ startIndex: 9, type: '' }
+		]
+	}],
 
 	// Tag with Attribute
 	[{
-	line: '<tool name="">',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'attribute.value.xml' },
-		{ startIndex: 13, type: 'delimiter.xml' }
-	]}],
+		line: '<tool name="">',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'attribute.value.xml' },
+			{ startIndex: 13, type: 'delimiter.xml' }
+		]
+	}],
 
 	[{
-	line: '<tool name="Monaco">',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'attribute.value.xml' },
-		{ startIndex: 19, type: 'delimiter.xml' }
-	]}],
+		line: '<tool name="Monaco">',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'attribute.value.xml' },
+			{ startIndex: 19, type: 'delimiter.xml' }
+		]
+	}],
 
 	[{
-	line: '<tool name=\'Monaco\'>',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'attribute.value.xml' },
-		{ startIndex: 19, type: 'delimiter.xml' }
-	]}],
+		line: '<tool name=\'Monaco\'>',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'attribute.value.xml' },
+			{ startIndex: 19, type: 'delimiter.xml' }
+		]
+	}],
 
 	// Tag with Attributes
 	[{
-	line: '<tool name="Monaco" version="1.0">',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'attribute.value.xml' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'attribute.name.xml' },
-		{ startIndex: 27, type: '' },
-		{ startIndex: 28, type: 'attribute.value.xml' },
-		{ startIndex: 33, type: 'delimiter.xml' }
-	]}],
+		line: '<tool name="Monaco" version="1.0">',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'attribute.value.xml' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'attribute.name.xml' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'attribute.value.xml' },
+			{ startIndex: 33, type: 'delimiter.xml' }
+		]
+	}],
 
 	// Tag with Name-Only-Attribute
 	[{
-	line: '<tool name>',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 10, type: 'delimiter.xml' }
-	]}],
+		line: '<tool name>',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 10, type: 'delimiter.xml' }
+		]
+	}],
 
 	[{
-	line: '<tool name version>',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'attribute.name.xml' },
-		{ startIndex: 18, type: 'delimiter.xml' }
-	]}],
+		line: '<tool name version>',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'attribute.name.xml' },
+			{ startIndex: 18, type: 'delimiter.xml' }
+		]
+	}],
 
 	// Tag with Attribute And Whitespace
 	[{
-	line: '<tool name=  "monaco">',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 13, type: 'attribute.value.xml' },
-		{ startIndex: 21, type: 'delimiter.xml' }
-	]}],
+		line: '<tool name=  "monaco">',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 13, type: 'attribute.value.xml' },
+			{ startIndex: 21, type: 'delimiter.xml' }
+		]
+	}],
 
 	[{
-	line: '<tool name = "monaco">',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 13, type: 'attribute.value.xml' },
-		{ startIndex: 21, type: 'delimiter.xml' }
-	]}],
+		line: '<tool name = "monaco">',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 13, type: 'attribute.value.xml' },
+			{ startIndex: 21, type: 'delimiter.xml' }
+		]
+	}],
 
 	// Tag with Invalid Attribute Name
 	[{
-	line: '<tool name!@#="bar">',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 15, type: 'attribute.name.xml' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'delimiter.xml' }
-	]}],
+		line: '<tool name!@#="bar">',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 15, type: 'attribute.name.xml' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'delimiter.xml' }
+		]
+	}],
 
 	// Tag with Invalid Attribute Value
 	[{
-	line: '<tool name=">',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'attribute.value.xml' },
-		{ startIndex: 12, type: 'delimiter.xml' }
-	]}],
+		line: '<tool name=">',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'attribute.value.xml' },
+			{ startIndex: 12, type: 'delimiter.xml' }
+		]
+	}],
 
 	// Complete End Tag
 	[{
-	line: '</person>',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 2, type: 'tag.xml' },
-		{ startIndex: 8, type: 'delimiter.xml' }
-	]}],
+		line: '</person>',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 2, type: 'tag.xml' },
+			{ startIndex: 8, type: 'delimiter.xml' }
+		]
+	}],
 
 	// Complete End Tag with Whitespace
 	[{
-	line: '</person  >',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 2, type: 'tag.xml' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 10, type: 'delimiter.xml' }
-	]}],
+		line: '</person  >',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 2, type: 'tag.xml' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 10, type: 'delimiter.xml' }
+		]
+	}],
 
 	// Incomplete End Tag
 	[{
-	line: '</person',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}],
+		line: '</person',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}],
 
 	// Comments
 	[{
-	line: '<!-- -->',
-	tokens: [
-		{ startIndex: 0, type: 'comment.xml' },
-		{ startIndex: 4, type: 'comment.content.xml' },
-		{ startIndex: 5, type: 'comment.xml' }
-	]}],
+		line: '<!-- -->',
+		tokens: [
+			{ startIndex: 0, type: 'comment.xml' },
+			{ startIndex: 4, type: 'comment.content.xml' },
+			{ startIndex: 5, type: 'comment.xml' }
+		]
+	}],
 
 	[{
-	line: '<!--a>monaco</a -->',
-	tokens: [
-		{ startIndex: 0, type: 'comment.xml' },
-		{ startIndex: 4, type: 'comment.content.xml' },
-		{ startIndex: 16, type: 'comment.xml' }
-	]}],
+		line: '<!--a>monaco</a -->',
+		tokens: [
+			{ startIndex: 0, type: 'comment.xml' },
+			{ startIndex: 4, type: 'comment.content.xml' },
+			{ startIndex: 16, type: 'comment.xml' }
+		]
+	}],
 
 	[{
-	line: '<!--a>',
-	tokens: [
-		{ startIndex: 0, type: 'comment.xml' },
-		{ startIndex: 4, type: 'comment.content.xml' }
-	]},{
-	line: 'monaco ',
-	tokens: [
-		{ startIndex: 0, type: 'comment.content.xml' }
-	]},{
-	line: 'tools</a -->',
-	tokens: [
-		{ startIndex: 0, type: 'comment.content.xml' },
-		{ startIndex: 9, type: 'comment.xml' }
-	]}],
+		line: '<!--a>',
+		tokens: [
+			{ startIndex: 0, type: 'comment.xml' },
+			{ startIndex: 4, type: 'comment.content.xml' }
+		]
+	}, {
+		line: 'monaco ',
+		tokens: [
+			{ startIndex: 0, type: 'comment.content.xml' }
+		]
+	}, {
+		line: 'tools</a -->',
+		tokens: [
+			{ startIndex: 0, type: 'comment.content.xml' },
+			{ startIndex: 9, type: 'comment.xml' }
+		]
+	}],
 
 	// CDATA
 	[{
-	line: '<tools><![CDATA[<person/>]]></tools>',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 6, type: 'delimiter.xml' },
-		{ startIndex: 7, type: 'delimiter.cdata.xml' },
-		{ startIndex: 16, type: '' },
-		{ startIndex: 25, type: 'delimiter.cdata.xml' },
-		{ startIndex: 28, type: 'delimiter.xml' },
-		{ startIndex: 30, type: 'tag.xml' },
-		{ startIndex: 35, type: 'delimiter.xml' }
-	]}],
+		line: '<tools><![CDATA[<person/>]]></tools>',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 6, type: 'delimiter.xml' },
+			{ startIndex: 7, type: 'delimiter.cdata.xml' },
+			{ startIndex: 16, type: '' },
+			{ startIndex: 25, type: 'delimiter.cdata.xml' },
+			{ startIndex: 28, type: 'delimiter.xml' },
+			{ startIndex: 30, type: 'tag.xml' },
+			{ startIndex: 35, type: 'delimiter.xml' }
+		]
+	}],
 
 	[{
-	line: '<tools>',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 6, type: 'delimiter.xml' }
-	]},{
-	line: '\t<![CDATA[',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.cdata.xml' }
-	]},{
-	line: '\t\t<person/>',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]},{
-	line: '\t]]>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.cdata.xml' },
-	]},{
-	line: '</tools>',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 2, type: 'tag.xml' },
-		{ startIndex: 7, type: 'delimiter.xml' }
-	]}],
+		line: '<tools>',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 6, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '\t<![CDATA[',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.cdata.xml' }
+		]
+	}, {
+		line: '\t\t<person/>',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '\t]]>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.cdata.xml' },
+		]
+	}, {
+		line: '</tools>',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 2, type: 'tag.xml' },
+			{ startIndex: 7, type: 'delimiter.xml' }
+		]
+	}],
 
 	// Generated from sample
 	[{
-	line: '<?xml version="1.0"?>',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 2, type: 'metatag.xml' },
-		{ startIndex: 5, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'attribute.value.xml' },
-		{ startIndex: 19, type: 'delimiter.xml' }
-	]}, {
-	line: '<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 1, type: 'tag.xml' },
-		{ startIndex: 14, type: '' },
-		{ startIndex: 15, type: 'attribute.name.xml' },
-		{ startIndex: 24, type: '' },
-		{ startIndex: 25, type: 'attribute.value.xml' },
-		{ startIndex: 78, type: 'delimiter.xml' }
-	]}, {
-	line: '  <connectionStrings>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.xml' },
-		{ startIndex: 3, type: 'tag.xml' },
-		{ startIndex: 20, type: 'delimiter.xml' }
-	]}, {
-	line: '    <add name="MyDB" ',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'delimiter.xml' },
-		{ startIndex: 5, type: 'tag.xml' },
-		{ startIndex: 8, type: '' },
-		{ startIndex: 9, type: 'attribute.name.xml' },
-		{ startIndex: 13, type: '' },
-		{ startIndex: 14, type: 'attribute.value.xml' },
-		{ startIndex: 20, type: '' }
-	]}, {
-	line: '      connectionString="value for the deployed Web.config file" ',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'attribute.value.xml' },
-		{ startIndex: 63, type: '' }
-	]}, {
-	line: '      xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 19, type: '' },
-		{ startIndex: 20, type: 'attribute.value.xml' },
-		{ startIndex: 35, type: '' },
-		{ startIndex: 36, type: 'attribute.name.xml' },
-		{ startIndex: 47, type: '' },
-		{ startIndex: 48, type: 'attribute.value.xml' },
-		{ startIndex: 61, type: 'tag.xml' },
-		{ startIndex: 62, type: 'delimiter.xml' }
-	]}, {
-	line: '  </connectionStrings>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.xml' },
-		{ startIndex: 4, type: 'tag.xml' },
-		{ startIndex: 21, type: 'delimiter.xml' }
-	]}, {
-	line: '  <system.web>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.xml' },
-		{ startIndex: 3, type: 'tag.xml' },
-		{ startIndex: 13, type: 'delimiter.xml' }
-	]}, {
-	line: '    <customErrors defaultRedirect="GenericError.htm"',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'delimiter.xml' },
-		{ startIndex: 5, type: 'tag.xml' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: 'attribute.name.xml' },
-		{ startIndex: 33, type: '' },
-		{ startIndex: 34, type: 'attribute.value.xml' }
-	]}, {
-	line: '      mode="RemoteOnly" xdt:Transform="Replace">',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'attribute.name.xml' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'attribute.value.xml' },
-		{ startIndex: 23, type: '' },
-		{ startIndex: 24, type: 'attribute.name.xml' },
-		{ startIndex: 37, type: '' },
-		{ startIndex: 38, type: 'attribute.value.xml' },
-		{ startIndex: 47, type: 'delimiter.xml' }
-	]}, {
-	line: '      <error statusCode="500" redirect="InternalError.htm"/>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 6, type: 'delimiter.xml' },
-		{ startIndex: 7, type: 'tag.xml' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'attribute.name.xml' },
-		{ startIndex: 23, type: '' },
-		{ startIndex: 24, type: 'attribute.value.xml' },
-		{ startIndex: 29, type: '' },
-		{ startIndex: 30, type: 'attribute.name.xml' },
-		{ startIndex: 38, type: '' },
-		{ startIndex: 39, type: 'attribute.value.xml' },
-		{ startIndex: 58, type: 'tag.xml' },
-		{ startIndex: 59, type: 'delimiter.xml' }
-	]}, {
-	line: '    </customErrors>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 4, type: 'delimiter.xml' },
-		{ startIndex: 6, type: 'tag.xml' },
-		{ startIndex: 18, type: 'delimiter.xml' }
-	]}, {
-	line: '  </system.web>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 2, type: 'delimiter.xml' },
-		{ startIndex: 4, type: 'tag.xml' },
-		{ startIndex: 14, type: 'delimiter.xml' }
-	]}, {
-	line: '	',
-	tokens: [
-		{ startIndex: 0, type: '' }
-	]}, {
-	line: '	<!-- The stuff below was added for extra tokenizer testing -->',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'comment.xml' },
-		{ startIndex: 5, type: 'comment.content.xml' },
-		{ startIndex: 60, type: 'comment.xml' }
-	]}, {
-	line: '	<!-- A multi-line comment <with> </with>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'comment.xml' },
-		{ startIndex: 5, type: 'comment.content.xml' }
-	]}, {
-	line: '       <tags>',
-	tokens: [
-		{ startIndex: 0, type: 'comment.content.xml' }
-	]}, {
-	line: '				 -->',
-	tokens: [
-		{ startIndex: 0, type: 'comment.content.xml' },
-		{ startIndex: 5, type: 'comment.xml' }
-	]}, {
-	line: '	<!DOCTYPE another meta tag>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.xml' },
-		{ startIndex: 3, type: 'metatag.xml' },
-		{ startIndex: 10, type: '' },
-		{ startIndex: 11, type: 'attribute.name.xml' },
-		{ startIndex: 18, type: '' },
-		{ startIndex: 19, type: 'attribute.name.xml' },
-		{ startIndex: 23, type: '' },
-		{ startIndex: 24, type: 'attribute.name.xml' },
-		{ startIndex: 27, type: 'delimiter.xml' }
-	]}, {
-	line: '	<tools><![CDATA[Some text and tags <person/>]]></tools>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.xml' },
-		{ startIndex: 2, type: 'tag.xml' },
-		{ startIndex: 7, type: 'delimiter.xml' },
-		{ startIndex: 8, type: 'delimiter.cdata.xml' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 45, type: 'delimiter.cdata.xml' },
-		{ startIndex: 48, type: 'delimiter.xml' },
-		{ startIndex: 50, type: 'tag.xml' },
-		{ startIndex: 55, type: 'delimiter.xml' }
-	]}, {
-	line: '	<aSelfClosingTag with="attribute" />',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.xml' },
-		{ startIndex: 2, type: 'tag.xml' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: 'attribute.name.xml' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'attribute.value.xml' },
-		{ startIndex: 34, type: '' },
-		{ startIndex: 35, type: 'tag.xml' },
-		{ startIndex: 36, type: 'delimiter.xml' }
-	]}, {
-	line: '	<aSelfClosingTag with="attribute"/>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.xml' },
-		{ startIndex: 2, type: 'tag.xml' },
-		{ startIndex: 17, type: '' },
-		{ startIndex: 18, type: 'attribute.name.xml' },
-		{ startIndex: 22, type: '' },
-		{ startIndex: 23, type: 'attribute.value.xml' },
-		{ startIndex: 34, type: 'tag.xml' },
-		{ startIndex: 35, type: 'delimiter.xml' }
-	]}, {
-	line: '	<namespace:aSelfClosingTag otherspace:with="attribute"/>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.xml' },
-		{ startIndex: 2, type: 'tag.xml' },
-		{ startIndex: 27, type: '' },
-		{ startIndex: 28, type: 'attribute.name.xml' },
-		{ startIndex: 43, type: '' },
-		{ startIndex: 44, type: 'attribute.value.xml' },
-		{ startIndex: 55, type: 'tag.xml' },
-		{ startIndex: 56, type: 'delimiter.xml' }
-	]}, {
-	line: '	<valid-name also_valid this.one=\'too is valid\'/>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.xml' },
-		{ startIndex: 2, type: 'tag.xml' },
-		{ startIndex: 12, type: '' },
-		{ startIndex: 13, type: 'attribute.name.xml' },
-		{ startIndex: 23, type: '' },
-		{ startIndex: 24, type: 'attribute.name.xml' },
-		{ startIndex: 32, type: '' },
-		{ startIndex: 33, type: 'attribute.value.xml' },
-		{ startIndex: 47, type: 'tag.xml' },
-		{ startIndex: 48, type: 'delimiter.xml' }
-	]}, {
-	line: '	<aSimpleSelfClosingTag />',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.xml' },
-		{ startIndex: 2, type: 'tag.xml' },
-		{ startIndex: 23, type: '' },
-		{ startIndex: 24, type: 'tag.xml' },
-		{ startIndex: 25, type: 'delimiter.xml' }
-	]}, {
-	line: '	<aSimpleSelfClosingTag/>',
-	tokens: [
-		{ startIndex: 0, type: '' },
-		{ startIndex: 1, type: 'delimiter.xml' },
-		{ startIndex: 2, type: 'tag.xml' },
-		{ startIndex: 24, type: 'delimiter.xml' }
-	]}, {
-	line: '</configuration>',
-	tokens: [
-		{ startIndex: 0, type: 'delimiter.xml' },
-		{ startIndex: 2, type: 'tag.xml' },
-		{ startIndex: 15, type: 'delimiter.xml' }
-	]}]
+		line: '<?xml version="1.0"?>',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 2, type: 'metatag.xml' },
+			{ startIndex: 5, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'attribute.value.xml' },
+			{ startIndex: 19, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 1, type: 'tag.xml' },
+			{ startIndex: 14, type: '' },
+			{ startIndex: 15, type: 'attribute.name.xml' },
+			{ startIndex: 24, type: '' },
+			{ startIndex: 25, type: 'attribute.value.xml' },
+			{ startIndex: 78, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '  <connectionStrings>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.xml' },
+			{ startIndex: 3, type: 'tag.xml' },
+			{ startIndex: 20, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '    <add name="MyDB" ',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'delimiter.xml' },
+			{ startIndex: 5, type: 'tag.xml' },
+			{ startIndex: 8, type: '' },
+			{ startIndex: 9, type: 'attribute.name.xml' },
+			{ startIndex: 13, type: '' },
+			{ startIndex: 14, type: 'attribute.value.xml' },
+			{ startIndex: 20, type: '' }
+		]
+	}, {
+		line: '      connectionString="value for the deployed Web.config file" ',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'attribute.value.xml' },
+			{ startIndex: 63, type: '' }
+		]
+	}, {
+		line: '      xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 19, type: '' },
+			{ startIndex: 20, type: 'attribute.value.xml' },
+			{ startIndex: 35, type: '' },
+			{ startIndex: 36, type: 'attribute.name.xml' },
+			{ startIndex: 47, type: '' },
+			{ startIndex: 48, type: 'attribute.value.xml' },
+			{ startIndex: 61, type: 'tag.xml' },
+			{ startIndex: 62, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '  </connectionStrings>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.xml' },
+			{ startIndex: 4, type: 'tag.xml' },
+			{ startIndex: 21, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '  <system.web>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.xml' },
+			{ startIndex: 3, type: 'tag.xml' },
+			{ startIndex: 13, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '    <customErrors defaultRedirect="GenericError.htm"',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'delimiter.xml' },
+			{ startIndex: 5, type: 'tag.xml' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'attribute.name.xml' },
+			{ startIndex: 33, type: '' },
+			{ startIndex: 34, type: 'attribute.value.xml' }
+		]
+	}, {
+		line: '      mode="RemoteOnly" xdt:Transform="Replace">',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'attribute.name.xml' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'attribute.value.xml' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'attribute.name.xml' },
+			{ startIndex: 37, type: '' },
+			{ startIndex: 38, type: 'attribute.value.xml' },
+			{ startIndex: 47, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '      <error statusCode="500" redirect="InternalError.htm"/>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 6, type: 'delimiter.xml' },
+			{ startIndex: 7, type: 'tag.xml' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'attribute.name.xml' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'attribute.value.xml' },
+			{ startIndex: 29, type: '' },
+			{ startIndex: 30, type: 'attribute.name.xml' },
+			{ startIndex: 38, type: '' },
+			{ startIndex: 39, type: 'attribute.value.xml' },
+			{ startIndex: 58, type: 'tag.xml' },
+			{ startIndex: 59, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '    </customErrors>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 4, type: 'delimiter.xml' },
+			{ startIndex: 6, type: 'tag.xml' },
+			{ startIndex: 18, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '  </system.web>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 2, type: 'delimiter.xml' },
+			{ startIndex: 4, type: 'tag.xml' },
+			{ startIndex: 14, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '	',
+		tokens: [
+			{ startIndex: 0, type: '' }
+		]
+	}, {
+		line: '	<!-- The stuff below was added for extra tokenizer testing -->',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'comment.xml' },
+			{ startIndex: 5, type: 'comment.content.xml' },
+			{ startIndex: 60, type: 'comment.xml' }
+		]
+	}, {
+		line: '	<!-- A multi-line comment <with> </with>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'comment.xml' },
+			{ startIndex: 5, type: 'comment.content.xml' }
+		]
+	}, {
+		line: '       <tags>',
+		tokens: [
+			{ startIndex: 0, type: 'comment.content.xml' }
+		]
+	}, {
+		line: '				 -->',
+		tokens: [
+			{ startIndex: 0, type: 'comment.content.xml' },
+			{ startIndex: 5, type: 'comment.xml' }
+		]
+	}, {
+		line: '	<!DOCTYPE another meta tag>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.xml' },
+			{ startIndex: 3, type: 'metatag.xml' },
+			{ startIndex: 10, type: '' },
+			{ startIndex: 11, type: 'attribute.name.xml' },
+			{ startIndex: 18, type: '' },
+			{ startIndex: 19, type: 'attribute.name.xml' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'attribute.name.xml' },
+			{ startIndex: 27, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '	<tools><![CDATA[Some text and tags <person/>]]></tools>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.xml' },
+			{ startIndex: 2, type: 'tag.xml' },
+			{ startIndex: 7, type: 'delimiter.xml' },
+			{ startIndex: 8, type: 'delimiter.cdata.xml' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 45, type: 'delimiter.cdata.xml' },
+			{ startIndex: 48, type: 'delimiter.xml' },
+			{ startIndex: 50, type: 'tag.xml' },
+			{ startIndex: 55, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '	<aSelfClosingTag with="attribute" />',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.xml' },
+			{ startIndex: 2, type: 'tag.xml' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'attribute.name.xml' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'attribute.value.xml' },
+			{ startIndex: 34, type: '' },
+			{ startIndex: 35, type: 'tag.xml' },
+			{ startIndex: 36, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '	<aSelfClosingTag with="attribute"/>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.xml' },
+			{ startIndex: 2, type: 'tag.xml' },
+			{ startIndex: 17, type: '' },
+			{ startIndex: 18, type: 'attribute.name.xml' },
+			{ startIndex: 22, type: '' },
+			{ startIndex: 23, type: 'attribute.value.xml' },
+			{ startIndex: 34, type: 'tag.xml' },
+			{ startIndex: 35, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '	<namespace:aSelfClosingTag otherspace:with="attribute"/>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.xml' },
+			{ startIndex: 2, type: 'tag.xml' },
+			{ startIndex: 27, type: '' },
+			{ startIndex: 28, type: 'attribute.name.xml' },
+			{ startIndex: 43, type: '' },
+			{ startIndex: 44, type: 'attribute.value.xml' },
+			{ startIndex: 55, type: 'tag.xml' },
+			{ startIndex: 56, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '	<valid-name also_valid this.one=\'too is valid\'/>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.xml' },
+			{ startIndex: 2, type: 'tag.xml' },
+			{ startIndex: 12, type: '' },
+			{ startIndex: 13, type: 'attribute.name.xml' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'attribute.name.xml' },
+			{ startIndex: 32, type: '' },
+			{ startIndex: 33, type: 'attribute.value.xml' },
+			{ startIndex: 47, type: 'tag.xml' },
+			{ startIndex: 48, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '	<aSimpleSelfClosingTag />',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.xml' },
+			{ startIndex: 2, type: 'tag.xml' },
+			{ startIndex: 23, type: '' },
+			{ startIndex: 24, type: 'tag.xml' },
+			{ startIndex: 25, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '	<aSimpleSelfClosingTag/>',
+		tokens: [
+			{ startIndex: 0, type: '' },
+			{ startIndex: 1, type: 'delimiter.xml' },
+			{ startIndex: 2, type: 'tag.xml' },
+			{ startIndex: 24, type: 'delimiter.xml' }
+		]
+	}, {
+		line: '</configuration>',
+		tokens: [
+			{ startIndex: 0, type: 'delimiter.xml' },
+			{ startIndex: 2, type: 'tag.xml' },
+			{ startIndex: 15, type: 'delimiter.xml' }
+		]
+	}]
 ]);

+ 2 - 2
test/yaml.test.ts

@@ -1,4 +1,4 @@
-import {testTokenization} from './testRunner';
+import { testTokenization } from './testRunner';
 
 testTokenization('yaml', [
 	// YAML directive
@@ -238,7 +238,7 @@ testTokenization('yaml', [
 		}, {
 			startIndex: 24,
 			type: 'delimiter.bracket.yaml'
-		}, ]
+		},]
 	}],
 
 	// Flow Sequence - Data types

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно