Merge pull request #20 from returntocorp/sticky-tokens
Disallow whitespace in some multi-fragment constructs.
This commit is contained in:
commit
25c71d6a24
108
corpus/from.txt
108
corpus/from.txt
|
@ -86,3 +86,111 @@ FROM --platform=linux/arm64 alpine-${VERSION}-z
|
|||
(image_name
|
||||
(expansion
|
||||
(variable))))))
|
||||
|
||||
======================================================
|
||||
No spaces in image name
|
||||
======================================================
|
||||
|
||||
FROM a b c
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(ERROR
|
||||
(from_instruction
|
||||
(image_spec
|
||||
(image_name)))))
|
||||
|
||||
======================================================
|
||||
No spaces in image name before expansion
|
||||
======================================================
|
||||
|
||||
FROM a $b
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(from_instruction
|
||||
(ERROR)
|
||||
(image_spec
|
||||
(image_name
|
||||
(expansion
|
||||
(variable))))))
|
||||
|
||||
======================================================
|
||||
No spaces in image name expansion
|
||||
======================================================
|
||||
|
||||
FROM $ X
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(ERROR))
|
||||
|
||||
======================================================
|
||||
No spaces in image tag expansion
|
||||
======================================================
|
||||
|
||||
FROM a: $B
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(from_instruction
|
||||
(ERROR
|
||||
(image_name))
|
||||
(image_spec
|
||||
(image_name
|
||||
(expansion
|
||||
(variable))))))
|
||||
|
||||
======================================================
|
||||
No spaces in image digest
|
||||
======================================================
|
||||
|
||||
FROM a:b@ $c
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(from_instruction
|
||||
(ERROR
|
||||
(image_name)
|
||||
(image_tag))
|
||||
(image_spec
|
||||
(image_name
|
||||
(expansion
|
||||
(variable))))))
|
||||
|
||||
======================================================
|
||||
No spaces in image alias
|
||||
======================================================
|
||||
|
||||
FROM a AS b c
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(ERROR
|
||||
(from_instruction
|
||||
(image_spec
|
||||
(image_name))
|
||||
(image_alias))))
|
||||
|
||||
======================================================
|
||||
No spaces in image alias expansion
|
||||
======================================================
|
||||
|
||||
FROM a AS b $C
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(from_instruction
|
||||
(image_spec
|
||||
(image_name))
|
||||
(ERROR)
|
||||
(image_alias
|
||||
(expansion
|
||||
(variable)))))
|
||||
|
|
|
@ -19,3 +19,55 @@ STOPSIGNAL SIGKILL
|
|||
|
||||
(source_file
|
||||
(stopsignal_instruction))
|
||||
|
||||
=========================================================
|
||||
Signal value with expansions
|
||||
=========================================================
|
||||
|
||||
STOPSIGNAL A$BC${DE}F
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(stopsignal_instruction
|
||||
(expansion
|
||||
(variable))
|
||||
(expansion
|
||||
(variable))))
|
||||
|
||||
=========================================================
|
||||
No space in signal value
|
||||
=========================================================
|
||||
|
||||
STOPSIGNAL A B
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(ERROR
|
||||
(stopsignal_instruction)))
|
||||
|
||||
=========================================================
|
||||
No space in signal value before expansion
|
||||
=========================================================
|
||||
|
||||
STOPSIGNAL A $B
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(stopsignal_instruction
|
||||
(ERROR)
|
||||
(expansion
|
||||
(variable))))
|
||||
|
||||
=========================================================
|
||||
No space in signal value within expansion
|
||||
=========================================================
|
||||
|
||||
STOPSIGNAL A$ B
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(ERROR))
|
||||
|
|
|
@ -35,3 +35,15 @@ USER 1004:1004
|
|||
(user_instruction
|
||||
user: (unquoted_string)
|
||||
group: (unquoted_string)))
|
||||
|
||||
===========================
|
||||
No spaces in user:group
|
||||
===========================
|
||||
|
||||
USER a: b
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(ERROR
|
||||
(unquoted_string)))
|
||||
|
|
66
grammar.js
66
grammar.js
|
@ -106,13 +106,27 @@ module.exports = grammar({
|
|||
optional(
|
||||
seq(
|
||||
token.immediate(":"),
|
||||
field("group", alias($._user_name_or_group, $.unquoted_string))
|
||||
field("group",
|
||||
alias($._immediate_user_name_or_group, $.unquoted_string))
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
_user_name_or_group: ($) =>
|
||||
repeat1(choice(/([a-z][-a-z0-9_]*|[0-9]+)/, $.expansion)),
|
||||
seq(
|
||||
choice(/([a-z][-a-z0-9_]*|[0-9]+)/, $.expansion),
|
||||
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(
|
||||
token.immediate(/([a-z][-a-z0-9_]*|[0-9]+)/),
|
||||
$._immediate_expansion
|
||||
),
|
||||
|
||||
workdir_instruction: ($) =>
|
||||
seq(alias(/[wW][oO][rR][kK][dD][iI][rR]/, "WORKDIR"), $.path),
|
||||
|
@ -138,7 +152,11 @@ module.exports = grammar({
|
|||
$._stopsignal_value
|
||||
),
|
||||
|
||||
_stopsignal_value: ($) => repeat1(choice(/[A-Z0-9]+/, $.expansion)),
|
||||
_stopsignal_value: ($) =>
|
||||
seq(
|
||||
choice(/[A-Z0-9]+/, $.expansion),
|
||||
repeat(choice(token.immediate(/[A-Z0-9]+/), $._immediate_expansion))
|
||||
),
|
||||
|
||||
healthcheck_instruction: ($) =>
|
||||
seq(
|
||||
|
@ -170,13 +188,28 @@ module.exports = grammar({
|
|||
/[^-\s\$]/, // cannot start with a '-' to avoid conflicts with params
|
||||
$.expansion
|
||||
),
|
||||
repeat(choice(/[^\s\$]+/, $.expansion))
|
||||
repeat(choice(token.immediate(/[^\s\$]+/), $._immediate_expansion))
|
||||
),
|
||||
|
||||
expansion: ($) =>
|
||||
seq("$", choice($.variable, seq("{", alias(/[^\}]+/, $.variable), "}"))),
|
||||
expansion: $ =>
|
||||
seq("$", $._expansion_body),
|
||||
|
||||
variable: ($) => /[a-zA-Z][a-zA-Z0-9_]*/,
|
||||
// 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("}")
|
||||
)
|
||||
),
|
||||
|
||||
variable: ($) => token.immediate(/[a-zA-Z][a-zA-Z0-9_]*/),
|
||||
|
||||
env_pair: ($) =>
|
||||
seq(
|
||||
|
@ -218,19 +251,19 @@ module.exports = grammar({
|
|||
image_name: ($) =>
|
||||
seq(
|
||||
choice(/[^@:\s\$-]/, $.expansion),
|
||||
repeat(choice(/[^@:\s\$]+/, $.expansion))
|
||||
repeat(choice(token.immediate(/[^@:\s\$]+/), $._immediate_expansion))
|
||||
),
|
||||
|
||||
image_tag: ($) =>
|
||||
seq(
|
||||
token.immediate(":"),
|
||||
repeat1(choice(token.immediate(/[^@\s\$]+/), $.expansion))
|
||||
repeat1(choice(token.immediate(/[^@\s\$]+/), $._immediate_expansion))
|
||||
),
|
||||
|
||||
image_digest: ($) =>
|
||||
seq(
|
||||
token.immediate("@"),
|
||||
repeat1(choice(token.immediate(/[a-zA-Z0-9:]+/), $.expansion))
|
||||
repeat1(choice(token.immediate(/[a-zA-Z0-9:]+/), $._immediate_expansion))
|
||||
),
|
||||
|
||||
param: ($) =>
|
||||
|
@ -241,7 +274,10 @@ module.exports = grammar({
|
|||
field("value", token.immediate(/[^\s]+/))
|
||||
),
|
||||
|
||||
image_alias: ($) => repeat1(choice(/[-a-zA-Z0-9_]+/, $.expansion)),
|
||||
image_alias: ($) => seq(
|
||||
choice(/[-a-zA-Z0-9_]+/, $.expansion),
|
||||
repeat(choice(token.immediate(/[-a-zA-Z0-9_]+/), $._immediate_expansion))
|
||||
),
|
||||
|
||||
string_array: ($) =>
|
||||
seq(
|
||||
|
@ -278,7 +314,11 @@ module.exports = grammar({
|
|||
seq(
|
||||
'"',
|
||||
repeat(
|
||||
choice(token.immediate(/[^"\n\\\$]+/), $.escape_sequence, $.expansion)
|
||||
choice(
|
||||
token.immediate(/[^"\n\\\$]+/),
|
||||
$.escape_sequence,
|
||||
$._immediate_expansion
|
||||
)
|
||||
),
|
||||
'"'
|
||||
),
|
||||
|
@ -288,7 +328,7 @@ module.exports = grammar({
|
|||
choice(
|
||||
token.immediate(/[^\s\n\"\\\$]+/),
|
||||
token.immediate("\\ "),
|
||||
$.expansion
|
||||
$._immediate_expansion
|
||||
)
|
||||
),
|
||||
|
||||
|
|
261
src/grammar.json
261
src/grammar.json
|
@ -519,7 +519,7 @@
|
|||
"type": "ALIAS",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "_user_name_or_group"
|
||||
"name": "_immediate_user_name_or_group"
|
||||
},
|
||||
"named": true,
|
||||
"value": "unquoted_string"
|
||||
|
@ -535,20 +535,52 @@
|
|||
]
|
||||
},
|
||||
"_user_name_or_group": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "([a-z][-a-z0-9_]*|[0-9]+)"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expansion"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "_immediate_user_name_or_group_fragment"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"_immediate_user_name_or_group": {
|
||||
"type": "REPEAT1",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_immediate_user_name_or_group_fragment"
|
||||
}
|
||||
},
|
||||
"_immediate_user_name_or_group_fragment": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "IMMEDIATE_TOKEN",
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "([a-z][-a-z0-9_]*|[0-9]+)"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expansion"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_immediate_expansion"
|
||||
}
|
||||
]
|
||||
},
|
||||
"workdir_instruction": {
|
||||
"type": "SEQ",
|
||||
|
@ -669,20 +701,41 @@
|
|||
]
|
||||
},
|
||||
"_stopsignal_value": {
|
||||
"type": "REPEAT1",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[A-Z0-9]+"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expansion"
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[A-Z0-9]+"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expansion"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "IMMEDIATE_TOKEN",
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "[A-Z0-9]+"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_immediate_expansion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"healthcheck_instruction": {
|
||||
"type": "SEQ",
|
||||
|
@ -799,12 +852,15 @@
|
|||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[^\\s\\$]+"
|
||||
"type": "IMMEDIATE_TOKEN",
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "[^\\s\\$]+"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expansion"
|
||||
"name": "_immediate_expansion"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -819,41 +875,82 @@
|
|||
"value": "$"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"type": "SYMBOL",
|
||||
"name": "_expansion_body"
|
||||
}
|
||||
]
|
||||
},
|
||||
"_immediate_expansion": {
|
||||
"type": "ALIAS",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "_imm_expansion"
|
||||
},
|
||||
"named": true,
|
||||
"value": "expansion"
|
||||
},
|
||||
"_imm_expansion": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "IMMEDIATE_TOKEN",
|
||||
"content": {
|
||||
"type": "STRING",
|
||||
"value": "$"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_expansion_body"
|
||||
}
|
||||
]
|
||||
},
|
||||
"_expansion_body": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "variable"
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "variable"
|
||||
"type": "IMMEDIATE_TOKEN",
|
||||
"content": {
|
||||
"type": "STRING",
|
||||
"value": "{"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "{"
|
||||
},
|
||||
{
|
||||
"type": "ALIAS",
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "[^\\}]+"
|
||||
},
|
||||
"named": true,
|
||||
"value": "variable"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "}"
|
||||
"type": "ALIAS",
|
||||
"content": {
|
||||
"type": "IMMEDIATE_TOKEN",
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "[^\\}]+"
|
||||
}
|
||||
]
|
||||
},
|
||||
"named": true,
|
||||
"value": "variable"
|
||||
},
|
||||
{
|
||||
"type": "IMMEDIATE_TOKEN",
|
||||
"content": {
|
||||
"type": "STRING",
|
||||
"value": "}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"variable": {
|
||||
"type": "PATTERN",
|
||||
"value": "[a-zA-Z][a-zA-Z0-9_]*"
|
||||
"type": "IMMEDIATE_TOKEN",
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "[a-zA-Z][a-zA-Z0-9_]*"
|
||||
}
|
||||
},
|
||||
"env_pair": {
|
||||
"type": "SEQ",
|
||||
|
@ -1090,12 +1187,15 @@
|
|||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[^@:\\s\\$]+"
|
||||
"type": "IMMEDIATE_TOKEN",
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "[^@:\\s\\$]+"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expansion"
|
||||
"name": "_immediate_expansion"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1126,7 +1226,7 @@
|
|||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expansion"
|
||||
"name": "_immediate_expansion"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1157,7 +1257,7 @@
|
|||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expansion"
|
||||
"name": "_immediate_expansion"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1203,20 +1303,41 @@
|
|||
]
|
||||
},
|
||||
"image_alias": {
|
||||
"type": "REPEAT1",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[-a-zA-Z0-9_]+"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expansion"
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "PATTERN",
|
||||
"value": "[-a-zA-Z0-9_]+"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expansion"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "IMMEDIATE_TOKEN",
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "[-a-zA-Z0-9_]+"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_immediate_expansion"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"string_array": {
|
||||
"type": "SEQ",
|
||||
|
@ -1388,7 +1509,7 @@
|
|||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expansion"
|
||||
"name": "_immediate_expansion"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -1420,7 +1541,7 @@
|
|||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expansion"
|
||||
"name": "_immediate_expansion"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
8497
src/parser.c
8497
src/parser.c
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue