Add quoted arguments, bracket expressions
This commit is contained in:
parent
5b26947ca8
commit
86e67f9403
|
@ -22,6 +22,21 @@ cat -n file1.txt file2.txt
|
||||||
(command (command_name) (argument))
|
(command (command_name) (argument))
|
||||||
(command (command_name) (argument) (argument) (argument)))
|
(command (command_name) (argument) (argument) (argument)))
|
||||||
|
|
||||||
|
===============================
|
||||||
|
Commands with string arguments
|
||||||
|
===============================
|
||||||
|
|
||||||
|
echo "hello $(whoami), this is $(uname)"
|
||||||
|
echo 'hi'
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(program
|
||||||
|
(command (command_name) (quoted_argument
|
||||||
|
(command_substitution (command (command_name)))
|
||||||
|
(command_substitution (command (command_name)))))
|
||||||
|
(command (command_name) (single_quoted_argument)))
|
||||||
|
|
||||||
===================================
|
===================================
|
||||||
Commands with environment variables
|
Commands with environment variables
|
||||||
===================================
|
===================================
|
||||||
|
@ -37,7 +52,7 @@ VAR1=a VAR2="ok" git diff --word-diff=color
|
||||||
(command_name))
|
(command_name))
|
||||||
(command
|
(command
|
||||||
(environment_variable_assignment (variable_name) (argument))
|
(environment_variable_assignment (variable_name) (argument))
|
||||||
(environment_variable_assignment (variable_name) (argument))
|
(environment_variable_assignment (variable_name) (quoted_argument))
|
||||||
(command_name)
|
(command_name)
|
||||||
(argument)
|
(argument)
|
||||||
(argument)))
|
(argument)))
|
||||||
|
|
|
@ -44,6 +44,24 @@ fi
|
||||||
(else_clause
|
(else_clause
|
||||||
(command (command_name)))))
|
(command (command_name)))))
|
||||||
|
|
||||||
|
====================================
|
||||||
|
If statements with conditional expressions
|
||||||
|
====================================
|
||||||
|
|
||||||
|
if [ "$(uname)" == 'Darwin' ]; then
|
||||||
|
echo one
|
||||||
|
fi
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(program
|
||||||
|
(if_statement
|
||||||
|
(bracket_command
|
||||||
|
(quoted_argument (command_substitution (command (command_name))))
|
||||||
|
(argument)
|
||||||
|
(single_quoted_argument))
|
||||||
|
(command (command_name) (argument))))
|
||||||
|
|
||||||
====================================
|
====================================
|
||||||
Case statements
|
Case statements
|
||||||
====================================
|
====================================
|
||||||
|
@ -61,7 +79,7 @@ esac
|
||||||
---
|
---
|
||||||
|
|
||||||
(program
|
(program
|
||||||
(case_statement (argument)
|
(case_statement (quoted_argument)
|
||||||
(case_item (argument)
|
(case_item (argument)
|
||||||
(command (command_name) (argument)))
|
(command (command_name) (argument)))
|
||||||
(case_item (argument)
|
(case_item (argument)
|
||||||
|
|
57
grammar.js
57
grammar.js
|
@ -1,7 +1,7 @@
|
||||||
module.exports = grammar({
|
module.exports = grammar({
|
||||||
name: 'bash',
|
name: 'bash',
|
||||||
|
|
||||||
inline: $ => [$.statement, $.terminator],
|
inline: $ => [$.statement, $.terminator, $.value],
|
||||||
|
|
||||||
externals: $ => [
|
externals: $ => [
|
||||||
$._simple_heredoc,
|
$._simple_heredoc,
|
||||||
|
@ -24,7 +24,9 @@ module.exports = grammar({
|
||||||
),
|
),
|
||||||
|
|
||||||
statement: $ => choice(
|
statement: $ => choice(
|
||||||
|
$.environment_variable_assignment,
|
||||||
$.command,
|
$.command,
|
||||||
|
$.bracket_command,
|
||||||
$.while_statement,
|
$.while_statement,
|
||||||
$.if_statement,
|
$.if_statement,
|
||||||
$.case_statement,
|
$.case_statement,
|
||||||
|
@ -68,7 +70,7 @@ module.exports = grammar({
|
||||||
|
|
||||||
case_statement: $ => seq(
|
case_statement: $ => seq(
|
||||||
'case',
|
'case',
|
||||||
rename($.word, 'argument'),
|
$.value,
|
||||||
optional($.terminator),
|
optional($.terminator),
|
||||||
'in',
|
'in',
|
||||||
$.terminator,
|
$.terminator,
|
||||||
|
@ -77,12 +79,17 @@ module.exports = grammar({
|
||||||
),
|
),
|
||||||
|
|
||||||
case_item: $ => seq(
|
case_item: $ => seq(
|
||||||
rename($.word, 'argument'),
|
$.value,
|
||||||
')',
|
')',
|
||||||
repeat($._terminated_statement),
|
repeat($._terminated_statement),
|
||||||
optional(';;')
|
optional(';;')
|
||||||
),
|
),
|
||||||
|
|
||||||
|
bracket_command: $ => choice(
|
||||||
|
seq('[', repeat1($.value), ']'),
|
||||||
|
seq('[[', repeat1($.value), ']]')
|
||||||
|
),
|
||||||
|
|
||||||
command: $ => seq(
|
command: $ => seq(
|
||||||
repeat(choice(
|
repeat(choice(
|
||||||
$.environment_variable_assignment,
|
$.environment_variable_assignment,
|
||||||
|
@ -91,11 +98,7 @@ module.exports = grammar({
|
||||||
rename($.leading_word, 'command_name'),
|
rename($.leading_word, 'command_name'),
|
||||||
optional(seq(
|
optional(seq(
|
||||||
/\s+/,
|
/\s+/,
|
||||||
repeat(choice(
|
repeat($.value)
|
||||||
rename($.word, 'argument'),
|
|
||||||
$.expansion,
|
|
||||||
$.operator_expansion
|
|
||||||
))
|
|
||||||
)),
|
)),
|
||||||
repeat(choice(
|
repeat(choice(
|
||||||
$.file_redirect,
|
$.file_redirect,
|
||||||
|
@ -118,9 +121,33 @@ module.exports = grammar({
|
||||||
environment_variable_assignment: $ => seq(
|
environment_variable_assignment: $ => seq(
|
||||||
rename($.leading_word, 'variable_name'),
|
rename($.leading_word, 'variable_name'),
|
||||||
'=',
|
'=',
|
||||||
rename($.word, 'argument')
|
$.value
|
||||||
),
|
),
|
||||||
|
|
||||||
|
value: $ => choice(
|
||||||
|
rename($.word, 'argument'),
|
||||||
|
$.command_substitution,
|
||||||
|
$.quoted_argument,
|
||||||
|
$.single_quoted_argument,
|
||||||
|
$.expansion,
|
||||||
|
$.operator_expansion
|
||||||
|
),
|
||||||
|
|
||||||
|
quoted_argument: $ => seq(
|
||||||
|
'"',
|
||||||
|
repeat(choice(
|
||||||
|
$._quoted_chars,
|
||||||
|
$.expansion,
|
||||||
|
$.operator_expansion,
|
||||||
|
$.command_substitution
|
||||||
|
)),
|
||||||
|
'"'
|
||||||
|
),
|
||||||
|
|
||||||
|
_quoted_chars: $ => /[^"$]+/,
|
||||||
|
|
||||||
|
single_quoted_argument: $ => /'[^']*'/,
|
||||||
|
|
||||||
expansion: $ => seq(
|
expansion: $ => seq(
|
||||||
'$',
|
'$',
|
||||||
rename($.word, 'variable_name')
|
rename($.word, 'variable_name')
|
||||||
|
@ -131,11 +158,17 @@ module.exports = grammar({
|
||||||
rename($.leading_word, 'variable_name'),
|
rename($.leading_word, 'variable_name'),
|
||||||
optional(seq(
|
optional(seq(
|
||||||
choice(':', ':?', '='),
|
choice(':', ':?', '='),
|
||||||
rename($.word, 'argument')
|
$.value
|
||||||
)),
|
)),
|
||||||
'}'
|
'}'
|
||||||
),
|
),
|
||||||
|
|
||||||
|
command_substitution: $ => seq(
|
||||||
|
'$(',
|
||||||
|
$.command,
|
||||||
|
')'
|
||||||
|
),
|
||||||
|
|
||||||
file_redirect: $ => seq(
|
file_redirect: $ => seq(
|
||||||
optional($.file_descriptor),
|
optional($.file_descriptor),
|
||||||
choice('<', '>', '<&', '>&'),
|
choice('<', '>', '<&', '>&'),
|
||||||
|
@ -165,9 +198,9 @@ module.exports = grammar({
|
||||||
|
|
||||||
file_descriptor: $ => token(prec(1, /\d+/)),
|
file_descriptor: $ => token(prec(1, /\d+/)),
|
||||||
|
|
||||||
leading_word: $ => /[^\\\s#=|;:{}]+/,
|
leading_word: $ => /[^"\\\s#=|;:{}()]+/,
|
||||||
|
|
||||||
word: $ => /[^#\\\s$<>{}&;)]+/,
|
word: $ => /[^"#\\\s$<>{}&;()]+/,
|
||||||
|
|
||||||
comment: $ => /#.*/,
|
comment: $ => /#.*/,
|
||||||
|
|
||||||
|
|
188
src/grammar.json
188
src/grammar.json
|
@ -24,10 +24,18 @@
|
||||||
"statement": {
|
"statement": {
|
||||||
"type": "CHOICE",
|
"type": "CHOICE",
|
||||||
"members": [
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "environment_variable_assignment"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "command"
|
"name": "command"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "bracket_command"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "while_statement"
|
"name": "while_statement"
|
||||||
|
@ -182,12 +190,8 @@
|
||||||
"value": "case"
|
"value": "case"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "RENAME",
|
|
||||||
"content": {
|
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "word"
|
"name": "value"
|
||||||
},
|
|
||||||
"value": "argument"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "CHOICE",
|
"type": "CHOICE",
|
||||||
|
@ -226,12 +230,8 @@
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "RENAME",
|
|
||||||
"content": {
|
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "word"
|
"name": "value"
|
||||||
},
|
|
||||||
"value": "argument"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
|
@ -258,6 +258,51 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"bracket_command": {
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "["
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "REPEAT1",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "value"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "[["
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "REPEAT1",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "value"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "]]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"command": {
|
"command": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
|
@ -297,26 +342,9 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "REPEAT",
|
"type": "REPEAT",
|
||||||
"content": {
|
|
||||||
"type": "CHOICE",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"type": "RENAME",
|
|
||||||
"content": {
|
"content": {
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "word"
|
"name": "value"
|
||||||
},
|
|
||||||
"value": "argument"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "expansion"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "operator_expansion"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -419,6 +447,15 @@
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": "="
|
"value": "="
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "value"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "RENAME",
|
"type": "RENAME",
|
||||||
"content": {
|
"content": {
|
||||||
|
@ -426,9 +463,74 @@
|
||||||
"name": "word"
|
"name": "word"
|
||||||
},
|
},
|
||||||
"value": "argument"
|
"value": "argument"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "command_substitution"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "quoted_argument"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "single_quoted_argument"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "expansion"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "operator_expansion"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"quoted_argument": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "\""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "REPEAT",
|
||||||
|
"content": {
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "_quoted_chars"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "expansion"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "operator_expansion"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "command_substitution"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "\""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"_quoted_chars": {
|
||||||
|
"type": "PATTERN",
|
||||||
|
"value": "[^\"$]+"
|
||||||
|
},
|
||||||
|
"single_quoted_argument": {
|
||||||
|
"type": "PATTERN",
|
||||||
|
"value": "'[^']*'"
|
||||||
|
},
|
||||||
"expansion": {
|
"expansion": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
|
@ -485,12 +587,8 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "RENAME",
|
|
||||||
"content": {
|
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "word"
|
"name": "value"
|
||||||
},
|
|
||||||
"value": "argument"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -505,6 +603,23 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"command_substitution": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "$("
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "command"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": ")"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"file_redirect": {
|
"file_redirect": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
|
@ -637,11 +752,11 @@
|
||||||
},
|
},
|
||||||
"leading_word": {
|
"leading_word": {
|
||||||
"type": "PATTERN",
|
"type": "PATTERN",
|
||||||
"value": "[^\\\\\\s#=|;:{}]+"
|
"value": "[^\"\\\\\\s#=|;:{}()]+"
|
||||||
},
|
},
|
||||||
"word": {
|
"word": {
|
||||||
"type": "PATTERN",
|
"type": "PATTERN",
|
||||||
"value": "[^#\\\\\\s$<>{}&;)]+"
|
"value": "[^\"#\\\\\\s$<>{}&;()]+"
|
||||||
},
|
},
|
||||||
"comment": {
|
"comment": {
|
||||||
"type": "PATTERN",
|
"type": "PATTERN",
|
||||||
|
@ -708,6 +823,7 @@
|
||||||
],
|
],
|
||||||
"inline": [
|
"inline": [
|
||||||
"statement",
|
"statement",
|
||||||
"terminator"
|
"terminator",
|
||||||
|
"value"
|
||||||
]
|
]
|
||||||
}
|
}
|
14889
src/parser.c
14889
src/parser.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue