Add quoted arguments, bracket expressions

This commit is contained in:
Max Brunsfeld 2017-07-14 16:47:25 -07:00
parent 5b26947ca8
commit 86e67f9403
5 changed files with 10702 additions and 4477 deletions

View File

@ -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)))

View File

@ -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)

View File

@ -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: $ => /#.*/,

View File

@ -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", "type": "SYMBOL",
"content": { "name": "value"
"type": "SYMBOL",
"name": "word"
},
"value": "argument"
}, },
{ {
"type": "CHOICE", "type": "CHOICE",
@ -226,12 +230,8 @@
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "RENAME", "type": "SYMBOL",
"content": { "name": "value"
"type": "SYMBOL",
"name": "word"
},
"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": [
@ -298,25 +343,8 @@
{ {
"type": "REPEAT", "type": "REPEAT",
"content": { "content": {
"type": "CHOICE", "type": "SYMBOL",
"members": [ "name": "value"
{
"type": "RENAME",
"content": {
"type": "SYMBOL",
"name": "word"
},
"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", "type": "SYMBOL",
"content": { "name": "value"
"type": "SYMBOL",
"name": "word"
},
"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

File diff suppressed because it is too large Load Diff