--- YAML syntax rules for Lx
-- Pattern set for block and flow YAML constructs
-- @module syntax.yaml

-- lx syntax
local syntax = require("core.syntax")

local yaml_flow = {
	match = {
		strategy = "priority_first",
	},
	patterns = {
		-- Priority ladder: 80 structural, 70 semantic atoms, 60 numbers, 50 punctuation, 10 fallback

		-- '#' starts comments only at line-start (indent allowed) or after whitespace
		{ pattern = { "#", "\n" }, type = "comment", line_start = true, line_prefix = "%s*", priority = 80 },
		{ pattern = { "#", "\n" }, type = "comment", preceded_by = "%s", priority = 80 },

		-- Quoted scalars with escape handling
		{ pattern = '"[^\n]*', type = "string", not_preceded_by = "[%w_]", priority = 80 },
		{ pattern = "'[^\n]*", type = "string", not_preceded_by = "[%w_]", priority = 80 },

		-- YAML tags for typed scalars and application tags
		{ pattern = "!![%w_:%-%.]+", type = "keyword", priority = 70 },
		{ pattern = "!<[^>\n]+>", type = "keyword", priority = 70 },
		{ pattern = "!%w[%w_:%-%.]*", type = "keyword", priority = 70 },

		-- Anchors and aliases in flow collections
		{ pattern = "&[%w_%-%.]+", type = "keyword2", priority = 70 },
		{ pattern = "%*[%w_%-%.]+", type = "keyword2", priority = 70 },

		{ pattern = "<<", type = "literal", priority = 70 },

		-- Numeric forms recognized by YAML
		{ pattern = "[%+%-]?%.inf%f[^%w_]", type = "number", priority = 60 },
		{ pattern = "%.NaN%f[^%w_]", type = "number", priority = 60 },
		{ pattern = "[%+%-]?0x[%da-fA-F_]+", type = "number", priority = 60 },
		{ pattern = "[%+%-]?0o[0-7_]+", type = "number", priority = 60 },
		{ pattern = "[%+%-]?0b[01_]+", type = "number", priority = 60 },
		{ pattern = "[%+%-]?%d[%d_]*%.%d[%d_]*([eE][%+%-]?%d[%d_]*)?", type = "number", priority = 60 },
		{ pattern = "[%+%-]?%d[%d_]*", type = "number", priority = 60 },

		{ pattern = "[%[%]{}]", type = "operator", not_preceded_by = "\\", priority = 50 },
		{ pattern = "[(),:]", type = "operator", priority = 50 },

		-- Plain scalars stop before delimiters used by flow collections
		{ pattern = "[^%s%[%]{}(),:#]+", type = "string", priority = 10 },
	},
	symbols = {
		["true"] = "literal",
		["false"] = "literal",
		["null"] = "literal",
		["Null"] = "literal",
		["NULL"] = "literal",
		["~"] = "literal",
		["yes"] = "literal",
		["no"] = "literal",
		["on"] = "literal",
		["off"] = "literal",
	},
}

