# JOE syntax highlight file for Coffeescript

# node = a.b.c /\s+/ seems to be allowed, foo
# need to recognize ... and ..
# include - as part of number?

# after term: it's a regex if

# suppress literals after .

=Idle
=Comment	green
=Constant	cyan
=Escape		bold cyan
=Operator	bold
=Keyword	bold
=Bad		bold red

:pre_idle Idle
	*		NULL		noeat call=.coffee()

.subr coffee

:idle Idle
	*		idle
	"("		idle		call=.coffee(paren)
	"["		idle		call=.coffee(brack)
	"{"		idle		call=.coffee(squiggly)
.ifdef paren
	")"		idle		return
.else
	")"		stray		recolor=-1
.endif
.ifdef brack
	"]"		idle		return
.else
	"]"		stray		recolor=-1
.endif
.ifdef squiggly
	"}"		idle		return
.else
	"}"		stray		recolor=-1
.endif
	"#"		comment		recolor=-1
	"0"		zero		recolor=-1
	"1-9"		decimal		recolor=-1
	"."		decimal_point	recolor=-1
	"\""		maybe_string	recolor=-1
	"'"		maybe_char	recolor=-1
	"/"		slash		recolor=-1
	"@$\i"		ident		buffer

:stray Bad
	*		idle

:after_term Idle
	*		idle		noeat
	" \t"		after_term_1
	"/"		slash_after_term_0

# "foo/x" is division?
# "foo/ x" is division.

:slash_after_term_0 Idle
	*		idle		noeat

:after_term_1 Idle
	*		idle		noeat
	" \t"		after_term_1
	"/"		slash_after_term_1

# "foo / x"  is division
# "foo /x"   is regex

:slash_after_term_1 Idle
	*		sregex		noeat
	"/"		slashslash
	" =	"	idle		noeat

:comment Comment
	*		line_comment	noeat
	"#"		maybe_block_comment

:maybe_block_comment Comment
	*		line_comment	noeat
	"#"		maybe_block_comment_1

# This is weird... #### is a line comment, but ### is a block comment

:maybe_block_comment_1 Comment
	*		block_comment	noeat
	"#"		line_comment

:line_comment Comment
	*		line_comment
	"\n"		idle

:block_comment Comment
	*		block_comment
	"#"		block_comment_1

:block_comment_1 Comment
	*		block_comment	noeat
	"#"		block_comment_2

:block_comment_2 Comment
	*		block_comment	noeat
	"#"		idle

# Check for regex

:slash Constant
	*		sregex		noeat
	"/"		slashslash

:slashslash Constant
	*		after_term		noeat
	"/"		regex

# Regex like this ///foo///

:regex Constant
	*		regex
	"\\"		regex_escape	recolor=-1
	"#"		regex_maybe_subst
	"/"		regexslash

:regex_maybe_subst Constant
	*		regex	noeat
	"{"		regex		recolor=-2 call=.coffee(squiggly)

:regexslash Constant
	*		regex		noeat
	"/"		regexslashslash

:regexslashslash Constant
	*		regex		noeat
	"/"		after_term

:regex_escape Escape
	*		regex
	"x"		regex_hex2
	"u"		regex_hex4

:regex_uni Escape
	*		regex_uni
	"}"		regex

:regex_hex4 Escape
	*		regex		noeat
	"{"		regex_uni
	"0-9a-fA-F"	regex_hex3

:regex_hex3 Escape
	*		regex		noeat
	"0-9a-fA-F"	regex_hex2

:regex_hex2 Escape
	*		regex		noeat
	"0-9a-fA-F"	regex_hex1

:regex_hex1 Escape
	*		regex		noeat
	"0-9a-fA-F"	regex

# Regex like this: /foo/

:sregex Constant
	*		sregex
	"\\"		sregex_escape	recolor=-1
	"#"		sregex_maybe_subst
	"/"		after_term

:sregex_maybe_subst Constant
	*		sregex	noeat
	"{"		sregex	call=.coffee(squiggly) recolor=-2

