1package h
2
3import (
4	. "github.com/alecthomas/chroma" // nolint
5	"github.com/alecthomas/chroma/lexers/internal"
6)
7
8// Haxe lexer.
9var Haxe = internal.Register(MustNewLazyLexer(
10	&Config{
11		Name:      "Haxe",
12		Aliases:   []string{"hx", "haxe", "hxsl"},
13		Filenames: []string{"*.hx", "*.hxsl"},
14		MimeTypes: []string{"text/haxe", "text/x-haxe", "text/x-hx"},
15		DotAll:    true,
16	},
17	haxeRules,
18))
19
20func haxeRules() Rules {
21	return Rules{
22		"root": {
23			Include("spaces"),
24			Include("meta"),
25			{`(?:package)\b`, KeywordNamespace, Push("semicolon", "package")},
26			{`(?:import)\b`, KeywordNamespace, Push("semicolon", "import")},
27			{`(?:using)\b`, KeywordNamespace, Push("semicolon", "using")},
28			{`(?:extern|private)\b`, KeywordDeclaration, nil},
29			{`(?:abstract)\b`, KeywordDeclaration, Push("abstract")},
30			{`(?:class|interface)\b`, KeywordDeclaration, Push("class")},
31			{`(?:enum)\b`, KeywordDeclaration, Push("enum")},
32			{`(?:typedef)\b`, KeywordDeclaration, Push("typedef")},
33			{`(?=.)`, Text, Push("expr-statement")},
34		},
35		"spaces": {
36			{`\s+`, Text, nil},
37			{`//[^\n\r]*`, CommentSingle, nil},
38			{`/\*.*?\*/`, CommentMultiline, nil},
39			{`(#)(if|elseif|else|end|error)\b`, CommentPreproc, MutatorFunc(haxePreProcMutator)},
40		},
41		"string-single-interpol": {
42			{`\$\{`, LiteralStringInterpol, Push("string-interpol-close", "expr")},
43			{`\$\$`, LiteralStringEscape, nil},
44			{`\$(?=(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+))`, LiteralStringInterpol, Push("ident")},
45			Include("string-single"),
46		},
47		"string-single": {
48			{`'`, LiteralStringSingle, Pop(1)},
49			{`\\.`, LiteralStringEscape, nil},
50			{`.`, LiteralStringSingle, nil},
51		},
52		"string-double": {
53			{`"`, LiteralStringDouble, Pop(1)},
54			{`\\.`, LiteralStringEscape, nil},
55			{`.`, LiteralStringDouble, nil},
56		},
57		"string-interpol-close": {
58			{`\$(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, LiteralStringInterpol, nil},
59			{`\}`, LiteralStringInterpol, Pop(1)},
60		},
61		"package": {
62			Include("spaces"),
63			{`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameNamespace, nil},
64			{`\.`, Punctuation, Push("import-ident")},
65			Default(Pop(1)),
66		},
67		"import": {
68			Include("spaces"),
69			{`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameNamespace, nil},
70			{`\*`, Keyword, nil},
71			{`\.`, Punctuation, Push("import-ident")},
72			{`in`, KeywordNamespace, Push("ident")},
73			Default(Pop(1)),
74		},
75		"import-ident": {
76			Include("spaces"),
77			{`\*`, Keyword, Pop(1)},
78			{`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameNamespace, Pop(1)},
79		},
80		"using": {
81			Include("spaces"),
82			{`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameNamespace, nil},
83			{`\.`, Punctuation, Push("import-ident")},
84			Default(Pop(1)),
85		},
86		"preproc-error": {
87			{`\s+`, CommentPreproc, nil},
88			{`'`, LiteralStringSingle, Push("#pop", "string-single")},
89			{`"`, LiteralStringDouble, Push("#pop", "string-double")},
90			Default(Pop(1)),
91		},
92		"preproc-expr": {
93			{`\s+`, CommentPreproc, nil},
94			{`\!`, CommentPreproc, nil},
95			{`\(`, CommentPreproc, Push("#pop", "preproc-parenthesis")},
96			{`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, CommentPreproc, Pop(1)},
97			{`\.[0-9]+`, LiteralNumberFloat, nil},
98			{`[0-9]+[eE][+\-]?[0-9]+`, LiteralNumberFloat, nil},
99			{`[0-9]+\.[0-9]*[eE][+\-]?[0-9]+`, LiteralNumberFloat, nil},
100			{`[0-9]+\.[0-9]+`, LiteralNumberFloat, nil},
101			{`[0-9]+\.(?!(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)|\.\.)`, LiteralNumberFloat, nil},
102			{`0x[0-9a-fA-F]+`, LiteralNumberHex, nil},
103			{`[0-9]+`, LiteralNumberInteger, nil},
104			{`'`, LiteralStringSingle, Push("#pop", "string-single")},
105			{`"`, LiteralStringDouble, Push("#pop", "string-double")},
106		},
107		"preproc-parenthesis": {
108			{`\s+`, CommentPreproc, nil},
109			{`\)`, CommentPreproc, Pop(1)},
110			Default(Push("preproc-expr-in-parenthesis")),
111		},
112		"preproc-expr-chain": {
113			{`\s+`, CommentPreproc, nil},
114			{`(?:%=|&=|\|=|\^=|\+=|\-=|\*=|/=|<<=|>\s*>\s*=|>\s*>\s*>\s*=|==|!=|<=|>\s*=|&&|\|\||<<|>>>|>\s*>|\.\.\.|<|>|%|&|\||\^|\+|\*|/|\-|=>|=)`, CommentPreproc, Push("#pop", "preproc-expr-in-parenthesis")},
115			Default(Pop(1)),
116		},
117		"preproc-expr-in-parenthesis": {
118			{`\s+`, CommentPreproc, nil},
119			{`\!`, CommentPreproc, nil},
120			{`\(`, CommentPreproc, Push("#pop", "preproc-expr-chain", "preproc-parenthesis")},
121			{`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, CommentPreproc, Push("#pop", "preproc-expr-chain")},
122			{`\.[0-9]+`, LiteralNumberFloat, Push("#pop", "preproc-expr-chain")},
123			{`[0-9]+[eE][+\-]?[0-9]+`, LiteralNumberFloat, Push("#pop", "preproc-expr-chain")},
124			{`[0-9]+\.[0-9]*[eE][+\-]?[0-9]+`, LiteralNumberFloat, Push("#pop", "preproc-expr-chain")},
125			{`[0-9]+\.[0-9]+`, LiteralNumberFloat, Push("#pop", "preproc-expr-chain")},
126			{`[0-9]+\.(?!(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)|\.\.)`, LiteralNumberFloat, Push("#pop", "preproc-expr-chain")},
127			{`0x[0-9a-fA-F]+`, LiteralNumberHex, Push("#pop", "preproc-expr-chain")},
128			{`[0-9]+`, LiteralNumberInteger, Push("#pop", "preproc-expr-chain")},
129			{`'`, LiteralStringSingle, Push("#pop", "preproc-expr-chain", "string-single")},
130			{`"`, LiteralStringDouble, Push("#pop", "preproc-expr-chain", "string-double")},
131		},
132		"abstract": {
133			Include("spaces"),
134			Default(Pop(1), Push("abstract-body"), Push("abstract-relation"), Push("abstract-opaque"), Push("type-param-constraint"), Push("type-name")),
135		},
136		"abstract-body": {
137			Include("spaces"),
138			{`\{`, Punctuation, Push("#pop", "class-body")},
139		},
140		"abstract-opaque": {
141			Include("spaces"),
142			{`\(`, Punctuation, Push("#pop", "parenthesis-close", "type")},
143			Default(Pop(1)),
144		},
145		"abstract-relation": {
146			Include("spaces"),
147			{`(?:to|from)`, KeywordDeclaration, Push("type")},
148			{`,`, Punctuation, nil},
149			Default(Pop(1)),
150		},
151		"meta": {
152			Include("spaces"),
153			{`@`, NameDecorator, Push("meta-body", "meta-ident", "meta-colon")},
154		},
155		"meta-colon": {
156			Include("spaces"),
157			{`:`, NameDecorator, Pop(1)},
158			Default(Pop(1)),
159		},
160		"meta-ident": {
161			Include("spaces"),
162			{`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameDecorator, Pop(1)},
163		},
164		"meta-body": {
165			Include("spaces"),
166			{`\(`, NameDecorator, Push("#pop", "meta-call")},
167			Default(Pop(1)),
168		},
169		"meta-call": {
170			Include("spaces"),
171			{`\)`, NameDecorator, Pop(1)},
172			Default(Pop(1), Push("meta-call-sep"), Push("expr")),
173		},
174		"meta-call-sep": {
175			Include("spaces"),
176			{`\)`, NameDecorator, Pop(1)},
177			{`,`, Punctuation, Push("#pop", "meta-call")},
178		},
179		"typedef": {
180			Include("spaces"),
181			Default(Pop(1), Push("typedef-body"), Push("type-param-constraint"), Push("type-name")),
182		},
183		"typedef-body": {
184			Include("spaces"),
185			{`=`, Operator, Push("#pop", "optional-semicolon", "type")},
186		},
187		"enum": {
188			Include("spaces"),
189			Default(Pop(1), Push("enum-body"), Push("bracket-open"), Push("type-param-constraint"), Push("type-name")),
190		},
191		"enum-body": {
192			Include("spaces"),
193			Include("meta"),
194			{`\}`, Punctuation, Pop(1)},
195			{`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Push("enum-member", "type-param-constraint")},
196		},
197		"enum-member": {
198			Include("spaces"),
199			{`\(`, Punctuation, Push("#pop", "semicolon", "flag", "function-param")},
200			Default(Pop(1), Push("semicolon"), Push("flag")),
201		},
202		"class": {
203			Include("spaces"),
204			Default(Pop(1), Push("class-body"), Push("bracket-open"), Push("extends"), Push("type-param-constraint"), Push("type-name")),
205		},
206		"extends": {
207			Include("spaces"),
208			{`(?:extends|implements)\b`, KeywordDeclaration, Push("type")},
209			{`,`, Punctuation, nil},
210			Default(Pop(1)),
211		},
212		"bracket-open": {
213			Include("spaces"),
214			{`\{`, Punctuation, Pop(1)},
215		},
216		"bracket-close": {
217			Include("spaces"),
218			{`\}`, Punctuation, Pop(1)},
219		},
220		"class-body": {
221			Include("spaces"),
222			Include("meta"),
223			{`\}`, Punctuation, Pop(1)},
224			{`(?:static|public|private|override|dynamic|inline|macro)\b`, KeywordDeclaration, nil},
225			Default(Push("class-member")),
226		},
227		"class-member": {
228			Include("spaces"),
229			{`(var)\b`, KeywordDeclaration, Push("#pop", "optional-semicolon", "var")},
230			{`(function)\b`, KeywordDeclaration, Push("#pop", "optional-semicolon", "class-method")},
231		},
232		"function-local": {
233			Include("spaces"),
234			{`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameFunction, Push("#pop", "optional-expr", "flag", "function-param", "parenthesis-open", "type-param-constraint")},
235			Default(Pop(1), Push("optional-expr"), Push("flag"), Push("function-param"), Push("parenthesis-open"), Push("type-param-constraint")),
236		},
237		"optional-expr": {
238			Include("spaces"),
239			Include("expr"),
240			Default(Pop(1)),
241		},
242		"class-method": {
243			Include("spaces"),
244			{`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, NameFunction, Push("#pop", "optional-expr", "flag", "function-param", "parenthesis-open", "type-param-constraint")},
245		},
246		"function-param": {
247			Include("spaces"),
248			{`\)`, Punctuation, Pop(1)},
249			{`\?`, Punctuation, nil},
250			{`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Push("#pop", "function-param-sep", "assign", "flag")},
251		},
252		"function-param-sep": {
253			Include("spaces"),
254			{`\)`, Punctuation, Pop(1)},
255			{`,`, Punctuation, Push("#pop", "function-param")},
256		},
257		"prop-get-set": {
258			Include("spaces"),
259			{`\(`, Punctuation, Push("#pop", "parenthesis-close", "prop-get-set-opt", "comma", "prop-get-set-opt")},
260			Default(Pop(1)),
261		},
262		"prop-get-set-opt": {
263			Include("spaces"),
264			{`(?:default|null|never|dynamic|get|set)\b`, Keyword, Pop(1)},
265			{`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Text, Pop(1)},
266		},
267		"expr-statement": {
268			Include("spaces"),
269			Default(Pop(1), Push("optional-semicolon"), Push("expr")),
270		},
271		"expr": {
272			Include("spaces"),
273			{`@`, NameDecorator, Push("#pop", "optional-expr", "meta-body", "meta-ident", "meta-colon")},
274			{`(?:\+\+|\-\-|~(?!/)|!|\-)`, Operator, nil},
275			{`\(`, Punctuation, Push("#pop", "expr-chain", "parenthesis")},
276			{`(?:static|public|private|override|dynamic|inline)\b`, KeywordDeclaration, nil},
277			{`(?:function)\b`, KeywordDeclaration, Push("#pop", "expr-chain", "function-local")},
278			{`\{`, Punctuation, Push("#pop", "expr-chain", "bracket")},
279			{`(?:true|false|null)\b`, KeywordConstant, Push("#pop", "expr-chain")},
280			{`(?:this)\b`, Keyword, Push("#pop", "expr-chain")},
281			{`(?:cast)\b`, Keyword, Push("#pop", "expr-chain", "cast")},
282			{`(?:try)\b`, Keyword, Push("#pop", "catch", "expr")},
283			{`(?:var)\b`, KeywordDeclaration, Push("#pop", "var")},
284			{`(?:new)\b`, Keyword, Push("#pop", "expr-chain", "new")},
285			{`(?:switch)\b`, Keyword, Push("#pop", "switch")},
286			{`(?:if)\b`, Keyword, Push("#pop", "if")},
287			{`(?:do)\b`, Keyword, Push("#pop", "do")},
288			{`(?:while)\b`, Keyword, Push("#pop", "while")},
289			{`(?:for)\b`, Keyword, Push("#pop", "for")},
290			{`(?:untyped|throw)\b`, Keyword, nil},
291			{`(?:return)\b`, Keyword, Push("#pop", "optional-expr")},
292			{`(?:macro)\b`, Keyword, Push("#pop", "macro")},
293			{`(?:continue|break)\b`, Keyword, Pop(1)},
294			{`(?:\$\s*[a-z]\b|\$(?!(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)))`, Name, Push("#pop", "dollar")},
295			{`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Push("#pop", "expr-chain")},
296			{`\.[0-9]+`, LiteralNumberFloat, Push("#pop", "expr-chain")},
297			{`[0-9]+[eE][+\-]?[0-9]+`, LiteralNumberFloat, Push("#pop", "expr-chain")},
298			{`[0-9]+\.[0-9]*[eE][+\-]?[0-9]+`, LiteralNumberFloat, Push("#pop", "expr-chain")},
299			{`[0-9]+\.[0-9]+`, LiteralNumberFloat, Push("#pop", "expr-chain")},
300			{`[0-9]+\.(?!(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)|\.\.)`, LiteralNumberFloat, Push("#pop", "expr-chain")},
301			{`0x[0-9a-fA-F]+`, LiteralNumberHex, Push("#pop", "expr-chain")},
302			{`[0-9]+`, LiteralNumberInteger, Push("#pop", "expr-chain")},
303			{`'`, LiteralStringSingle, Push("#pop", "expr-chain", "string-single-interpol")},
304			{`"`, LiteralStringDouble, Push("#pop", "expr-chain", "string-double")},
305			{`~/(\\\\|\\/|[^/\n])*/[gimsu]*`, LiteralStringRegex, Push("#pop", "expr-chain")},
306			{`\[`, Punctuation, Push("#pop", "expr-chain", "array-decl")},
307		},
308		"expr-chain": {
309			Include("spaces"),
310			{`(?:\+\+|\-\-)`, Operator, nil},
311			{`(?:%=|&=|\|=|\^=|\+=|\-=|\*=|/=|<<=|>\s*>\s*=|>\s*>\s*>\s*=|==|!=|<=|>\s*=|&&|\|\||<<|>>>|>\s*>|\.\.\.|<|>|%|&|\||\^|\+|\*|/|\-|=>|=)`, Operator, Push("#pop", "expr")},
312			{`(?:in)\b`, Keyword, Push("#pop", "expr")},
313			{`\?`, Operator, Push("#pop", "expr", "ternary", "expr")},
314			{`(\.)((?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+))`, ByGroups(Punctuation, Name), nil},
315			{`\[`, Punctuation, Push("array-access")},
316			{`\(`, Punctuation, Push("call")},
317			Default(Pop(1)),
318		},
319		"macro": {
320			Include("spaces"),
321			Include("meta"),
322			{`:`, Punctuation, Push("#pop", "type")},
323			{`(?:extern|private)\b`, KeywordDeclaration, nil},
324			{`(?:abstract)\b`, KeywordDeclaration, Push("#pop", "optional-semicolon", "abstract")},
325			{`(?:class|interface)\b`, KeywordDeclaration, Push("#pop", "optional-semicolon", "macro-class")},
326			{`(?:enum)\b`, KeywordDeclaration, Push("#pop", "optional-semicolon", "enum")},
327			{`(?:typedef)\b`, KeywordDeclaration, Push("#pop", "optional-semicolon", "typedef")},
328			Default(Pop(1), Push("expr")),
329		},
330		"macro-class": {
331			{`\{`, Punctuation, Push("#pop", "class-body")},
332			Include("class"),
333		},
334		"cast": {
335			Include("spaces"),
336			{`\(`, Punctuation, Push("#pop", "parenthesis-close", "cast-type", "expr")},
337			Default(Pop(1), Push("expr")),
338		},
339		"cast-type": {
340			Include("spaces"),
341			{`,`, Punctuation, Push("#pop", "type")},
342			Default(Pop(1)),
343		},
344		"catch": {
345			Include("spaces"),
346			{`(?:catch)\b`, Keyword, Push("expr", "function-param", "parenthesis-open")},
347			Default(Pop(1)),
348		},
349		"do": {
350			Include("spaces"),
351			Default(Pop(1), Push("do-while"), Push("expr")),
352		},
353		"do-while": {
354			Include("spaces"),
355			{`(?:while)\b`, Keyword, Push("#pop", "parenthesis", "parenthesis-open")},
356		},
357		"while": {
358			Include("spaces"),
359			{`\(`, Punctuation, Push("#pop", "expr", "parenthesis")},
360		},
361		"for": {
362			Include("spaces"),
363			{`\(`, Punctuation, Push("#pop", "expr", "parenthesis")},
364		},
365		"if": {
366			Include("spaces"),
367			{`\(`, Punctuation, Push("#pop", "else", "optional-semicolon", "expr", "parenthesis")},
368		},
369		"else": {
370			Include("spaces"),
371			{`(?:else)\b`, Keyword, Push("#pop", "expr")},
372			Default(Pop(1)),
373		},
374		"switch": {
375			Include("spaces"),
376			Default(Pop(1), Push("switch-body"), Push("bracket-open"), Push("expr")),
377		},
378		"switch-body": {
379			Include("spaces"),
380			{`(?:case|default)\b`, Keyword, Push("case-block", "case")},
381			{`\}`, Punctuation, Pop(1)},
382		},
383		"case": {
384			Include("spaces"),
385			{`:`, Punctuation, Pop(1)},
386			Default(Pop(1), Push("case-sep"), Push("case-guard"), Push("expr")),
387		},
388		"case-sep": {
389			Include("spaces"),
390			{`:`, Punctuation, Pop(1)},
391			{`,`, Punctuation, Push("#pop", "case")},
392		},
393		"case-guard": {
394			Include("spaces"),
395			{`(?:if)\b`, Keyword, Push("#pop", "parenthesis", "parenthesis-open")},
396			Default(Pop(1)),
397		},
398		"case-block": {
399			Include("spaces"),
400			{`(?!(?:case|default)\b|\})`, Keyword, Push("expr-statement")},
401			Default(Pop(1)),
402		},
403		"new": {
404			Include("spaces"),
405			Default(Pop(1), Push("call"), Push("parenthesis-open"), Push("type")),
406		},
407		"array-decl": {
408			Include("spaces"),
409			{`\]`, Punctuation, Pop(1)},
410			Default(Pop(1), Push("array-decl-sep"), Push("expr")),
411		},
412		"array-decl-sep": {
413			Include("spaces"),
414			{`\]`, Punctuation, Pop(1)},
415			{`,`, Punctuation, Push("#pop", "array-decl")},
416		},
417		"array-access": {
418			Include("spaces"),
419			Default(Pop(1), Push("array-access-close"), Push("expr")),
420		},
421		"array-access-close": {
422			Include("spaces"),
423			{`\]`, Punctuation, Pop(1)},
424		},
425		"comma": {
426			Include("spaces"),
427			{`,`, Punctuation, Pop(1)},
428		},
429		"colon": {
430			Include("spaces"),
431			{`:`, Punctuation, Pop(1)},
432		},
433		"semicolon": {
434			Include("spaces"),
435			{`;`, Punctuation, Pop(1)},
436		},
437		"optional-semicolon": {
438			Include("spaces"),
439			{`;`, Punctuation, Pop(1)},
440			Default(Pop(1)),
441		},
442		"ident": {
443			Include("spaces"),
444			{`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Pop(1)},
445		},
446		"dollar": {
447			Include("spaces"),
448			{`\{`, Punctuation, Push("#pop", "expr-chain", "bracket-close", "expr")},
449			Default(Pop(1), Push("expr-chain")),
450		},
451		"type-name": {
452			Include("spaces"),
453			{`_*[A-Z]\w*`, Name, Pop(1)},
454		},
455		"type-full-name": {
456			Include("spaces"),
457			{`\.`, Punctuation, Push("ident")},
458			Default(Pop(1)),
459		},
460		"type": {
461			Include("spaces"),
462			{`\?`, Punctuation, nil},
463			{`(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Push("#pop", "type-check", "type-full-name")},
464			{`\{`, Punctuation, Push("#pop", "type-check", "type-struct")},
465			{`\(`, Punctuation, Push("#pop", "type-check", "type-parenthesis")},
466		},
467		"type-parenthesis": {
468			Include("spaces"),
469			Default(Pop(1), Push("parenthesis-close"), Push("type")),
470		},
471		"type-check": {
472			Include("spaces"),
473			{`->`, Punctuation, Push("#pop", "type")},
474			{`<(?!=)`, Punctuation, Push("type-param")},
475			Default(Pop(1)),
476		},
477		"type-struct": {
478			Include("spaces"),
479			{`\}`, Punctuation, Pop(1)},
480			{`\?`, Punctuation, nil},
481			{`>`, Punctuation, Push("comma", "type")},
482			{`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Push("#pop", "type-struct-sep", "type", "colon")},
483			Include("class-body"),
484		},
485		"type-struct-sep": {
486			Include("spaces"),
487			{`\}`, Punctuation, Pop(1)},
488			{`,`, Punctuation, Push("#pop", "type-struct")},
489		},
490		"type-param-type": {
491			{`\.[0-9]+`, LiteralNumberFloat, Pop(1)},
492			{`[0-9]+[eE][+\-]?[0-9]+`, LiteralNumberFloat, Pop(1)},
493			{`[0-9]+\.[0-9]*[eE][+\-]?[0-9]+`, LiteralNumberFloat, Pop(1)},
494			{`[0-9]+\.[0-9]+`, LiteralNumberFloat, Pop(1)},
495			{`[0-9]+\.(?!(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)|\.\.)`, LiteralNumberFloat, Pop(1)},
496			{`0x[0-9a-fA-F]+`, LiteralNumberHex, Pop(1)},
497			{`[0-9]+`, LiteralNumberInteger, Pop(1)},
498			{`'`, LiteralStringSingle, Push("#pop", "string-single")},
499			{`"`, LiteralStringDouble, Push("#pop", "string-double")},
500			{`~/(\\\\|\\/|[^/\n])*/[gim]*`, LiteralStringRegex, Pop(1)},
501			{`\[`, Operator, Push("#pop", "array-decl")},
502			Include("type"),
503		},
504		"type-param": {
505			Include("spaces"),
506			Default(Pop(1), Push("type-param-sep"), Push("type-param-type")),
507		},
508		"type-param-sep": {
509			Include("spaces"),
510			{`>`, Punctuation, Pop(1)},
511			{`,`, Punctuation, Push("#pop", "type-param")},
512		},
513		"type-param-constraint": {
514			Include("spaces"),
515			{`<(?!=)`, Punctuation, Push("#pop", "type-param-constraint-sep", "type-param-constraint-flag", "type-name")},
516			Default(Pop(1)),
517		},
518		"type-param-constraint-sep": {
519			Include("spaces"),
520			{`>`, Punctuation, Pop(1)},
521			{`,`, Punctuation, Push("#pop", "type-param-constraint-sep", "type-param-constraint-flag", "type-name")},
522		},
523		"type-param-constraint-flag": {
524			Include("spaces"),
525			{`:`, Punctuation, Push("#pop", "type-param-constraint-flag-type")},
526			Default(Pop(1)),
527		},
528		"type-param-constraint-flag-type": {
529			Include("spaces"),
530			{`\(`, Punctuation, Push("#pop", "type-param-constraint-flag-type-sep", "type")},
531			Default(Pop(1), Push("type")),
532		},
533		"type-param-constraint-flag-type-sep": {
534			Include("spaces"),
535			{`\)`, Punctuation, Pop(1)},
536			{`,`, Punctuation, Push("type")},
537		},
538		"parenthesis": {
539			Include("spaces"),
540			Default(Pop(1), Push("parenthesis-close"), Push("flag"), Push("expr")),
541		},
542		"parenthesis-open": {
543			Include("spaces"),
544			{`\(`, Punctuation, Pop(1)},
545		},
546		"parenthesis-close": {
547			Include("spaces"),
548			{`\)`, Punctuation, Pop(1)},
549		},
550		"var": {
551			Include("spaces"),
552			{`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Text, Push("#pop", "var-sep", "assign", "flag", "prop-get-set")},
553		},
554		"var-sep": {
555			Include("spaces"),
556			{`,`, Punctuation, Push("#pop", "var")},
557			Default(Pop(1)),
558		},
559		"assign": {
560			Include("spaces"),
561			{`=`, Operator, Push("#pop", "expr")},
562			Default(Pop(1)),
563		},
564		"flag": {
565			Include("spaces"),
566			{`:`, Punctuation, Push("#pop", "type")},
567			Default(Pop(1)),
568		},
569		"ternary": {
570			Include("spaces"),
571			{`:`, Operator, Pop(1)},
572		},
573		"call": {
574			Include("spaces"),
575			{`\)`, Punctuation, Pop(1)},
576			Default(Pop(1), Push("call-sep"), Push("expr")),
577		},
578		"call-sep": {
579			Include("spaces"),
580			{`\)`, Punctuation, Pop(1)},
581			{`,`, Punctuation, Push("#pop", "call")},
582		},
583		"bracket": {
584			Include("spaces"),
585			{`(?!(?:\$\s*[a-z]\b|\$(?!(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+))))(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Push("#pop", "bracket-check")},
586			{`'`, LiteralStringSingle, Push("#pop", "bracket-check", "string-single")},
587			{`"`, LiteralStringDouble, Push("#pop", "bracket-check", "string-double")},
588			Default(Pop(1), Push("block")),
589		},
590		"bracket-check": {
591			Include("spaces"),
592			{`:`, Punctuation, Push("#pop", "object-sep", "expr")},
593			Default(Pop(1), Push("block"), Push("optional-semicolon"), Push("expr-chain")),
594		},
595		"block": {
596			Include("spaces"),
597			{`\}`, Punctuation, Pop(1)},
598			Default(Push("expr-statement")),
599		},
600		"object": {
601			Include("spaces"),
602			{`\}`, Punctuation, Pop(1)},
603			Default(Pop(1), Push("object-sep"), Push("expr"), Push("colon"), Push("ident-or-string")),
604		},
605		"ident-or-string": {
606			Include("spaces"),
607			{`(?!(?:function|class|static|var|if|else|while|do|for|break|return|continue|extends|implements|import|switch|case|default|public|private|try|untyped|catch|new|this|throw|extern|enum|in|interface|cast|override|dynamic|typedef|package|inline|using|null|true|false|abstract)\b)(?:_*[a-z]\w*|_+[0-9]\w*|_*[A-Z]\w*|_+|\$\w+)`, Name, Pop(1)},
608			{`'`, LiteralStringSingle, Push("#pop", "string-single")},
609			{`"`, LiteralStringDouble, Push("#pop", "string-double")},
610		},
611		"object-sep": {
612			Include("spaces"),
613			{`\}`, Punctuation, Pop(1)},
614			{`,`, Punctuation, Push("#pop", "object")},
615		},
616	}
617}
618
619func haxePreProcMutator(state *LexerState) error {
620	stack, ok := state.Get("haxe-pre-proc").([][]string)
621	if !ok {
622		stack = [][]string{}
623	}
624
625	proc := state.Groups[2]
626	switch proc {
627	case "if":
628		stack = append(stack, state.Stack)
629	case "else", "elseif":
630		if len(stack) > 0 {
631			state.Stack = stack[len(stack)-1]
632		}
633	case "end":
634		stack = stack[:len(stack)-1]
635	}
636
637	if proc == "if" || proc == "elseif" {
638		state.Stack = append(state.Stack, "preproc-expr")
639	}
640
641	if proc == "error" {
642		state.Stack = append(state.Stack, "preproc-error")
643	}
644	state.Set("haxe-pre-proc", stack)
645	return nil
646}
647