syntax.add({
	name = "YAML",
	shortname = "YAML",
	extensions = {
		"yaml",
		"yml",
		"sublime-syntax",
	},
	comment = "#",
	headers = "%%YAML",

	match = {
		strategy = "priority_first",
	},
	line_patterns = {
		-- Document markers and directives consume the full line
		{ pattern = "%-%-%-%s*$", type = "meta", consume_line = true, priority = 100 },
		{ pattern = "%-%-%-%s*#.*", type = "meta", consume_line = true, priority = 100 },
		{ pattern = "%.%.%.%s*$", type = "meta", consume_line = true, priority = 100 },
		{ pattern = "%.%.%.%s*#.*", type = "meta", consume_line = true, priority = 100 },
		{ pattern = "%%%w+.*", type = "meta", consume_line = true, priority = 100 },

		-- Full-line comments can bypass regular pattern scan
		{ pattern = "%s*#.*", type = "comment", consume_line = true, priority = 90 },
	},
	patterns = {
		-- Priority ladder:
		-- 100 directives
		-- 90 comments
		-- 80 subsyntax delimiters
		-- 70 sequence mapping
		-- 60 nested mapping
		-- 50 top-level mapping
		-- 40 semantic atoms
		-- 30 numbers
		-- 20 operators
		-- 10 fallback

		{ pattern = { "#", "\n" }, type = "comment", line_start = true, line_prefix = "%s*", priority = 90 },
		{ pattern = { "#", "\n" }, type = "comment", preceded_by = "%s", priority = 90 },

		-- Quoted scalars must win before flow delimiters so '{' and '[' inside quotes stay literal
		{ pattern = '"[^\n]*', type = "string", not_preceded_by = "[%w_]", priority = 45 },
		{ pattern = "'[^\n]*", type = "string", not_preceded_by = "[%w_]", priority = 45 },
		{ pattern = "\\[%[%]{}(),:;|]", type = "string", priority = 85 },

		-- Flow collections are tokenized with inline subsyntax table
		{ pattern = { "%[", "%]" }, syntax = yaml_flow, type = "operator", not_preceded_by = "\\", priority = 80 },
		{ pattern = { "{", "}" }, syntax = yaml_flow, type = "operator", not_preceded_by = "\\", priority = 80 },

		-- List marker is '-' at first non-space followed by list spacing
		{ pattern = "%-", type = "operator", line_prefix = "%s*", followed_by = "%s+", priority = 70 },

		-- Sequence mapping key after '- ' when key is unquoted
		{
			pattern = "[%w_][%w_%-%./]*",
			type = "keyword2",
			line_prefix = "%s*%-%s+",
			followed_by = "%s*:",
			priority = 70,
		},
		-- Sequence mapping key after '- ' when key is quoted
		{ pattern = '%b""', type = "keyword2", line_prefix = "%s*%-%s+", followed_by = "%s*:", priority = 70 },
		{ pattern = "%b''", type = "keyword2", line_prefix = "%s*%-%s+", followed_by = "%s*:", priority = 70 },

		-- Nested mapping key uses indentation and trailing ':'
			{
				pattern = "[%w_][%w_%-%./]*",
				type = "keyword2",
				line_prefix = "%s+",
				followed_by = "%s*:",
				priority = 60,
			},
		{ pattern = '%b""', type = "keyword2", line_prefix = "%s+", followed_by = "%s*:", priority = 60 },
		{ pattern = "%b''", type = "keyword2", line_prefix = "%s+", followed_by = "%s*:", priority = 60 },

		-- Top-level mapping key starts without indentation and ends at ':'
			{
				pattern = "[%w_][%w_%-%./]*",
				type = "function",
				line_prefix = "%s*",
				followed_by = "%s*:",
				priority = 50,
			},
		{ pattern = '%b""', type = "literal", line_prefix = "%s*", followed_by = "%s*:", priority = 50 },
		{ pattern = "%b''", type = "literal", line_prefix = "%s*", followed_by = "%s*:", priority = 50 },

		{ pattern = "<<", type = "literal", priority = 40 },

		{ pattern = "&[%w_%-%.]+", type = "keyword2", priority = 40 },
		{ pattern = "%*[%w_%-%.]+", type = "keyword2", priority = 40 },

		{ pattern = "!![%w_:%-%.]+", type = "keyword", priority = 40 },
		{ pattern = "!<[^>\n]+>", type = "keyword", priority = 40 },
		{ pattern = "!%w[%w_:%-%.]*", type = "keyword", priority = 40 },

		-- Block scalar indicator after mapping separator
		{ pattern = "[|>][%+%-]?%d*", type = "meta", preceded_by = ":%s*", priority = 40 },

		{ pattern = "%$%a[%w_]*", type = "keyword", priority = 40 },
		{ pattern = "%$%{%{.-%}%}", type = "keyword", priority = 40 },

		{ pattern = "[%+%-]?%.inf%f[^%w_]", type = "number", priority = 30 },
		{ pattern = "%.NaN%f[^%w_]", type = "number", priority = 30 },
		{ pattern = "[%+%-]?0x[%da-fA-F_]+", type = "number", priority = 30 },
		{ pattern = "[%+%-]?0o[0-7_]+", type = "number", priority = 30 },
		{ pattern = "[%+%-]?0b[01_]+", type = "number", priority = 30 },
		{ pattern = "[%+%-]?%d[%d_]*%.%d[%d_]*([eE][%+%-]?%d[%d_]*)?", type = "number", priority = 30 },
		{ pattern = "[%+%-]?%d[%d_]*", type = "number", priority = 30 },

		{ pattern = ":", type = "operator", priority = 20 },
		{ pattern = "[%[%]{}]", type = "operator", not_preceded_by = "\\", priority = 20 },
		{ pattern = "[,:]", type = "operator", priority = 20 },

		-- Plain scalar fallback excludes structure delimiters and comment start
		{ pattern = "[^%s#:%[%]{},]+", type = "string", priority = 10 },
	},
	outline_patterns = {
		{ pattern = "%-%-%-", type = "meta", line_start = true },
		{ pattern = "%.%.%.", type = "meta", line_start = true },
		{ pattern = "%s*[%w_][%w_%-%./]*%s*:", type = "literal", line_start = true },
--		{ pattern = "%s*%-%s+[%w_][%w_%-%./]*%s*:", type = "keyword2", line_start = true },
	},
	symbols = {
		["true"] = "literal",
		["false"] = "literal",
		["null"] = "literal",
		["Null"] = "literal",
		["NULL"] = "literal",
		["~"] = "literal",
		["yes"] = "literal",
		["no"] = "literal",
		["on"] = "literal",
		["off"] = "literal",
	},
})
