2021-05-09 22:11:30 -04:00
|
|
|
module.exports = grammar({
|
2021-05-11 22:00:07 -04:00
|
|
|
name: "dockerfile",
|
|
|
|
|
2021-06-20 13:55:27 -04:00
|
|
|
extras: ($) => [/\s+/, $.line_continuation],
|
2024-04-19 16:08:28 -04:00
|
|
|
externals: ($) => [
|
|
|
|
$.heredoc_marker,
|
|
|
|
$.heredoc_line,
|
|
|
|
$.heredoc_end,
|
|
|
|
$.heredoc_nl,
|
|
|
|
$.error_sentinel,
|
|
|
|
],
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
rules: {
|
2021-06-20 13:35:37 -04:00
|
|
|
source_file: ($) => repeat(seq(choice($._instruction, $.comment), "\n")),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
_instruction: ($) =>
|
|
|
|
choice(
|
|
|
|
$.from_instruction,
|
|
|
|
$.run_instruction,
|
|
|
|
$.cmd_instruction,
|
|
|
|
$.label_instruction,
|
|
|
|
$.expose_instruction,
|
|
|
|
$.env_instruction,
|
|
|
|
$.add_instruction,
|
|
|
|
$.copy_instruction,
|
|
|
|
$.entrypoint_instruction,
|
|
|
|
$.volume_instruction,
|
|
|
|
$.user_instruction,
|
|
|
|
$.workdir_instruction,
|
|
|
|
$.arg_instruction,
|
|
|
|
$.onbuild_instruction,
|
|
|
|
$.stopsignal_instruction,
|
|
|
|
$.healthcheck_instruction,
|
|
|
|
$.shell_instruction,
|
|
|
|
$.maintainer_instruction,
|
2024-04-19 16:08:28 -04:00
|
|
|
$.cross_build_instruction,
|
2021-05-11 22:00:07 -04:00
|
|
|
),
|
|
|
|
|
|
|
|
from_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[fF][rR][oO][mM]/, "FROM"),
|
|
|
|
optional($.param),
|
|
|
|
$.image_spec,
|
|
|
|
optional(seq(alias(/[aA][sS]/, "AS"), field("as", $.image_alias)))
|
|
|
|
),
|
|
|
|
|
|
|
|
run_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[rR][uU][nN]/, "RUN"),
|
2022-10-25 22:48:10 -04:00
|
|
|
repeat(
|
|
|
|
choice(
|
|
|
|
$.param,
|
|
|
|
$.mount_param
|
|
|
|
)
|
|
|
|
),
|
2024-04-19 16:08:28 -04:00
|
|
|
choice($.json_string_array, $.shell_command),
|
|
|
|
repeat($.heredoc_block)
|
2021-05-11 22:00:07 -04:00
|
|
|
),
|
|
|
|
|
|
|
|
cmd_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[cC][mM][dD]/, "CMD"),
|
2023-06-22 22:44:07 -04:00
|
|
|
choice($.json_string_array, $.shell_command)
|
2021-05-11 22:00:07 -04:00
|
|
|
),
|
|
|
|
|
|
|
|
label_instruction: ($) =>
|
2021-06-20 14:46:57 -04:00
|
|
|
seq(alias(/[lL][aA][bB][eE][lL]/, "LABEL"), repeat1($.label_pair)),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
expose_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[eE][xX][pP][oO][sS][eE]/, "EXPOSE"),
|
|
|
|
repeat1(choice($.expose_port, $.expansion))
|
|
|
|
),
|
|
|
|
|
|
|
|
env_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[eE][nN][vV]/, "ENV"),
|
|
|
|
choice(repeat1($.env_pair), alias($._spaced_env_pair, $.env_pair))
|
|
|
|
),
|
|
|
|
|
|
|
|
add_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[aA][dD][dD]/, "ADD"),
|
2023-10-09 19:38:49 -04:00
|
|
|
repeat($.param),
|
2022-01-26 17:41:32 -05:00
|
|
|
repeat1(
|
2024-04-19 16:08:28 -04:00
|
|
|
seq(alias($.path_with_heredoc, $.path), $._non_newline_whitespace)
|
2022-01-26 17:41:32 -05:00
|
|
|
),
|
2024-04-19 16:08:28 -04:00
|
|
|
alias($.path_with_heredoc, $.path),
|
|
|
|
repeat($.heredoc_block)
|
2021-05-11 22:00:07 -04:00
|
|
|
),
|
|
|
|
|
|
|
|
copy_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[cC][oO][pP][yY]/, "COPY"),
|
2023-10-09 19:38:49 -04:00
|
|
|
repeat($.param),
|
2022-01-26 17:41:32 -05:00
|
|
|
repeat1(
|
2024-04-19 16:08:28 -04:00
|
|
|
seq(alias($.path_with_heredoc, $.path), $._non_newline_whitespace)
|
2022-01-26 17:41:32 -05:00
|
|
|
),
|
2024-04-19 16:08:28 -04:00
|
|
|
alias($.path_with_heredoc, $.path),
|
|
|
|
repeat($.heredoc_block)
|
2021-05-11 22:00:07 -04:00
|
|
|
),
|
|
|
|
|
|
|
|
entrypoint_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[eE][nN][tT][rR][yY][pP][oO][iI][nN][tT]/, "ENTRYPOINT"),
|
2023-06-22 22:44:07 -04:00
|
|
|
choice($.json_string_array, $.shell_command)
|
2021-05-11 22:00:07 -04:00
|
|
|
),
|
|
|
|
|
|
|
|
volume_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[vV][oO][lL][uU][mM][eE]/, "VOLUME"),
|
|
|
|
choice(
|
2023-06-22 22:44:07 -04:00
|
|
|
$.json_string_array,
|
2021-05-11 22:00:07 -04:00
|
|
|
seq($.path, repeat(seq($._non_newline_whitespace, $.path)))
|
|
|
|
)
|
|
|
|
),
|
|
|
|
|
|
|
|
user_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[uU][sS][eE][rR]/, "USER"),
|
2021-06-20 14:34:05 -04:00
|
|
|
field("user", alias($._user_name_or_group, $.unquoted_string)),
|
2021-05-11 22:00:07 -04:00
|
|
|
optional(
|
|
|
|
seq(
|
|
|
|
token.immediate(":"),
|
2022-04-04 22:08:03 -04:00
|
|
|
field("group",
|
|
|
|
alias($._immediate_user_name_or_group, $.unquoted_string))
|
2021-05-11 22:00:07 -04:00
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
|
2021-06-20 14:34:05 -04:00
|
|
|
_user_name_or_group: ($) =>
|
2022-04-04 22:08:03 -04:00
|
|
|
seq(
|
2023-05-02 14:51:24 -04:00
|
|
|
choice(/([a-zA-Z][-A-Za-z0-9_]*|[0-9]+)/, $.expansion),
|
2022-04-04 22:08:03 -04:00
|
|
|
repeat($._immediate_user_name_or_group_fragment)
|
|
|
|
),
|
|
|
|
|
|
|
|
// same as _user_name_or_group but sticks to previous token
|
|
|
|
_immediate_user_name_or_group: ($) =>
|
|
|
|
repeat1($._immediate_user_name_or_group_fragment),
|
|
|
|
|
|
|
|
_immediate_user_name_or_group_fragment: ($) =>
|
|
|
|
choice(
|
2023-05-02 14:51:24 -04:00
|
|
|
token.immediate(/([a-zA-Z][-a-zA-Z0-9_]*|[0-9]+)/),
|
2022-04-04 22:08:03 -04:00
|
|
|
$._immediate_expansion
|
|
|
|
),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
workdir_instruction: ($) =>
|
2021-06-20 14:34:05 -04:00
|
|
|
seq(alias(/[wW][oO][rR][kK][dD][iI][rR]/, "WORKDIR"), $.path),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
arg_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[aA][rR][gG]/, "ARG"),
|
|
|
|
field("name", alias(/[a-zA-Z0-9_]+/, $.unquoted_string)),
|
|
|
|
optional(
|
|
|
|
seq(
|
|
|
|
token.immediate("="),
|
2023-06-22 22:44:07 -04:00
|
|
|
field("default",
|
|
|
|
choice(
|
|
|
|
$.double_quoted_string,
|
|
|
|
$.single_quoted_string,
|
|
|
|
$.unquoted_string
|
|
|
|
))
|
2021-05-11 22:00:07 -04:00
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
|
|
|
|
onbuild_instruction: ($) =>
|
2021-06-20 14:34:05 -04:00
|
|
|
seq(alias(/[oO][nN][bB][uU][iI][lL][dD]/, "ONBUILD"), $._instruction),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
stopsignal_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[sS][tT][oO][pP][sS][iI][gG][nN][aA][lL]/, "STOPSIGNAL"),
|
|
|
|
$._stopsignal_value
|
|
|
|
),
|
|
|
|
|
2022-04-04 22:08:03 -04:00
|
|
|
_stopsignal_value: ($) =>
|
|
|
|
seq(
|
|
|
|
choice(/[A-Z0-9]+/, $.expansion),
|
|
|
|
repeat(choice(token.immediate(/[A-Z0-9]+/), $._immediate_expansion))
|
|
|
|
),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
healthcheck_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[hH][eE][aA][lL][tT][hH][cC][hH][eE][cC][kK]/, "HEALTHCHECK"),
|
|
|
|
choice("NONE", seq(repeat($.param), $.cmd_instruction))
|
|
|
|
),
|
|
|
|
|
|
|
|
shell_instruction: ($) =>
|
2023-06-22 22:44:07 -04:00
|
|
|
seq(alias(/[sS][hH][eE][lL][lL]/, "SHELL"), $.json_string_array),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
maintainer_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(/[mM][aA][iI][nN][tT][aA][iI][nN][eE][rR]/, "MAINTAINER"),
|
|
|
|
/.*/
|
|
|
|
),
|
|
|
|
|
|
|
|
cross_build_instruction: ($) =>
|
|
|
|
seq(
|
|
|
|
alias(
|
|
|
|
/[cC][rR][oO][sS][sS]_[bB][uU][iI][lL][dD][a-zA-Z_]*/,
|
|
|
|
"CROSS_BUILD"
|
|
|
|
),
|
|
|
|
/.*/
|
|
|
|
),
|
|
|
|
|
2024-04-19 16:08:28 -04:00
|
|
|
heredoc_block: ($) =>
|
|
|
|
seq(
|
|
|
|
// A heredoc block starts with a line break after the instruction it
|
|
|
|
// belongs to. The herdoc_nl token is a special token that only matches
|
|
|
|
// \n if there's at least one open heredoc to avoid conflicts.
|
|
|
|
// We also alias this token to hide it from the output like all other
|
|
|
|
// whitespace.
|
|
|
|
alias($.heredoc_nl, "_heredoc_nl"),
|
|
|
|
repeat(seq($.heredoc_line, "\n")),
|
|
|
|
$.heredoc_end
|
|
|
|
),
|
|
|
|
|
2021-05-11 22:00:07 -04:00
|
|
|
path: ($) =>
|
|
|
|
seq(
|
|
|
|
choice(
|
2024-04-19 16:08:28 -04:00
|
|
|
/[^-\s\$<]/, // cannot start with a '-' to avoid conflicts with params
|
|
|
|
/<[^<]/, // cannot start with a '<<' to avoid conflicts with heredocs (a single < is fine, though)
|
2021-05-11 22:00:07 -04:00
|
|
|
$.expansion
|
|
|
|
),
|
2022-04-04 22:08:03 -04:00
|
|
|
repeat(choice(token.immediate(/[^\s\$]+/), $._immediate_expansion))
|
2021-05-11 22:00:07 -04:00
|
|
|
),
|
|
|
|
|
2024-04-19 16:08:28 -04:00
|
|
|
path_with_heredoc: ($) =>
|
|
|
|
choice(
|
|
|
|
$.heredoc_marker,
|
|
|
|
seq(
|
|
|
|
choice(
|
|
|
|
/[^-\s\$<]/, // cannot start with a '-' to avoid conflicts with params
|
|
|
|
/<[^-\s\$<]/,
|
|
|
|
$.expansion
|
|
|
|
),
|
|
|
|
repeat(choice(token.immediate(/[^\s\$]+/), $._immediate_expansion))
|
|
|
|
)
|
|
|
|
),
|
|
|
|
|
2022-04-04 22:08:03 -04:00
|
|
|
expansion: $ =>
|
|
|
|
seq("$", $._expansion_body),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
2022-04-04 22:08:03 -04:00
|
|
|
// we have 2 rules b/c aliases don't work as expected on seq() directly
|
|
|
|
_immediate_expansion: $ => alias($._imm_expansion, $.expansion),
|
|
|
|
_imm_expansion: $ =>
|
|
|
|
seq(token.immediate("$"), $._expansion_body),
|
|
|
|
|
|
|
|
_expansion_body: $ =>
|
|
|
|
choice(
|
|
|
|
$.variable,
|
|
|
|
seq(
|
|
|
|
token.immediate("{"),
|
|
|
|
alias(token.immediate(/[^\}]+/), $.variable),
|
|
|
|
token.immediate("}")
|
|
|
|
)
|
|
|
|
),
|
|
|
|
|
2022-09-13 19:27:53 -04:00
|
|
|
variable: ($) => token.immediate(/[a-zA-Z_][a-zA-Z0-9_]*/),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
env_pair: ($) =>
|
|
|
|
seq(
|
|
|
|
field("name", $._env_key),
|
|
|
|
token.immediate("="),
|
2022-01-23 14:33:36 -05:00
|
|
|
optional(
|
2023-06-22 22:44:07 -04:00
|
|
|
field("value",
|
|
|
|
choice(
|
|
|
|
$.double_quoted_string,
|
|
|
|
$.single_quoted_string,
|
|
|
|
$.unquoted_string
|
|
|
|
))
|
2022-01-23 14:33:36 -05:00
|
|
|
)
|
2021-05-11 22:00:07 -04:00
|
|
|
),
|
|
|
|
|
|
|
|
_spaced_env_pair: ($) =>
|
|
|
|
seq(
|
|
|
|
field("name", $._env_key),
|
|
|
|
token.immediate(/\s+/),
|
2023-06-22 22:44:07 -04:00
|
|
|
field("value",
|
|
|
|
choice(
|
|
|
|
$.double_quoted_string,
|
|
|
|
$.single_quoted_string,
|
|
|
|
$.unquoted_string
|
|
|
|
))
|
2021-05-11 22:00:07 -04:00
|
|
|
),
|
|
|
|
|
|
|
|
_env_key: ($) =>
|
2022-09-13 19:27:53 -04:00
|
|
|
alias(/[a-zA-Z_][a-zA-Z0-9_]*/, $.unquoted_string),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
expose_port: ($) => seq(/\d+/, optional(choice("/tcp", "/udp"))),
|
|
|
|
|
|
|
|
label_pair: ($) =>
|
|
|
|
seq(
|
2023-09-27 14:35:26 -04:00
|
|
|
field("key", choice(
|
|
|
|
alias(/[-a-zA-Z0-9\._]+/, $.unquoted_string),
|
|
|
|
$.double_quoted_string,
|
|
|
|
$.single_quoted_string
|
|
|
|
)),
|
2021-05-11 22:00:07 -04:00
|
|
|
token.immediate("="),
|
2023-06-22 22:44:07 -04:00
|
|
|
field("value",
|
|
|
|
choice(
|
|
|
|
$.double_quoted_string,
|
|
|
|
$.single_quoted_string,
|
|
|
|
$.unquoted_string
|
|
|
|
))
|
2021-05-11 22:00:07 -04:00
|
|
|
),
|
|
|
|
|
|
|
|
image_spec: ($) =>
|
|
|
|
seq(
|
|
|
|
field("name", $.image_name),
|
|
|
|
seq(
|
|
|
|
field("tag", optional($.image_tag)),
|
|
|
|
field("digest", optional($.image_digest))
|
|
|
|
)
|
|
|
|
),
|
|
|
|
|
2022-01-23 14:33:36 -05:00
|
|
|
image_name: ($) =>
|
|
|
|
seq(
|
|
|
|
choice(/[^@:\s\$-]/, $.expansion),
|
2022-04-04 22:08:03 -04:00
|
|
|
repeat(choice(token.immediate(/[^@:\s\$]+/), $._immediate_expansion))
|
2022-01-23 14:33:36 -05:00
|
|
|
),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
image_tag: ($) =>
|
|
|
|
seq(
|
|
|
|
token.immediate(":"),
|
2022-04-04 22:08:03 -04:00
|
|
|
repeat1(choice(token.immediate(/[^@\s\$]+/), $._immediate_expansion))
|
2021-05-11 22:00:07 -04:00
|
|
|
),
|
|
|
|
|
|
|
|
image_digest: ($) =>
|
|
|
|
seq(
|
|
|
|
token.immediate("@"),
|
2022-04-04 22:08:03 -04:00
|
|
|
repeat1(choice(token.immediate(/[a-zA-Z0-9:]+/), $._immediate_expansion))
|
2021-05-11 22:00:07 -04:00
|
|
|
),
|
|
|
|
|
2022-10-25 22:48:10 -04:00
|
|
|
// Generic parsing of options passed right after an instruction name.
|
2021-05-11 22:00:07 -04:00
|
|
|
param: ($) =>
|
|
|
|
seq(
|
|
|
|
"--",
|
|
|
|
field("name", token.immediate(/[a-z][-a-z]*/)),
|
|
|
|
token.immediate("="),
|
|
|
|
field("value", token.immediate(/[^\s]+/))
|
|
|
|
),
|
|
|
|
|
2022-10-25 22:48:10 -04:00
|
|
|
// Specific parsing of the --mount option e.g.
|
|
|
|
//
|
|
|
|
// --mount=type=cache,target=/root/.cache/go-build
|
|
|
|
//
|
|
|
|
mount_param: ($) => seq(
|
|
|
|
"--",
|
|
|
|
field("name", token.immediate("mount")),
|
|
|
|
token.immediate("="),
|
|
|
|
field(
|
|
|
|
"value",
|
|
|
|
seq(
|
|
|
|
$.mount_param_param,
|
|
|
|
repeat(
|
|
|
|
seq(token.immediate(","), $.mount_param_param)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
|
|
|
|
mount_param_param: ($) => seq(
|
|
|
|
token.immediate(/[^\s=,]+/),
|
|
|
|
token.immediate("="),
|
|
|
|
token.immediate(/[^\s=,]+/)
|
|
|
|
),
|
|
|
|
|
2022-04-04 22:08:03 -04:00
|
|
|
image_alias: ($) => seq(
|
|
|
|
choice(/[-a-zA-Z0-9_]+/, $.expansion),
|
|
|
|
repeat(choice(token.immediate(/[-a-zA-Z0-9_]+/), $._immediate_expansion))
|
|
|
|
),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
shell_command: ($) =>
|
|
|
|
seq(
|
2022-01-23 14:33:36 -05:00
|
|
|
repeat($._comment_line),
|
2021-05-11 22:00:07 -04:00
|
|
|
$.shell_fragment,
|
|
|
|
repeat(
|
2021-12-16 01:31:20 -05:00
|
|
|
seq(
|
|
|
|
alias($.required_line_continuation, $.line_continuation),
|
2022-01-23 14:33:36 -05:00
|
|
|
repeat($._comment_line),
|
|
|
|
$.shell_fragment
|
2021-12-16 01:31:20 -05:00
|
|
|
)
|
2021-05-11 22:00:07 -04:00
|
|
|
)
|
|
|
|
),
|
|
|
|
|
2022-10-25 22:48:10 -04:00
|
|
|
shell_fragment: ($) => repeat1(
|
|
|
|
choice(
|
|
|
|
// A shell fragment is broken into the same tokens as other
|
|
|
|
// constructs because the lexer prefers the longer tokens
|
|
|
|
// when it has a choice. The example below shows the tokenization
|
|
|
|
// of the --mount parameter.
|
|
|
|
//
|
|
|
|
// RUN --mount=foo=bar,baz=42 ls --all
|
|
|
|
// ^^ ^ ^ ^ ^
|
|
|
|
// ^^^^^ ^^^ ^^^ ^^^ ^^
|
|
|
|
// |--------param-------|
|
|
|
|
// |--shell_command--|
|
|
|
|
//
|
2024-04-19 16:08:28 -04:00
|
|
|
seq($.heredoc_marker, /[ \t]*/),
|
2022-10-25 22:48:10 -04:00
|
|
|
/[,=-]/,
|
2024-04-19 16:08:28 -04:00
|
|
|
/[^\\\[\n#\s,=-][^\\\n<]*/,
|
|
|
|
/\\[^\n,=-]/,
|
|
|
|
/<[^<]/,
|
2022-10-25 22:48:10 -04:00
|
|
|
)
|
|
|
|
),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
line_continuation: ($) => "\\\n",
|
2021-12-16 01:31:20 -05:00
|
|
|
required_line_continuation: ($) => "\\\n",
|
2021-05-11 22:00:07 -04:00
|
|
|
|
|
|
|
_comment_line: ($) => seq(alias($._anon_comment, $.comment), "\n"),
|
|
|
|
|
|
|
|
_anon_comment: ($) => seq("#", /.*/),
|
|
|
|
|
2023-06-22 22:44:07 -04:00
|
|
|
json_string_array: ($) =>
|
|
|
|
seq(
|
|
|
|
"[",
|
|
|
|
optional(
|
|
|
|
seq($.json_string, repeat(seq(",", $.json_string)))
|
|
|
|
),
|
|
|
|
"]"
|
|
|
|
),
|
|
|
|
|
|
|
|
// Note that JSON strings are different from the other double-quoted
|
|
|
|
// strings. They don't support $-expansions.
|
|
|
|
// Convenient reference: https://www.json.org/
|
2023-06-23 17:54:29 -04:00
|
|
|
json_string: ($) => seq(
|
|
|
|
'"',
|
|
|
|
repeat(
|
|
|
|
choice(
|
|
|
|
token.immediate(/[^"\\]+/),
|
|
|
|
alias($.json_escape_sequence, $.escape_sequence)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
'"'
|
|
|
|
),
|
|
|
|
|
|
|
|
json_escape_sequence: ($) => token.immediate(
|
|
|
|
/\\(?:["\\/bfnrt]|u[0-9A-Fa-f]{4})/
|
|
|
|
),
|
2023-06-22 22:44:07 -04:00
|
|
|
|
2021-05-11 22:00:07 -04:00
|
|
|
double_quoted_string: ($) =>
|
|
|
|
seq(
|
|
|
|
'"',
|
|
|
|
repeat(
|
2022-04-04 22:08:03 -04:00
|
|
|
choice(
|
|
|
|
token.immediate(/[^"\n\\\$]+/),
|
2023-06-23 17:54:29 -04:00
|
|
|
alias($.double_quoted_escape_sequence, $.escape_sequence),
|
2023-06-23 16:12:10 -04:00
|
|
|
"\\",
|
2022-04-04 22:08:03 -04:00
|
|
|
$._immediate_expansion
|
|
|
|
)
|
2021-05-11 22:00:07 -04:00
|
|
|
),
|
|
|
|
'"'
|
|
|
|
),
|
|
|
|
|
2023-06-22 22:44:07 -04:00
|
|
|
// same as double_quoted_string but without $-expansions:
|
|
|
|
single_quoted_string: ($) =>
|
|
|
|
seq(
|
|
|
|
"'",
|
|
|
|
repeat(
|
|
|
|
choice(
|
|
|
|
token.immediate(/[^'\n\\]+/),
|
2023-06-23 17:54:29 -04:00
|
|
|
alias($.single_quoted_escape_sequence, $.escape_sequence),
|
2023-06-23 16:12:10 -04:00
|
|
|
"\\",
|
2023-06-22 22:44:07 -04:00
|
|
|
)
|
|
|
|
),
|
|
|
|
"'"
|
|
|
|
),
|
|
|
|
|
2021-05-11 22:00:07 -04:00
|
|
|
unquoted_string: ($) =>
|
|
|
|
repeat1(
|
|
|
|
choice(
|
2023-06-22 22:44:07 -04:00
|
|
|
token.immediate(/[^\s\n\"'\\\$]+/),
|
2021-05-11 22:00:07 -04:00
|
|
|
token.immediate("\\ "),
|
2022-04-04 22:08:03 -04:00
|
|
|
$._immediate_expansion
|
2021-05-11 22:00:07 -04:00
|
|
|
)
|
|
|
|
),
|
|
|
|
|
2023-06-22 22:44:07 -04:00
|
|
|
double_quoted_escape_sequence: ($) => token.immediate(
|
|
|
|
choice(
|
|
|
|
"\\\\",
|
2023-06-23 16:12:10 -04:00
|
|
|
"\\\""
|
2023-06-22 22:44:07 -04:00
|
|
|
)
|
|
|
|
),
|
|
|
|
|
|
|
|
single_quoted_escape_sequence: ($) => token.immediate(
|
|
|
|
choice(
|
|
|
|
"\\\\",
|
2023-06-23 16:12:10 -04:00
|
|
|
"\\'"
|
2023-06-22 22:44:07 -04:00
|
|
|
)
|
|
|
|
),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
2024-04-19 16:08:28 -04:00
|
|
|
_non_newline_whitespace: ($) => token.immediate(/[\t ]+/),
|
2021-05-11 22:00:07 -04:00
|
|
|
|
2021-06-20 14:46:57 -04:00
|
|
|
comment: ($) => /#.*/,
|
2021-05-11 22:00:07 -04:00
|
|
|
},
|
2021-05-09 22:11:30 -04:00
|
|
|
});
|