File: //usr/share/joe/syntax/json.jsf
# JSON highlighter per json.org
# Written by Rebecca Turner (@ReBecaOrg)
# Define colors
=Idle
=Comma
=PairSep
=Bracket	+Brace
=Brace		+Control +Operator
=Constant
=Number		+Constant
=Boolean	+Constant
=Null		+Constant
=String		+Constant
=Key		+Attr +Type +String
=Escape
=StringEscape	+Escape +String
=Bad
=ERROR		+Bad
:json Idle
	*			end		noeat call=.value()
	" \t\n"			json
:end Idle
	*			endBAD		noeat
	" \t\n"			end
:endBAD Bad
	*			end
.subr value
:value Idle
	*			valueBAD	noeat
	"\""			end		noeat call=.string()
	"-0-9"			end		noeat call=.number()
	"tfn"			end		noeat call=.bareword()
	"{"			end		noeat call=.object()
	"["			end		noeat call=.array()
:valueBAD Bad
	*			value
:end Idle
	*			NULL		noeat return
.end
.subr object
:object Brace
	*			objectBAD	noeat
	"{"			maybeempty
:objectBAD ERROR
	*			end
:maybeempty Brace
	*			key		noeat
	" \t\n"			maybeempty
	"}"			end		recolor=-1
:key Idle
	*			keyBAD		noeat
	"\""			pairsep		noeat call=.keystring()
	" \t\n"			key
:keyBAD Bad
	*			key
:pairsep PairSep
	*			pairsepBAD	noeat
	":"			value
	" \t\n"			pairsep
:pairsepBAD Bad
	*			pairsep
:value Idle
	*			nextpair	noeat call=.value()
	" \t\n"			value
:nextpair Comma
	*			nextpairBAD	noeat
	"}"			end		recolor=-1
	","			key
	" \t\n"			nextpair
:nextpairBAD Bad
	*			nextpair
:end Brace
	*			NULL		noeat return
.end
.subr array
:array Bracket
	*			arrayBAD	noeat
	"["			maybeempty
:arrayBAD ERROR
	*			end
:maybeempty Bracket
	*			value		noeat
	" \t\n"			maybeempty
	"]"			end		recolor=-1
:value Idle
	*			nextvalue	noeat call=.value()
	" \t\n"			value
:nextvalue Comma
	*			nextvalueBAD	noeat
	"]"			end		recolor=-1
	","			value
	" \t\n"			nextvalue
:nextvalueBAD Bad
	*			nextvalue
:end Bracket
	*			NULL		noeat return
.end
.subr string
:string String string
	*			stringBAD	noeat
	"\""			body
:body String string
	*			body
	"\""			end
	"\\"			escape		recolor=-1
:stringBAD ERROR
	*			end
:escape StringEscape string
	*			escapeBAD	recolor=-2 noeat
	"\"/bfnrt\\"		body
	"u"			unicode1
:escapeBAD Bad
	*			body
:unicode1 StringEscape string
	*			unicodeBAD	recolor=-3 noeat
	"0-9a-fA-F"		unicode2
:unicode2 StringEscape string
	*			unicodeBAD	recolor=-4 noeat
	"0-9a-fA-F"		unicode3
:unicode3 StringEscape string
	*			unicodeBAD	recolor=-5 noeat
	"0-9a-fA-F"		unicode4
:unicode4 StringEscape string
	*			unicodeBAD	recolor=-6 noeat
	"0-9a-fA-F"		body
:unicodeBAD Bad
	*			body
:end Idle
	*			NULL		noeat return
.end
.subr keystring
:string Key
	*			stringBAD	noeat
	"\""			body
:body Key
	*			body
	"\""			end
	"\\"			escape		recolor=-1
:stringBAD ERROR
	*			end
:escape Escape
	*			escapeBAD	recolor=-2 noeat
	"\"/bfnrt\\"		body
	"u"			unicode1
:escapeBAD Bad
	*			body
:unicode1 Escape
	*			unicodeBAD	recolor=-3 noeat
	"0-9a-fA-F"		unicode2
:unicode2 Escape
	*			unicodeBAD	recolor=-4 noeat
	"0-9a-fA-F"		unicode3
:unicode3 Escape
	*			unicodeBAD	recolor=-5 noeat
	"0-9a-fA-F"		unicode4
:unicode4 Escape
	*			unicodeBAD	recolor=-6 noeat
	"0-9a-fA-F"		body
:unicodeBAD Bad
	*			body
:end Idle
	*			NULL		noeat return
.end
.subr bareword
:bareword Idle
	*			body		noeat mark buffer
:body Bad
	*			end		noeat markend strings
	"true"			boolean
	"false"			boolean
	"null"			null
	
done
	"truefalsn"		body
:boolean Boolean
	*			end		noeat
:null Null
	*			end		noeat
:end Idle
	*			NULL		noeat return
.end
.subr number
:number Number
	*			numberBAD
	"0-9"			numberA		noeat
	"-"			numberA
:numberBAD ERROR
	*			end
:numberA Number
	"0"			decimalpoint
	"1-9"			integer
:integer Number
	*			end		noeat
	"0-9"			integer
	"."			decimalpart
	"eE"			exponentpart
:decimalpoint Number
	*			end		noeat
	"0-9"			decimalpointBAD
	"eE"			exponentpart
	"."			decimalpart
:decimalpointBAD Bad
	*			end
:decimalpart Number
	*			decimalpartBAD
	"0-9"			decimalpartA
:decimalpartBAD Bad
	*			end
:decimalpartA Number
	*			end		noeat
	"0-9"			decimalpartA
	"eE"			exponentpart
:exponentpart Number
	*			exponentpartBAD
	"-+"			exponentpartA
	"0-9"			exponentpartB
:exponentpartBAD Bad
	*			end
:exponentpartA Number
	*			exponentpartBAD
	"0-9"			exponentpartB
:exponentpartB Number
	*			end		noeat
	"0-9"			exponentpartB
:end Idle
	*			NULL		noeat return
.end