Add support for replacement vars

This commit is contained in:
Camden Cheek 2021-05-10 15:11:30 -06:00
parent 05a2aba52a
commit 3055288ce1
No known key found for this signature in database
GPG key ID: 595BFFE3A04E48B9
7 changed files with 7036 additions and 4461 deletions

View file

@ -8,7 +8,8 @@ FROM testimage
(source_file
(from_instruction
(image_spec)))
(image_spec
name: (image_name))))
==================
Image with tag
@ -21,7 +22,8 @@ FROM testimage:tag
(source_file
(from_instruction
(image_spec
(image_tag))))
name: (image_name)
tag: (image_tag))))
==================
Image with digest
@ -34,7 +36,8 @@ FROM testimage@sha256:skgshlshg
(source_file
(from_instruction
(image_spec
(image_digest))))
name: (image_name)
digest: (image_digest))))
==================
Image with tag and digest
@ -47,8 +50,9 @@ FROM testimage:tag@sha256:452525
(source_file
(from_instruction
(image_spec
(image_tag)
(image_digest))))
name: (image_name)
tag: (image_tag)
digest: (image_digest))))
==================
@ -62,7 +66,8 @@ FROM sourcegraph/alpine:3.12@sha256:ce099fbcd3cf70b338fc4cb2a4e1fa9ae847de21afdb
(source_file
(from_instruction
(image_spec
(image_tag)
(image_digest))
(name)))
name: (image_name)
tag: (image_tag)
digest: (image_digest))
as: (name)))

View file

@ -46,3 +46,47 @@ LABEL key.1="value1" \
(label_pair
key: (unquoted_string)
value: (double_quoted_string))))
==================
Label
==================
LABEL key="value${FOO}"
---
(source_file
(label_instruction
(label_pair
key: (unquoted_string)
value: (double_quoted_string
(env_spec)))))
==================
Stopsignal
==================
STOPSIGNAL $FOO
---
(source_file
(stopsignal_instruction
(env_spec)))
==================
User
==================
USER foo$FOO:bar$BAR
---
(source_file
(user_instruction
user: (unquoted_string
(env_spec))
group: (unquoted_string
(env_spec))))

197
corpus/vars.txt Normal file
View file

@ -0,0 +1,197 @@
==================
Add
==================
ADD /$FOO ./${bar}
---
(source_file
(add_instruction
(path
(env_spec))
(path
(env_spec))))
==================
Copy
==================
COPY $FOO ./${bar}
---
(source_file
(copy_instruction
(path
(env_spec))
(path
(env_spec))))
==================
Special chars
==================
COPY $FOO ./${bar:-abc}
---
(source_file
(copy_instruction
(path
(env_spec))
(path
(env_spec))))
==================
Env
==================
ENV TEST="foo$BAR" \
TEST_2=foo\ bar$BAZ \
TEST_3="foo${bar}" \
TEST_4=foo\ ${baz}bar \
---
(source_file
(env_instruction
(env_pair
name: (unquoted_string)
value: (double_quoted_string
(env_spec)))
(env_pair
name: (unquoted_string)
value: (unquoted_string
(env_spec)))
(env_pair
name: (unquoted_string)
value: (double_quoted_string
(env_spec)))
(env_pair
name: (unquoted_string)
value: (unquoted_string
(env_spec)))))
==================
Expose
==================
EXPOSE $FOO
---
(source_file
(expose_instruction
(expose_port
(env_spec))))
==================
From
==================
FROM foo/$FOO:$BAR@sha256:$BAZ AS baz$QUX
---
(source_file
(from_instruction
(image_spec
name: (image_name
(env_spec))
tag: (image_tag
(env_spec))
digest: (image_digest
(env_spec)))
as: (name
(env_spec))))
==================
Label
==================
LABEL key="value$FOO"
---
(source_file
(label_instruction
(label_pair
key: (unquoted_string)
value: (double_quoted_string
(env_spec)))))
==================
Stopsignal
==================
STOPSIGNAL $FOO
---
(source_file
(stopsignal_instruction
(env_spec)))
==================
User
==================
USER foo$FOO:bar${bar}
---
(source_file
(user_instruction
user: (unquoted_string
(env_spec))
group: (unquoted_string
(env_spec))))
==================
Volume
==================
volume /my$FOO /my${bar}
---
(source_file
(volume_instruction
(path
(env_spec))
(path
(env_spec))))
==================
Workdir
==================
WORKDIR /tmp/$FOO
---
(source_file
(workdir_instruction
(path
(env_spec))))
==================
Onbuild
==================
ONBUILD ADD /$FOO ./${bar}
---
(source_file
(onbuild_instruction
(add_instruction
(path
(env_spec))
(path
(env_spec)))))

View file

@ -33,7 +33,7 @@ module.exports = grammar({
$.image_spec,
optional(seq(
alias(/[aA][sS]/, "AS"),
$.name,
field("as", $.name),
)),
),
@ -78,6 +78,7 @@ module.exports = grammar({
$._non_newline_whitespace,
optional($.param),
$.path,
$._non_newline_whitespace,
$.path,
),
@ -86,6 +87,7 @@ module.exports = grammar({
$._non_newline_whitespace,
optional($.param),
$.path,
$._non_newline_whitespace,
$.path,
),
@ -103,20 +105,28 @@ module.exports = grammar({
$._non_newline_whitespace,
choice(
$.string_array,
repeat1($.path),
seq(
$.path,
repeat(seq($._non_newline_whitespace, $.path)),
),
),
),
user_instruction: $ => seq(
alias(/[uU][sS][eE][rR]/, "USER"),
$._non_newline_whitespace,
field("user", alias(/[a-z][-a-z0-9_]*/, $.unquoted_string)),
field("user", alias($._user_name_group, $.unquoted_string)),
optional(seq(
token.immediate(":"),
field("group", alias(token.immediate(/[a-z][-a-z0-9_]*/), $.unquoted_string)),
field("group", alias($._user_name_group, $.unquoted_string)),
)),
),
_user_name_group: $ => repeat1(choice(
token.immediate(/[a-z][-a-z0-9_]*/),
$.env_spec,
)),
workdir_instruction: $ => seq(
alias(/[wW][oO][rR][kK][dD][iI][rR]/, "WORKDIR"),
$._non_newline_whitespace,
@ -145,9 +155,14 @@ module.exports = grammar({
stopsignal_instruction: $ => seq(
alias(/[sS][tT][oO][pP][sS][iI][gG][nN][aA][lL]/, "STOPSIGNAL"),
$._non_newline_whitespace,
/[A-Z0-9]+/,
$._stopsignal_value,
),
_stopsignal_value: $ => repeat1(choice(
/[A-Z0-9]+/,
$.env_spec,
)),
healthcheck_instruction: $ => seq(
alias(/[hH][eE][aA][lL][tT][hH][cC][hH][eE][cC][kK]/, "HEALTHCHECK"),
$._non_newline_whitespace,
@ -166,7 +181,26 @@ module.exports = grammar({
$.string_array,
),
path: $ => /[^-\[][^\s]*/,
// path: $ => /[^-\[][^\s]*/,
path: $ => seq(
choice(
/[^-\s]/, // cannot start with a '-' to avoid conflicts with params
$.env_spec,
),
repeat(choice(
token.immediate(/[^\s\$]+/),
$.env_spec,
)),
),
env_spec: $ => seq(
'$',
repeat1(choice(
token.immediate(/[a-zA-Z][a-zA-Z0-9_]*/),
seq('{', /[^\}]+/, '}'),
))
),
env_pair: $ => seq(
field("name", alias(/[a-zA-Z][a-zA-Z0-9_]+[a-zA-Z0-9]/, $.unquoted_string)),
@ -177,12 +211,15 @@ module.exports = grammar({
)),
),
expose_port: $ => seq(
/\d+/,
optional(choice(
"/tcp",
"/udp",
)),
expose_port: $ => choice(
seq(
/\d+/,
optional(choice(
"/tcp",
"/udp",
)),
),
$.env_spec,
),
label_pair: $ => seq(
@ -195,31 +232,45 @@ module.exports = grammar({
),
image_spec: $ => seq(
alias(/[^:@\s]+/, "name"),
field("name", $.image_name),
seq(
optional($.image_tag),
optional($.image_digest),
field("tag", optional($.image_tag)),
field("digest", optional($.image_digest)),
),
),
image_tag: $ => token.immediate(seq(
":",
/[^\s@]+/,
image_name: $ => repeat1(choice(
token.immediate(/[^:@\s\$]+/),
$.env_spec,
)),
image_digest: $ => token.immediate(seq(
"@",
/[^\s]+/,
)),
image_tag: $ => seq(
token.immediate(":"),
repeat1(choice(
token.immediate(/[^\s@\$]+/),
$.env_spec,
))
),
image_digest: $ => seq(
token.immediate("@"),
repeat1(choice(
token.immediate(/[^\s\$]+/),
$.env_spec,
)),
),
param: $ => seq(
"--",
field("name", /[a-z][-a-z]*/),
"=",
field("value", /[^\s]+/),
field("name", token.immediate(/[a-z][-a-z]*/)),
token.immediate("="),
field("value", token.immediate(/[^\s]+/)),
),
name: $ => /[-a-z_]+/,
name: $ => repeat1(choice(
/[-a-z_]+/,
$.env_spec,
)),
string_array: $ => seq(
"[",
@ -231,22 +282,24 @@ module.exports = grammar({
),
shell_command: $ => seq(
/[^\[\s].*[^\\\n]/,
/[^\[\s].*[^\\\n]/, // TODO allow escape sequences
repeat(seq("\\\n", /.*[^\\\n]/)),
),
double_quoted_string: $ => seq(
'"',
repeat(choice(
token.immediate(prec(1, /[^"\n\\]+/)),
$.escape_sequence
token.immediate(prec(1, /[^"\n\\\$]+/)),
$.escape_sequence,
$.env_spec,
)),
'"'
),
unquoted_string: $ => repeat1(choice(
token.immediate(/[^\s\n\"\\]+/),
token.immediate(/[^\s\n\"\\\$]+/),
token.immediate("\\ "),
$.env_spec,
)),
escape_sequence: $ => token.immediate(seq(
@ -260,7 +313,7 @@ module.exports = grammar({
)
)),
_non_newline_whitespace: $ => /[\t ]*/,
_non_newline_whitespace: $ => /[\t ]+/,
comment: $ => seq("#", /.*/),
}

View file

@ -138,8 +138,12 @@
"value": "AS"
},
{
"type": "SYMBOL",
"name": "name"
"type": "FIELD",
"name": "as",
"content": {
"type": "SYMBOL",
"name": "name"
}
}
]
},
@ -319,6 +323,10 @@
"type": "SYMBOL",
"name": "path"
},
{
"type": "SYMBOL",
"name": "_non_newline_whitespace"
},
{
"type": "SYMBOL",
"name": "path"
@ -357,6 +365,10 @@
"type": "SYMBOL",
"name": "path"
},
{
"type": "SYMBOL",
"name": "_non_newline_whitespace"
},
{
"type": "SYMBOL",
"name": "path"
@ -418,11 +430,29 @@
"name": "string_array"
},
{
"type": "REPEAT1",
"content": {
"type": "SYMBOL",
"name": "path"
}
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "path"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_non_newline_whitespace"
},
{
"type": "SYMBOL",
"name": "path"
}
]
}
}
]
}
]
}
@ -450,8 +480,8 @@
"content": {
"type": "ALIAS",
"content": {
"type": "PATTERN",
"value": "[a-z][-a-z0-9_]*"
"type": "SYMBOL",
"name": "_user_name_group"
},
"named": true,
"value": "unquoted_string"
@ -476,11 +506,8 @@
"content": {
"type": "ALIAS",
"content": {
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "PATTERN",
"value": "[a-z][-a-z0-9_]*"
}
"type": "SYMBOL",
"name": "_user_name_group"
},
"named": true,
"value": "unquoted_string"
@ -495,6 +522,25 @@
}
]
},
"_user_name_group": {
"type": "REPEAT1",
"content": {
"type": "CHOICE",
"members": [
{
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "PATTERN",
"value": "[a-z][-a-z0-9_]*"
}
},
{
"type": "SYMBOL",
"name": "env_spec"
}
]
}
},
"workdir_instruction": {
"type": "SEQ",
"members": [
@ -624,11 +670,27 @@
"name": "_non_newline_whitespace"
},
{
"type": "PATTERN",
"value": "[A-Z0-9]+"
"type": "SYMBOL",
"name": "_stopsignal_value"
}
]
},
"_stopsignal_value": {
"type": "REPEAT1",
"content": {
"type": "CHOICE",
"members": [
{
"type": "PATTERN",
"value": "[A-Z0-9]+"
},
{
"type": "SYMBOL",
"name": "env_spec"
}
]
}
},
"healthcheck_instruction": {
"type": "SEQ",
"members": [
@ -695,8 +757,82 @@
]
},
"path": {
"type": "PATTERN",
"value": "[^-\\[][^\\s]*"
"type": "SEQ",
"members": [
{
"type": "CHOICE",
"members": [
{
"type": "PATTERN",
"value": "[^-\\s]"
},
{
"type": "SYMBOL",
"name": "env_spec"
}
]
},
{
"type": "REPEAT",
"content": {
"type": "CHOICE",
"members": [
{
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "PATTERN",
"value": "[^\\s\\$]+"
}
},
{
"type": "SYMBOL",
"name": "env_spec"
}
]
}
}
]
},
"env_spec": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "$"
},
{
"type": "REPEAT1",
"content": {
"type": "CHOICE",
"members": [
{
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "PATTERN",
"value": "[a-zA-Z][a-zA-Z0-9_]*"
}
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "{"
},
{
"type": "PATTERN",
"value": "[^\\}]+"
},
{
"type": "STRING",
"value": "}"
}
]
}
]
}
}
]
},
"env_pair": {
"type": "SEQ",
@ -741,32 +877,41 @@
]
},
"expose_port": {
"type": "SEQ",
"type": "CHOICE",
"members": [
{
"type": "PATTERN",
"value": "\\d+"
},
{
"type": "CHOICE",
"type": "SEQ",
"members": [
{
"type": "PATTERN",
"value": "\\d+"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "/tcp"
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "/tcp"
},
{
"type": "STRING",
"value": "/udp"
}
]
},
{
"type": "STRING",
"value": "/udp"
"type": "BLANK"
}
]
},
{
"type": "BLANK"
}
]
},
{
"type": "SYMBOL",
"name": "env_spec"
}
]
},
@ -816,76 +961,132 @@
"type": "SEQ",
"members": [
{
"type": "ALIAS",
"type": "FIELD",
"name": "name",
"content": {
"type": "PATTERN",
"value": "[^:@\\s]+"
},
"named": false,
"value": "name"
"type": "SYMBOL",
"name": "image_name"
}
},
{
"type": "SEQ",
"members": [
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "image_tag"
},
{
"type": "BLANK"
}
]
"type": "FIELD",
"name": "tag",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "image_tag"
},
{
"type": "BLANK"
}
]
}
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "image_digest"
},
{
"type": "BLANK"
}
]
"type": "FIELD",
"name": "digest",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "image_digest"
},
{
"type": "BLANK"
}
]
}
}
]
}
]
},
"image_tag": {
"type": "IMMEDIATE_TOKEN",
"image_name": {
"type": "REPEAT1",
"content": {
"type": "SEQ",
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ":"
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "PATTERN",
"value": "[^:@\\s\\$]+"
}
},
{
"type": "PATTERN",
"value": "[^\\s@]+"
"type": "SYMBOL",
"name": "env_spec"
}
]
}
},
"image_tag": {
"type": "SEQ",
"members": [
{
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "STRING",
"value": ":"
}
},
{
"type": "REPEAT1",
"content": {
"type": "CHOICE",
"members": [
{
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "PATTERN",
"value": "[^\\s@\\$]+"
}
},
{
"type": "SYMBOL",
"name": "env_spec"
}
]
}
}
]
},
"image_digest": {
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "SEQ",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "STRING",
"value": "@"
},
{
"type": "PATTERN",
"value": "[^\\s]+"
}
]
}
},
{
"type": "REPEAT1",
"content": {
"type": "CHOICE",
"members": [
{
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "PATTERN",
"value": "[^\\s\\$]+"
}
},
{
"type": "SYMBOL",
"name": "env_spec"
}
]
}
}
]
},
"param": {
"type": "SEQ",
@ -898,27 +1099,48 @@
"type": "FIELD",
"name": "name",
"content": {
"type": "PATTERN",
"value": "[a-z][-a-z]*"
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "PATTERN",
"value": "[a-z][-a-z]*"
}
}
},
{
"type": "STRING",
"value": "="
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "STRING",
"value": "="
}
},
{
"type": "FIELD",
"name": "value",
"content": {
"type": "PATTERN",
"value": "[^\\s]+"
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "PATTERN",
"value": "[^\\s]+"
}
}
}
]
},
"name": {
"type": "PATTERN",
"value": "[-a-z_]+"
"type": "REPEAT1",
"content": {
"type": "CHOICE",
"members": [
{
"type": "PATTERN",
"value": "[-a-z_]+"
},
{
"type": "SYMBOL",
"name": "env_spec"
}
]
}
},
"string_array": {
"type": "SEQ",
@ -1010,13 +1232,17 @@
"value": 1,
"content": {
"type": "PATTERN",
"value": "[^\"\\n\\\\]+"
"value": "[^\"\\n\\\\\\$]+"
}
}
},
{
"type": "SYMBOL",
"name": "escape_sequence"
},
{
"type": "SYMBOL",
"name": "env_spec"
}
]
}
@ -1036,7 +1262,7 @@
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "PATTERN",
"value": "[^\\s\\n\\\"\\\\]+"
"value": "[^\\s\\n\\\"\\\\\\$]+"
}
},
{
@ -1045,6 +1271,10 @@
"type": "STRING",
"value": "\\ "
}
},
{
"type": "SYMBOL",
"name": "env_spec"
}
]
}
@ -1088,7 +1318,7 @@
},
"_non_newline_whitespace": {
"type": "PATTERN",
"value": "[\\t ]*"
"value": "[\\t ]+"
},
"comment": {
"type": "SEQ",

View file

@ -99,6 +99,10 @@
"multiple": true,
"required": false,
"types": [
{
"type": "env_spec",
"named": true
},
{
"type": "escape_sequence",
"named": true
@ -170,6 +174,11 @@
}
}
},
{
"type": "env_spec",
"named": true,
"fields": {}
},
{
"type": "expose_instruction",
"named": true,
@ -188,12 +197,33 @@
{
"type": "expose_port",
"named": true,
"fields": {}
"fields": {},
"children": {
"multiple": false,
"required": false,
"types": [
{
"type": "env_spec",
"named": true
}
]
}
},
{
"type": "from_instruction",
"named": true,
"fields": {},
"fields": {
"as": {
"multiple": false,
"required": false,
"types": [
{
"type": "name",
"named": true
}
]
}
},
"children": {
"multiple": true,
"required": true,
@ -202,10 +232,6 @@
"type": "image_spec",
"named": true
},
{
"type": "name",
"named": true
},
{
"type": "param",
"named": true
@ -233,7 +259,7 @@
}
},
{
"type": "image_spec",
"type": "image_digest",
"named": true,
"fields": {},
"children": {
@ -241,11 +267,73 @@
"required": false,
"types": [
{
"type": "image_digest",
"type": "env_spec",
"named": true
},
}
]
}
},
{
"type": "image_name",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "image_tag",
"type": "env_spec",
"named": true
}
]
}
},
{
"type": "image_spec",
"named": true,
"fields": {
"digest": {
"multiple": false,
"required": false,
"types": [
{
"type": "image_digest",
"named": true
}
]
},
"name": {
"multiple": false,
"required": true,
"types": [
{
"type": "image_name",
"named": true
}
]
},
"tag": {
"multiple": false,
"required": false,
"types": [
{
"type": "image_tag",
"named": true
}
]
}
}
},
{
"type": "image_tag",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "env_spec",
"named": true
}
]
@ -296,6 +384,21 @@
}
}
},
{
"type": "name",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "env_spec",
"named": true
}
]
}
},
{
"type": "onbuild_instruction",
"named": true,
@ -380,6 +483,21 @@
"named": true,
"fields": {}
},
{
"type": "path",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "env_spec",
"named": true
}
]
}
},
{
"type": "run_instruction",
"named": true,
@ -501,7 +619,17 @@
{
"type": "stopsignal_instruction",
"named": true,
"fields": {}
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "env_spec",
"named": true
}
]
}
},
{
"type": "string_array",
@ -521,7 +649,17 @@
{
"type": "unquoted_string",
"named": true,
"fields": {}
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "env_spec",
"named": true
}
]
}
},
{
"type": "user_instruction",
@ -595,6 +733,10 @@
"type": "#",
"named": false
},
{
"type": "$",
"named": false
},
{
"type": ",",
"named": false
@ -619,6 +761,10 @@
"type": "=",
"named": false
},
{
"type": "@",
"named": false
},
{
"type": "ADD",
"named": false
@ -716,23 +862,11 @@
"named": true
},
{
"type": "image_digest",
"named": true
},
{
"type": "image_tag",
"named": true
},
{
"type": "name",
"type": "{",
"named": false
},
{
"type": "name",
"named": true
},
{
"type": "path",
"named": true
"type": "}",
"named": false
}
]

10530
src/parser.c

File diff suppressed because it is too large Load diff