Add support for single-quoted strings and distinguish JSON strings from
the double-quoted strings that support variable expansion.
This commit is contained in:
parent
fd30df68c4
commit
98fdcad2a0
|
@ -41,7 +41,7 @@ cmd []
|
||||||
|
|
||||||
(source_file
|
(source_file
|
||||||
(cmd_instruction
|
(cmd_instruction
|
||||||
(string_array)))
|
(json_string_array)))
|
||||||
|
|
||||||
==================
|
==================
|
||||||
Run with shell array
|
Run with shell array
|
||||||
|
@ -52,8 +52,8 @@ cmd ["echo", "test"]
|
||||||
---
|
---
|
||||||
|
|
||||||
(source_file
|
(source_file
|
||||||
(cmd_instruction
|
(cmd_instruction
|
||||||
(string_array
|
(json_string_array
|
||||||
(double_quoted_string)
|
(json_string)
|
||||||
(double_quoted_string))))
|
(json_string))))
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ ENTRYPOINT []
|
||||||
|
|
||||||
(source_file
|
(source_file
|
||||||
(entrypoint_instruction
|
(entrypoint_instruction
|
||||||
(string_array)))
|
(json_string_array)))
|
||||||
|
|
||||||
==================
|
==================
|
||||||
Run with shell array
|
Run with shell array
|
||||||
|
@ -52,8 +52,7 @@ ENTRYPOINT ["echo", "test"]
|
||||||
---
|
---
|
||||||
|
|
||||||
(source_file
|
(source_file
|
||||||
(entrypoint_instruction
|
(entrypoint_instruction
|
||||||
(string_array
|
(json_string_array
|
||||||
(double_quoted_string)
|
(json_string)
|
||||||
(double_quoted_string))))
|
(json_string))))
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ run []
|
||||||
|
|
||||||
(source_file
|
(source_file
|
||||||
(run_instruction
|
(run_instruction
|
||||||
(string_array)))
|
(json_string_array)))
|
||||||
|
|
||||||
==================
|
==================
|
||||||
Run with shell array
|
Run with shell array
|
||||||
|
@ -52,10 +52,10 @@ run ["echo", "test"]
|
||||||
---
|
---
|
||||||
|
|
||||||
(source_file
|
(source_file
|
||||||
(run_instruction
|
(run_instruction
|
||||||
(string_array
|
(json_string_array
|
||||||
(double_quoted_string)
|
(json_string)
|
||||||
(double_quoted_string))))
|
(json_string))))
|
||||||
|
|
||||||
==================
|
==================
|
||||||
Run with options
|
Run with options
|
||||||
|
|
|
@ -8,7 +8,7 @@ SHELL ["powershell","-command"]
|
||||||
|
|
||||||
(source_file
|
(source_file
|
||||||
(shell_instruction
|
(shell_instruction
|
||||||
(string_array
|
(json_string_array
|
||||||
(double_quoted_string)
|
(json_string)
|
||||||
(double_quoted_string))))
|
(json_string))))
|
||||||
|
|
||||||
|
|
146
corpus/strings.txt
Normal file
146
corpus/strings.txt
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
==========================
|
||||||
|
JSON string arrays
|
||||||
|
==========================
|
||||||
|
|
||||||
|
CMD ["a", "bcd"]
|
||||||
|
CMD ["\"\\"]
|
||||||
|
CMD ["\b\f\n\r\t\u0ABC\u12Cd"]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(cmd_instruction
|
||||||
|
(json_string_array
|
||||||
|
(json_string)
|
||||||
|
(json_string)))
|
||||||
|
(cmd_instruction
|
||||||
|
(json_string_array
|
||||||
|
(json_string)))
|
||||||
|
(cmd_instruction
|
||||||
|
(json_string_array
|
||||||
|
(json_string))))
|
||||||
|
|
||||||
|
==========================
|
||||||
|
Double-quoted strings
|
||||||
|
==========================
|
||||||
|
|
||||||
|
ENV KEY "value"
|
||||||
|
ENV KEY "conti\
|
||||||
|
nue"
|
||||||
|
ENV KEY "quotes: \" '"
|
||||||
|
ENV KEY "backslash: \\"
|
||||||
|
ENV KEY "not escape sequences: \a \n"
|
||||||
|
ENV KEY "expansions: $FOO ${BAR}"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(double_quoted_string)))
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(double_quoted_string
|
||||||
|
(line_continuation))))
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(double_quoted_string
|
||||||
|
(double_quoted_escape_sequence))))
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(double_quoted_string
|
||||||
|
(double_quoted_escape_sequence))))
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(double_quoted_string
|
||||||
|
(double_quoted_escape_sequence)
|
||||||
|
(double_quoted_escape_sequence))))
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(double_quoted_string
|
||||||
|
(expansion
|
||||||
|
(variable))
|
||||||
|
(expansion
|
||||||
|
(variable))))))
|
||||||
|
|
||||||
|
==========================
|
||||||
|
Single-quoted strings
|
||||||
|
==========================
|
||||||
|
|
||||||
|
ENV KEY 'value'
|
||||||
|
ENV KEY 'conti\
|
||||||
|
nue'
|
||||||
|
ENV KEY 'quotes: \' \''
|
||||||
|
ENV KEY 'backslash: \\'
|
||||||
|
ENV KEY 'not escape sequences: \a \n'
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(single_quoted_string)))
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(single_quoted_string
|
||||||
|
(line_continuation))))
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(single_quoted_string
|
||||||
|
(single_quoted_escape_sequence)
|
||||||
|
(single_quoted_escape_sequence))))
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(single_quoted_string
|
||||||
|
(single_quoted_escape_sequence))))
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(single_quoted_string
|
||||||
|
(single_quoted_escape_sequence)
|
||||||
|
(single_quoted_escape_sequence)))))
|
||||||
|
|
||||||
|
==========================
|
||||||
|
Unquoted strings
|
||||||
|
==========================
|
||||||
|
|
||||||
|
ENV KEY value
|
||||||
|
ENV KEY two\ words
|
||||||
|
ENV KEY conti\
|
||||||
|
nue
|
||||||
|
ENV KEY $FOO${BAR}baz
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(unquoted_string)))
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(unquoted_string)))
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(unquoted_string
|
||||||
|
(line_continuation))))
|
||||||
|
(env_instruction
|
||||||
|
(env_pair
|
||||||
|
(unquoted_string)
|
||||||
|
(unquoted_string
|
||||||
|
(expansion
|
||||||
|
(variable))
|
||||||
|
(expansion
|
||||||
|
(variable))))))
|
|
@ -49,8 +49,8 @@ VOLUME ["/test/myvol"]
|
||||||
|
|
||||||
(source_file
|
(source_file
|
||||||
(volume_instruction
|
(volume_instruction
|
||||||
(string_array
|
(json_string_array
|
||||||
(double_quoted_string))))
|
(json_string))))
|
||||||
|
|
||||||
==================
|
==================
|
||||||
Multiline array
|
Multiline array
|
||||||
|
@ -63,7 +63,7 @@ VOLUME ["/test/myvol", \
|
||||||
|
|
||||||
(source_file
|
(source_file
|
||||||
(volume_instruction
|
(volume_instruction
|
||||||
(string_array
|
(json_string_array
|
||||||
(double_quoted_string)
|
(json_string)
|
||||||
(line_continuation)
|
(line_continuation)
|
||||||
(double_quoted_string))))
|
(json_string))))
|
||||||
|
|
106
grammar.js
106
grammar.js
|
@ -46,13 +46,13 @@ module.exports = grammar({
|
||||||
$.mount_param
|
$.mount_param
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
choice($.string_array, $.shell_command)
|
choice($.json_string_array, $.shell_command)
|
||||||
),
|
),
|
||||||
|
|
||||||
cmd_instruction: ($) =>
|
cmd_instruction: ($) =>
|
||||||
seq(
|
seq(
|
||||||
alias(/[cC][mM][dD]/, "CMD"),
|
alias(/[cC][mM][dD]/, "CMD"),
|
||||||
choice($.string_array, $.shell_command)
|
choice($.json_string_array, $.shell_command)
|
||||||
),
|
),
|
||||||
|
|
||||||
label_instruction: ($) =>
|
label_instruction: ($) =>
|
||||||
|
@ -93,14 +93,14 @@ module.exports = grammar({
|
||||||
entrypoint_instruction: ($) =>
|
entrypoint_instruction: ($) =>
|
||||||
seq(
|
seq(
|
||||||
alias(/[eE][nN][tT][rR][yY][pP][oO][iI][nN][tT]/, "ENTRYPOINT"),
|
alias(/[eE][nN][tT][rR][yY][pP][oO][iI][nN][tT]/, "ENTRYPOINT"),
|
||||||
choice($.string_array, $.shell_command)
|
choice($.json_string_array, $.shell_command)
|
||||||
),
|
),
|
||||||
|
|
||||||
volume_instruction: ($) =>
|
volume_instruction: ($) =>
|
||||||
seq(
|
seq(
|
||||||
alias(/[vV][oO][lL][uU][mM][eE]/, "VOLUME"),
|
alias(/[vV][oO][lL][uU][mM][eE]/, "VOLUME"),
|
||||||
choice(
|
choice(
|
||||||
$.string_array,
|
$.json_string_array,
|
||||||
seq($.path, repeat(seq($._non_newline_whitespace, $.path)))
|
seq($.path, repeat(seq($._non_newline_whitespace, $.path)))
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -144,7 +144,12 @@ module.exports = grammar({
|
||||||
optional(
|
optional(
|
||||||
seq(
|
seq(
|
||||||
token.immediate("="),
|
token.immediate("="),
|
||||||
field("default", choice($.double_quoted_string, $.unquoted_string))
|
field("default",
|
||||||
|
choice(
|
||||||
|
$.double_quoted_string,
|
||||||
|
$.single_quoted_string,
|
||||||
|
$.unquoted_string
|
||||||
|
))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -171,7 +176,7 @@ module.exports = grammar({
|
||||||
),
|
),
|
||||||
|
|
||||||
shell_instruction: ($) =>
|
shell_instruction: ($) =>
|
||||||
seq(alias(/[sS][hH][eE][lL][lL]/, "SHELL"), $.string_array),
|
seq(alias(/[sS][hH][eE][lL][lL]/, "SHELL"), $.json_string_array),
|
||||||
|
|
||||||
maintainer_instruction: ($) =>
|
maintainer_instruction: ($) =>
|
||||||
seq(
|
seq(
|
||||||
|
@ -222,7 +227,12 @@ module.exports = grammar({
|
||||||
field("name", $._env_key),
|
field("name", $._env_key),
|
||||||
token.immediate("="),
|
token.immediate("="),
|
||||||
optional(
|
optional(
|
||||||
field("value", choice($.double_quoted_string, $.unquoted_string))
|
field("value",
|
||||||
|
choice(
|
||||||
|
$.double_quoted_string,
|
||||||
|
$.single_quoted_string,
|
||||||
|
$.unquoted_string
|
||||||
|
))
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -230,7 +240,12 @@ module.exports = grammar({
|
||||||
seq(
|
seq(
|
||||||
field("name", $._env_key),
|
field("name", $._env_key),
|
||||||
token.immediate(/\s+/),
|
token.immediate(/\s+/),
|
||||||
field("value", choice($.double_quoted_string, $.unquoted_string))
|
field("value",
|
||||||
|
choice(
|
||||||
|
$.double_quoted_string,
|
||||||
|
$.single_quoted_string,
|
||||||
|
$.unquoted_string
|
||||||
|
))
|
||||||
),
|
),
|
||||||
|
|
||||||
_env_key: ($) =>
|
_env_key: ($) =>
|
||||||
|
@ -242,7 +257,12 @@ module.exports = grammar({
|
||||||
seq(
|
seq(
|
||||||
field("key", alias(/[-a-zA-Z0-9\._]+/, $.unquoted_string)),
|
field("key", alias(/[-a-zA-Z0-9\._]+/, $.unquoted_string)),
|
||||||
token.immediate("="),
|
token.immediate("="),
|
||||||
field("value", choice($.double_quoted_string, $.unquoted_string))
|
field("value",
|
||||||
|
choice(
|
||||||
|
$.double_quoted_string,
|
||||||
|
$.single_quoted_string,
|
||||||
|
$.unquoted_string
|
||||||
|
))
|
||||||
),
|
),
|
||||||
|
|
||||||
image_spec: ($) =>
|
image_spec: ($) =>
|
||||||
|
@ -311,15 +331,6 @@ module.exports = grammar({
|
||||||
repeat(choice(token.immediate(/[-a-zA-Z0-9_]+/), $._immediate_expansion))
|
repeat(choice(token.immediate(/[-a-zA-Z0-9_]+/), $._immediate_expansion))
|
||||||
),
|
),
|
||||||
|
|
||||||
string_array: ($) =>
|
|
||||||
seq(
|
|
||||||
"[",
|
|
||||||
optional(
|
|
||||||
seq($.double_quoted_string, repeat(seq(",", $.double_quoted_string)))
|
|
||||||
),
|
|
||||||
"]"
|
|
||||||
),
|
|
||||||
|
|
||||||
shell_command: ($) =>
|
shell_command: ($) =>
|
||||||
seq(
|
seq(
|
||||||
repeat($._comment_line),
|
repeat($._comment_line),
|
||||||
|
@ -359,41 +370,70 @@ module.exports = grammar({
|
||||||
|
|
||||||
_anon_comment: ($) => seq("#", /.*/),
|
_anon_comment: ($) => seq("#", /.*/),
|
||||||
|
|
||||||
|
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/
|
||||||
|
json_string: ($) => /"(?:[^"\\]|\\(?:["\\/bfnrt]|u[0-9A-Fa-f]{4}))*"/,
|
||||||
|
|
||||||
double_quoted_string: ($) =>
|
double_quoted_string: ($) =>
|
||||||
seq(
|
seq(
|
||||||
'"',
|
'"',
|
||||||
repeat(
|
repeat(
|
||||||
choice(
|
choice(
|
||||||
token.immediate(/[^"\n\\\$]+/),
|
token.immediate(/[^"\n\\\$]+/),
|
||||||
$.escape_sequence,
|
$.double_quoted_escape_sequence,
|
||||||
$._immediate_expansion
|
$._immediate_expansion
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
'"'
|
'"'
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// same as double_quoted_string but without $-expansions:
|
||||||
|
single_quoted_string: ($) =>
|
||||||
|
seq(
|
||||||
|
"'",
|
||||||
|
repeat(
|
||||||
|
choice(
|
||||||
|
token.immediate(/[^'\n\\]+/),
|
||||||
|
$.single_quoted_escape_sequence
|
||||||
|
)
|
||||||
|
),
|
||||||
|
"'"
|
||||||
|
),
|
||||||
|
|
||||||
unquoted_string: ($) =>
|
unquoted_string: ($) =>
|
||||||
repeat1(
|
repeat1(
|
||||||
choice(
|
choice(
|
||||||
token.immediate(/[^\s\n\"\\\$]+/),
|
token.immediate(/[^\s\n\"'\\\$]+/),
|
||||||
token.immediate("\\ "),
|
token.immediate("\\ "),
|
||||||
$._immediate_expansion
|
$._immediate_expansion
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
escape_sequence: ($) =>
|
double_quoted_escape_sequence: ($) => token.immediate(
|
||||||
token.immediate(
|
choice(
|
||||||
seq(
|
"\\\\",
|
||||||
"\\",
|
"\\\"",
|
||||||
choice(
|
"\\"
|
||||||
/[^xuU]/,
|
)
|
||||||
/\d{2,3}/,
|
),
|
||||||
/x[0-9a-fA-F]{2,}/,
|
|
||||||
/u[0-9a-fA-F]{4}/,
|
single_quoted_escape_sequence: ($) => token.immediate(
|
||||||
/U[0-9a-fA-F]{8}/
|
choice(
|
||||||
)
|
"\\\\",
|
||||||
)
|
"\\'",
|
||||||
),
|
"\\"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
_non_newline_whitespace: ($) => /[\t ]+/,
|
_non_newline_whitespace: ($) => /[\t ]+/,
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue