# Flex-flavoured regular expressions
scopeName: "source.lex.regexp"
patterns: [include: "#main"]

repository:
	main:
		patterns: [
			{include: "#wildcard"}
			{include: "#alternation"}
			{include: "#lookahead"}
			{include: "#anchors"}
			{include: "#start-condition"}
			{include: "#quantifier"}
			{include: "#string"}
			{include: "#expansion"}
			{include: "#quantifier-range"}
			{include: "#class"}
			{include: "#subpattern"}
			{include: "#escapes"}
		]

	# Alternation
	alternation:
		name:  "keyword.operator.logical.or.lex"
		match: "\\|"

	# Zero-width assertions
	anchors:
		patterns: [{
			# Start of line
			name:  "keyword.control.anchor.line-start.lex"
			match: "\\^"
		},{
			# End of line
			name:  "keyword.control.anchor.line-end.lex"
			match: "\\$"
		},{
			# End of file
			name:  "keyword.control.anchor.eof.lex"
			match: "(<<)EOF(>>)"
			captures:
				1: name: "punctuation.definition.angle.bracket.begin.lex"
				2: name: "punctuation.definition.angle.bracket.end.lex"
		}]

	# Character class: [^xyz]
	class:
		name:  "meta.character-class.set.lex"
		begin: "(\\[)(\\^)?(-)?"
		end:   "\\]"
		beginCaptures:
			1: name: "punctuation.definition.character-class.set.begin.lex"
			2: name: "keyword.operator.logical.not.lex"
			3: name: "constant.single.character.character-class.lex"
		endCaptures:
			0: name: "punctuation.definition.character-class.set.end.lex"
		patterns: [
			{include: "#escapes"}
			{include: "#expressions"}
			{match: "-(?!\\])", name: "punctuation.separator.range.dash.lex"}
			{match: ".",        name: "constant.single.character.character-class.lex"}]


	# Escape sequences used in regular expressions
	escapes:
		patterns: [{
			name: "constant.character.escape.codepoint.octal.lex"
			match: "\\\\[0-7]{3}"
		},{
			name: "constant.character.escape.codepoint.hexadecimal.hex.lex"
			match: "\\\\[xX][A-Fa-f0-9]{2}"
		},{
			name: "constant.character.escape.lex"
			match: "\\\\."
		}]


	# Definition expansion
	expansion:
		name:  "meta.expansion.lex"
		match: "(\\{)([^{}\\s]+)(\\})"
		captures:
			1: name: "punctuation.definition.expansion.bracket.curly.begin.lex"
			2: name: "variable.parameter.reference.lex"
			3: name: "punctuation.definition.expansion.bracket.curly.end.lex"


	# Character class "expression" (POSIX character class)
	expressions:
		name: "constant.language.posix.$2-char.character-class.lex"
		match: """(?x)
			(\\[:)
			(alnum|alpha|blank|cntrl|digit|graph
			|lower|print|punct|space|upper|xdigit)
			(:\\])
		"""
		captures:
			1: name: "punctuation.definition.character-class.set.begin.lex"
			2: name: "support.constant.posix-class.lex"
			3: name: "punctuation.definition.character-class.set.end.lex"


	# Lookahead, or something like it
	lookahead:
		name:  "keyword.operator.logical.and.lookahead.lex"
		match: "/"

	# Quantifier
	quantifier:
		name: "keyword.operator.quantifier.lex"
		match: "[*+?]"

	# Quantifier (specific range: {2,4}, {2,}, {,4}…)
	"quantifier-range":
		name: "keyword.operator.quantifier.specific.lex"
		match: "({)(?:([0-9]+)(?:(,)([0-9]*))?|(,)([0-9]+))(})"
		captures:
			1: name: "punctuation.definition.quantifier.bracket.curly.begin.lex"
			2: name: "keyword.operator.quantifier.min.lex"
			3: name: "punctuation.delimiter.comma.lex"
			4: name: "keyword.operator.quantifier.max.lex"
			5: name: "punctuation.delimiter.comma.lex"
			6: name: "keyword.operator.quantifier.max.lex"
			7: name: "punctuation.definition.quantifier.bracket.curly.end.lex"

	# Start condition
	"start-condition":
		name:  "meta.start-condition.lex"
		begin: "<"
		end:   ">|(?=$)"
		beginCaptures: 0: name: "punctuation.definition.angle.bracket.begin.lex"
		endCaptures:   0: name: "punctuation.definition.angle.bracket.end.lex"
		patterns: [{
			name:  "keyword.operator.wildcard.condition.lex"
			match: "\\*"
		},{
			name:  "punctuation.delimiter.separator.comma.lex"
			match: ","
		},{
			name: "constant.language.condition.name.lex"
			match: "[^<>*,\\s]+"
		}]

	# "Double-quoted" string literal
	string:
		name:  "string.quoted.double.lex"
		begin: '"'
		end:   '"'
		beginCaptures: 0: name: "punctuation.definition.string.begin.lex"
		endCaptures:   0: name: "punctuation.definition.string.end.lex"
		patterns: [include: "#escapes"]

	# Subpattern: (xyz)
	subpattern:
		name:  "meta.group.regexp"
		begin: "\\("
		end:   "\\)"
		beginCaptures: 0: name: "punctuation.definition.group.begin.lex"
		endCaptures:   0: name: "punctuation.definition.group.end.lex"
		patterns: [include: "#main"]

	# Wildcard: .
	wildcard:
		name:  "constant.character.wildcard.dot.match.any.lex"
		match: "\\."
