module.exports = grammar({
name: "gomod",
extras: ($) => [$.comment, /\s/],
rules: {
source_file: ($) => repeat($._directive),
_directive: ($) =>
choice(
$.module_directive,
$.go_directive,
$.toolchain_directive,
$.require_directive,
$.exclude_directive,
$.replace_directive,
$.retract_directive
),
_string_literal: ($) =>
choice($.raw_string_literal, $.interpreted_string_literal),
raw_string_literal: ($) => token(seq("`", repeat(/[^`]/), "`")),
interpreted_string_literal: ($) =>
seq(
'"',
repeat(
choice(token.immediate(prec(1, /[^"\n\\]+/)), $.escape_sequence)
),
'"'
),
escape_sequence: ($) =>
token.immediate(
seq(
"\\",
choice(
/[^xuU]/,
/\d{2,3}/,
/x[0-9a-fA-F]{2,}/,
/u[0-9a-fA-F]{4}/,
/U[0-9a-fA-F]{8}/
)
)
),
_identifier: ($) => token(/[^\s,\[\]]+/),
_string_or_ident: ($) => choice($._string_literal, $._identifier),
module_path: ($) => $._string_or_ident,
go_version: ($) => $._string_or_ident,
version: ($) => $._string_or_ident,
module_directive: ($) =>
seq(
"module",
choice($.module_path, seq("(", "\n", $.module_path, "\n", ")"))
),
go_directive: ($) => seq("go", $.go_version, "\n"),
toolchain_directive: ($) =>
seq(
"toolchain",
field('name', $.toolchain_name),
),
toolchain_name: ($) => $._string_or_ident,
require_directive: ($) =>
seq(
"require",
choice(
$.require_spec,
seq("(", "\n", repeat($.require_spec), ")", "\n")
)
),
require_spec: ($) => seq($.module_path, $.version, "\n"),
exclude_directive: ($) =>
seq(
"exclude",
choice(
$.exclude_spec,
seq("(", "\n", repeat($.exclude_spec), ")", "\n")
)
),
exclude_spec: ($) => seq($.module_path, $.version, "\n"),
replace_directive: ($) =>
seq(
"replace",
choice(
$.replace_spec,
seq("(", "\n", repeat($.replace_spec), ")", "\n")
)
),
replace_spec: ($) =>
choice(
seq($.module_path, optional($.version), "=>", $.file_path, "\n"),
seq(
$.module_path,
optional($.version),
"=>",
$.module_path,
$.version,
"\n"
)
),
file_path: ($) => $._identifier,
retract_directive: ($) =>
seq(
"retract",
choice(
seq("(", "\n", repeat($.retract_spec), ")", "\n"),
$.retract_spec
)
),
retract_spec: ($) =>
seq(
choice(seq("[", $.version, prec(1, ","), $.version, "]"), $.version),
"\n"
),
comment: ($) => seq("//", /.*/),
},
});