:sregex_escape Escape
	*		sregex
	"x"		sregex_hex2
	"u"		sregex_hex4

:sregex_uni Escape
	*		sregex_uni
	"}"		sregex

:sregex_hex4 Escape
	*		sregex		noeat
	"{"		sregex_uni
	"0-9a-fA-F"	sregex_hex3

:sregex_hex3 Escape
	*		sregex		noeat
	"0-9a-fA-F"	sregex_hex2

:sregex_hex2 Escape
	*		sregex		noeat
	"0-9a-fA-F"	sregex_hex1

:sregex_hex1 Escape
	*		sregex		noeat
	"0-9a-fA-F"	sregex

# Numbers

:bad_number Bad
	*		after_term	noeat
	"0-9"		bad_number

:zero Constant
	*		after_term	noeat
	"b"		binary
	"o"		octal
	"x"		hex
	"."		maybe_float
	"eE"		epart
	"0-9"		decimal	recolor=-1

:decimal_point Constant
	*		after_term	noeat	recolor=-2
	"."		decimal_point_1	recolor=-2
	"\i"		not_ident	recolor=-2
	"0-9"		float

:not_ident Idle
	*		after_term	noeat
	"\c"		not_ident

:decimal_point_1 Idle
	*		idle		noeat
	"."		idle

:octal Constant
	*		after_term	noeat
	"0-7_"		octal
	"89"		bad_number	recolor=-1

:binary Constant
	*		after_term	noeat
	"01_"		binary
	"2-9"		bad_number	recolor=-1

:hex Constant
	*		after_term	noeat
	"0-9A-Fa-f_"	hex

:decimal Constant
	*		after_term	noeat
	"0-9_"		decimal
	"eE"		epart
	"."		maybe_float

:maybe_float Constant
	*		after_term	noeat recolor=-2
	"."		decimal_point_1	recolor=-2
	"eE"		epart
	"0-9_"		float

:float Constant
	*		after_term	noeat
	"eE"		epart
	"0-9_"		float

:epart Constant
	*		after_term	noeat
	"0-9+\-"	enum

:enum Constant
	*		after_term	noeat
	"0-9_"		enum

# strings like "hello"

:maybe_string Constant
	*		string		noeat
	"\""		maybe_string_1

:maybe_string_1 Constant
	*		after_term	noeat
	"\""		stringstring

:string	Constant
	*		string
	"\""		after_term
	"#"		string_maybe_subst
	"\\"		string_escape	recolor=-1

:string_maybe_subst Constant
	*		string	noeat
	"{"		string	call=.coffee(squiggly)	recolor=-2

:string_escape Escape
	*		string
	"x"		string_hex2
	"u"		string_hex4

:string_uni Escape
	*		string_uni
	"}"		string

:string_hex4 Escape
	*		string		noeat
	"{"		string_uni
	"0-9a-fA-F"	string_hex3

:string_hex3 Escape
	*		string		noeat
	"0-9a-fA-F"	string_hex2

:string_hex2 Escape
	*		string		noeat
	"0-9a-fA-F"	string_hex1

:string_hex1 Escape
	*		string		noeat
	"0-9a-fA-F"	string

# Strings like """ foo """

:stringstring	Constant
	*		stringstring
	"\""		stringstring_1
	"#"		stringstring_maybe_subst
	"\\"		stringstring_escape	recolor=-1

:stringstring_1	Constant
	*		stringstring	noeat
	"\""		stringstring_2

:stringstring_2 Constant
	*		stringstring	noeat
	"\""		after_term

:stringstring_maybe_subst Constant
	*		stringstring	noeat
	"{"		stringstring	call=.coffee(squiggly)	recolor=-2

:stringstring_escape Escape
	*		stringstring
	"x"		stringstring_hex2
	"u"		stringstring_hex4

:stringstring_uni Escape
	*		stringstring_uni
	"}"		stringstring

:stringstring_hex4 Escape
	*		stringstring		noeat
	"{"		stringstring_uni
	"0-9a-fA-F"	stringstring_hex3

:stringstring_hex3 Escape
	*		stringstring		noeat
	"0-9a-fA-F"	stringstring_hex2

:stringstring_hex2 Escape
	*		stringstring		noeat
	"0-9a-fA-F"	stringstring_hex1

:stringstring_hex1 Escape
	*		stringstring		noeat
	"0-9a-fA-F"	stringstring

# character constants like 'h'

:maybe_char	Constant
	*		char	noeat
	"'"	maybe_char_1

:maybe_char_1	Constant
	*	after_term	noeat
	"'"	charchar

:char	Constant
	*		char
	"'"		after_term
	"\\"		char_escape	recolor=-1

:char_escape Escape
	*		char		noeat
	"x"		char_hex2
	"u"		char_hex4

:char_uni Escape
	*		char_uni
	"}"		char_done

:char_hex4 Escape
	*		char		noeat
	"{"		char_uni
	"0-9a-fA-F"	char_hex3

:char_hex3 Escape
	*		char		noeat
	"0-9a-fA-F"	char_hex2

:char_hex2 Escape
	*		char		noeat
	"0-9a-fA-F"	char_hex1

:char_hex1 Escape
	*		char		noeat
	"0-9a-fA-F"	char

# strings like this '''foo'''

:charchar Constant
	*		charchar
	"'"		charchar_1
	"\\"		charchar_escape	recolor=-1

:charchar_1 Constant
	*		charchar		noeat
	"'"		charchar_2

:charchar_2 Constant
	*		charchar		noeat
	"'"		after_term

:charchar_escape Escape
	*		charchar		noeat
	"x"		charchar_hex2
	"u"		charchar_hex4

:charchar_uni Escape
	*		charchar_uni
	"}"		charchar_done

:charchar_hex4 Escape
	*		charchar		noeat
	"{"		charchar_uni
	"0-9a-fA-F"	charchar_hex3

:charchar_hex3 Escape
	*		charchar		noeat
	"0-9a-fA-F"	charchar_hex2

:charchar_hex2 Escape
	*		charchar		noeat
	"0-9a-fA-F"	charchar_hex1

:charchar_hex1 Escape
	*		charchar		noeat
	"0-9a-fA-F"	charchar


# Identifiers

:ident Idle
	*		after_term	noeat strings
	"and"		operator
	"break"		kw
	"by"		kw
	"catch"		kw
	"class"		kw
	"continue"	kw
	"delete"	kw
	"debugger"	kw
	"do"		kw
	"else"		kw
	"extends"	kw
	"false"		lit
	"finally"	kw
	"for"		kw
	"if"		kw
	"in"		kw
	"instanceof"	kw
	"is"		kw
	"isnt"		kw
	"loop"		kw
	"new"		kw
	"no"		lit
	"not"		operator
	"null"		lit
	"off"		lit
	"of"		kw
	"on"		lit
	"or"		operator
	"return"	kw
	"super"		kw
	"switch"	kw
	"then"		kw
	"this"		lit
	"throw"		kw
	"true"		lit
	"try"		kw
	"typeof"	kw
	"undefined"	lit
	"unless"	kw
	"until"		kw
	"when"		kw
	"while"		kw
	"yes"		lit
	"yield"		kw
	"case"		forbid
	"default"	forbid
	"function"	forbid
	"var"		forbid
	"void"		forbid
	"with"		forbid
	"const"		forbid
	"let"		forbid
	"enum"		forbid
	"export"	forbid
	"import"	forbid
	"native"	forbid
	"implements"	forbid
	"interface"	forbid
	"package"	forbid
	"private"	forbid
	"protected"	forbid
	"public"	forbid
	"static"	forbid
	"arguments"	forbid
	"eval"		forbid
done
	"$\c"	ident

:kw Keyword
	*		idle			noeat

:forbid Keyword
	*		idle			noeat

:lit Constant
	*		after_term		noeat

:operator Operator
	*		idle			noeat

.end
