mirror of
https://github.com/pnx/tree-sitter-dotenv
synced 2026-10-14 12:06:44 +02:00
fix: parse variable references in unquoted strings
This commit is contained in:
parent
a16f203ba0
commit
90f212b3ea
5 changed files with 1171 additions and 582 deletions
40
grammar.js
40
grammar.js
|
|
@ -45,10 +45,12 @@ module.exports = grammar({
|
||||||
comment: _ => /\#[^\n]*/,
|
comment: _ => /\#[^\n]*/,
|
||||||
|
|
||||||
identifier: _ => /[A-Za-z_][A-Za-z0-9_]*/,
|
identifier: _ => /[A-Za-z_][A-Za-z0-9_]*/,
|
||||||
variable: $ => seq('$', choice(
|
variable: $ => choice(
|
||||||
$.identifier,
|
seq('$', $.identifier),
|
||||||
seq('{', $.identifier, '}')
|
$._braced_variable,
|
||||||
)),
|
),
|
||||||
|
|
||||||
|
_braced_variable: $ => seq('$', '{', $.identifier, '}'),
|
||||||
|
|
||||||
_value: $ => choice(
|
_value: $ => choice(
|
||||||
$.string,
|
$.string,
|
||||||
|
|
@ -66,7 +68,35 @@ module.exports = grammar({
|
||||||
$._unquoted_string,
|
$._unquoted_string,
|
||||||
),
|
),
|
||||||
|
|
||||||
_unquoted_string: $ => alias(/[^\#\s\"\'\$]+(?:[ \t]+[^\#\s\"\'\$]+)+/, $.string_content),
|
_unquoted_string: $ => choice(
|
||||||
|
alias($._unquoted_content, $.string_content),
|
||||||
|
seq(
|
||||||
|
choice(
|
||||||
|
alias($.value, $.string_content),
|
||||||
|
alias($.boolean, $.string_content),
|
||||||
|
alias($.decimal, $.string_content),
|
||||||
|
alias($.hexadecimal, $.string_content),
|
||||||
|
alias($.float, $.string_content),
|
||||||
|
alias($._unquoted_content, $.string_content),
|
||||||
|
),
|
||||||
|
alias($._braced_variable, $.variable),
|
||||||
|
optional(choice(
|
||||||
|
alias($.value, $.string_content),
|
||||||
|
alias($._unquoted_content, $.string_content),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
_unquoted_content: _ => token(choice(
|
||||||
|
/[^\#\s\"\'\$]+(?:[ \t]+[^\#\s\"\'\$]+)+/,
|
||||||
|
seq(
|
||||||
|
/[^\#\s\"\'\$]+(?:[ \t]+[^\#\s\"\'\$]+)*/,
|
||||||
|
repeat1(seq(
|
||||||
|
/\$[A-Za-z_][A-Za-z0-9_]*/,
|
||||||
|
optional(/(?:[ \t]*[^\#\s\"\'\$]+)+/),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
|
||||||
_literal_string: $ => seq(
|
_literal_string: $ => seq(
|
||||||
"'",
|
"'",
|
||||||
|
|
|
||||||
222
src/grammar.json
generated
222
src/grammar.json
generated
|
|
@ -143,6 +143,28 @@
|
||||||
"value": "[A-Za-z_][A-Za-z0-9_]*"
|
"value": "[A-Za-z_][A-Za-z0-9_]*"
|
||||||
},
|
},
|
||||||
"variable": {
|
"variable": {
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "identifier"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "_braced_variable"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"_braced_variable": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
|
|
@ -150,30 +172,16 @@
|
||||||
"value": "$"
|
"value": "$"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "CHOICE",
|
"type": "STRING",
|
||||||
"members": [
|
"value": "{"
|
||||||
{
|
},
|
||||||
"type": "SYMBOL",
|
{
|
||||||
"name": "identifier"
|
"type": "SYMBOL",
|
||||||
},
|
"name": "identifier"
|
||||||
{
|
},
|
||||||
"type": "SEQ",
|
{
|
||||||
"members": [
|
"type": "STRING",
|
||||||
{
|
"value": "}"
|
||||||
"type": "STRING",
|
|
||||||
"value": "{"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "identifier"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "STRING",
|
|
||||||
"value": "}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -220,13 +228,167 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"_unquoted_string": {
|
"_unquoted_string": {
|
||||||
"type": "ALIAS",
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "ALIAS",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "_unquoted_content"
|
||||||
|
},
|
||||||
|
"named": true,
|
||||||
|
"value": "string_content"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "ALIAS",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "value"
|
||||||
|
},
|
||||||
|
"named": true,
|
||||||
|
"value": "string_content"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ALIAS",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "boolean"
|
||||||
|
},
|
||||||
|
"named": true,
|
||||||
|
"value": "string_content"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ALIAS",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "decimal"
|
||||||
|
},
|
||||||
|
"named": true,
|
||||||
|
"value": "string_content"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ALIAS",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "hexadecimal"
|
||||||
|
},
|
||||||
|
"named": true,
|
||||||
|
"value": "string_content"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ALIAS",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "float"
|
||||||
|
},
|
||||||
|
"named": true,
|
||||||
|
"value": "string_content"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ALIAS",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "_unquoted_content"
|
||||||
|
},
|
||||||
|
"named": true,
|
||||||
|
"value": "string_content"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ALIAS",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "_braced_variable"
|
||||||
|
},
|
||||||
|
"named": true,
|
||||||
|
"value": "variable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "ALIAS",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "value"
|
||||||
|
},
|
||||||
|
"named": true,
|
||||||
|
"value": "string_content"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ALIAS",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "_unquoted_content"
|
||||||
|
},
|
||||||
|
"named": true,
|
||||||
|
"value": "string_content"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"_unquoted_content": {
|
||||||
|
"type": "TOKEN",
|
||||||
"content": {
|
"content": {
|
||||||
"type": "PATTERN",
|
"type": "CHOICE",
|
||||||
"value": "[^\\#\\s\\\"\\'\\$]+(?:[ \\t]+[^\\#\\s\\\"\\'\\$]+)+"
|
"members": [
|
||||||
},
|
{
|
||||||
"named": true,
|
"type": "PATTERN",
|
||||||
"value": "string_content"
|
"value": "[^\\#\\s\\\"\\'\\$]+(?:[ \\t]+[^\\#\\s\\\"\\'\\$]+)+"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "PATTERN",
|
||||||
|
"value": "[^\\#\\s\\\"\\'\\$]+(?:[ \\t]+[^\\#\\s\\\"\\'\\$]+)*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "REPEAT1",
|
||||||
|
"content": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "PATTERN",
|
||||||
|
"value": "\\$[A-Za-z_][A-Za-z0-9_]*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "PATTERN",
|
||||||
|
"value": "(?:[ \\t]*[^\\#\\s\\\"\\'\\$]+)+"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"_literal_string": {
|
"_literal_string": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
|
|
|
||||||
1248
src/parser.c
generated
1248
src/parser.c
generated
File diff suppressed because it is too large
Load diff
161
test/corpus/scalar_interpolation.txt
Normal file
161
test/corpus/scalar_interpolation.txt
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
================================================================================
|
||||||
|
Boolean prefixes become string content
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
PLAIN_TRUE=true
|
||||||
|
TRUE_PREFIX=true${APP_NAME}
|
||||||
|
PLAIN_FALSE=false
|
||||||
|
FALSE_PREFIX=false${APP_NAME}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(document
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(boolean))
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(string
|
||||||
|
(string_content)
|
||||||
|
(variable (identifier))))
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(boolean))
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(string
|
||||||
|
(string_content)
|
||||||
|
(variable (identifier)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Numeric prefixes become string content
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
PLAIN_INTEGER=123
|
||||||
|
INTEGER_PREFIX=123${APP_NAME}
|
||||||
|
PLAIN_NEGATIVE=-123
|
||||||
|
NEGATIVE_PREFIX=-123${APP_NAME}
|
||||||
|
PLAIN_HEX=0xFF
|
||||||
|
HEX_PREFIX=0xFF${APP_NAME}
|
||||||
|
PLAIN_FLOAT=1.5
|
||||||
|
FLOAT_PREFIX=1.5${APP_NAME}
|
||||||
|
PLAIN_NEGATIVE_FLOAT=-1.5
|
||||||
|
NEGATIVE_FLOAT_PREFIX=-1.5${APP_NAME}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(document
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(number (integer (decimal))))
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(string
|
||||||
|
(string_content)
|
||||||
|
(variable (identifier))))
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(number (integer (decimal))))
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(string
|
||||||
|
(string_content)
|
||||||
|
(variable (identifier))))
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(number (integer (hexadecimal))))
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(string
|
||||||
|
(string_content)
|
||||||
|
(variable (identifier))))
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(number (float)))
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(string
|
||||||
|
(string_content)
|
||||||
|
(variable (identifier))))
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(number (float)))
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(string
|
||||||
|
(string_content)
|
||||||
|
(variable (identifier)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Scalar prefixes with suffixes and comments
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
BOOL=true${APP_NAME}-suffix # comment
|
||||||
|
NUMBER=123${APP_NAME} suffix words
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(document
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(string
|
||||||
|
(string_content)
|
||||||
|
(variable (identifier))
|
||||||
|
(string_content)))
|
||||||
|
(comment)
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(string
|
||||||
|
(string_content)
|
||||||
|
(variable (identifier))
|
||||||
|
(string_content))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Bare boolean-prefixed references are literal strings
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
BOOL=true$APP_NAME
|
||||||
|
BOOL=false$APP_NAME
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(document
|
||||||
|
(assignment (identifier) (string (string_content)))
|
||||||
|
(assignment (identifier) (string (string_content))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Bare decimal-prefixed references are literal strings
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
NUMBER=123$APP_NAME
|
||||||
|
NUMBER=-123$APP_NAME
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(document
|
||||||
|
(assignment (identifier) (string (string_content)))
|
||||||
|
(assignment (identifier) (string (string_content))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Bare hexadecimal-prefixed references are literal strings
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
HEX=0xFF$APP_NAME
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(document
|
||||||
|
(assignment (identifier) (string (string_content))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Bare float-prefixed references are literal strings
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
FLOAT=1.5$APP_NAME
|
||||||
|
FLOAT=-1.5$APP_NAME
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(document
|
||||||
|
(assignment (identifier) (string (string_content)))
|
||||||
|
(assignment (identifier) (string (string_content))))
|
||||||
|
|
@ -42,3 +42,85 @@ MULTIPLE = "variable is: ${VARIABLE}, and $ANOTHER !!!"
|
||||||
(variable
|
(variable
|
||||||
(identifier))
|
(identifier))
|
||||||
(string_content))))
|
(string_content))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Unquoted braced variables with prefixes
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
BASIC = prefix${VARIABLE}
|
||||||
|
VITE_APP_NAME=xxx${APP_NAME}
|
||||||
|
SUFFIX = prefix${VARIABLE}-suffix
|
||||||
|
MULTIWORD = prefix words${VARIABLE} suffix words # comment
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(document
|
||||||
|
(assignment
|
||||||
|
key: (identifier)
|
||||||
|
value: (string
|
||||||
|
(string_content)
|
||||||
|
(variable
|
||||||
|
(identifier))))
|
||||||
|
(assignment
|
||||||
|
key: (identifier)
|
||||||
|
value: (string
|
||||||
|
(string_content)
|
||||||
|
(variable
|
||||||
|
(identifier))))
|
||||||
|
(assignment
|
||||||
|
key: (identifier)
|
||||||
|
value: (string
|
||||||
|
(string_content)
|
||||||
|
(variable
|
||||||
|
(identifier))
|
||||||
|
(string_content)))
|
||||||
|
(assignment
|
||||||
|
key: (identifier)
|
||||||
|
value: (string
|
||||||
|
(string_content)
|
||||||
|
(variable
|
||||||
|
(identifier))
|
||||||
|
(string_content)))
|
||||||
|
(comment))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Unquoted bare references with prefixes are literal strings
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
VITE_APP_NAME=xxx$APP_NAME
|
||||||
|
NAME=XXX$APP_NAME
|
||||||
|
SUFFIX=xxx$APP_NAME-suffix
|
||||||
|
MULTIPLE=xxx$APP_NAME$OTHER
|
||||||
|
MULTIWORD=prefix words$APP_NAME suffix words # comment
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(document
|
||||||
|
(assignment (identifier) (string (string_content)))
|
||||||
|
(assignment (identifier) (string (string_content)))
|
||||||
|
(assignment (identifier) (string (string_content)))
|
||||||
|
(assignment (identifier) (string (string_content)))
|
||||||
|
(assignment (identifier) (string (string_content)))
|
||||||
|
(comment))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Literal bare references alongside braced interpolation
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
PREFIX=xxx$LITERAL${APP_NAME}
|
||||||
|
SUFFIX=xxx${APP_NAME}suffix$LITERAL
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(document
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(string
|
||||||
|
(string_content)
|
||||||
|
(variable (identifier))))
|
||||||
|
(assignment
|
||||||
|
(identifier)
|
||||||
|
(string
|
||||||
|
(string_content)
|
||||||
|
(variable (identifier))
|
||||||
|
(string_content))))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue