2017-07-14 19:28:54 +00:00
|
|
|
module.exports = grammar({
|
|
|
|
name: 'bash',
|
|
|
|
|
2017-07-14 23:11:35 +00:00
|
|
|
inline: $ => [$.statement],
|
2017-07-14 19:28:54 +00:00
|
|
|
|
2017-07-14 20:54:05 +00:00
|
|
|
externals: $ => [
|
2017-07-14 21:27:13 +00:00
|
|
|
$._simple_heredoc,
|
|
|
|
$._heredoc_beginning,
|
|
|
|
$._heredoc_middle,
|
|
|
|
$._heredoc_end
|
2017-07-14 20:54:05 +00:00
|
|
|
],
|
|
|
|
|
2017-07-14 21:34:49 +00:00
|
|
|
extras: $ => [
|
|
|
|
$.comment,
|
2017-07-14 21:39:28 +00:00
|
|
|
token(choice(/\s/, '\\\n')),
|
2017-07-14 21:34:49 +00:00
|
|
|
],
|
|
|
|
|
2017-07-14 19:28:54 +00:00
|
|
|
rules: {
|
2017-07-14 23:11:35 +00:00
|
|
|
program: $ => repeat($._terminated_statement),
|
2017-07-14 19:28:54 +00:00
|
|
|
|
2017-07-14 23:11:35 +00:00
|
|
|
_terminated_statement: $ => seq(
|
|
|
|
$.statement,
|
|
|
|
choice(';', ';;', '\n')
|
|
|
|
),
|
|
|
|
|
|
|
|
statement: $ => choice(
|
|
|
|
$.command,
|
|
|
|
$.while_statement,
|
|
|
|
$.pipeline,
|
|
|
|
$.list
|
|
|
|
),
|
|
|
|
|
|
|
|
while_statement: $ => seq(
|
|
|
|
'while',
|
|
|
|
$._terminated_statement,
|
|
|
|
$.do_group
|
|
|
|
),
|
|
|
|
|
|
|
|
do_group: $ => seq(
|
|
|
|
'do',
|
|
|
|
repeat($._terminated_statement),
|
|
|
|
'done'
|
2017-07-14 19:28:54 +00:00
|
|
|
),
|
|
|
|
|
2017-07-14 23:11:35 +00:00
|
|
|
command: $ => seq(
|
2017-07-14 19:43:42 +00:00
|
|
|
repeat(choice(
|
|
|
|
$.environment_variable_assignment,
|
|
|
|
$.file_redirect
|
|
|
|
)),
|
2017-07-14 19:28:54 +00:00
|
|
|
rename($.leading_word, 'command_name'),
|
|
|
|
optional(seq(
|
|
|
|
/\s+/,
|
2017-07-14 20:00:41 +00:00
|
|
|
repeat(choice(
|
|
|
|
rename($.word, 'argument'),
|
|
|
|
$.expansion,
|
|
|
|
$.operator_expansion
|
|
|
|
))
|
2017-07-14 19:43:42 +00:00
|
|
|
)),
|
2017-07-14 20:54:05 +00:00
|
|
|
repeat(choice(
|
|
|
|
$.file_redirect,
|
|
|
|
$.heredoc_redirect
|
|
|
|
))
|
2017-07-14 19:28:54 +00:00
|
|
|
),
|
|
|
|
|
2017-07-14 23:11:35 +00:00
|
|
|
pipeline: $ => prec.left(1, seq(
|
|
|
|
$.statement,
|
2017-07-14 19:28:54 +00:00
|
|
|
choice('|', '|&'),
|
2017-07-14 23:11:35 +00:00
|
|
|
$.statement
|
2017-07-14 19:28:54 +00:00
|
|
|
)),
|
|
|
|
|
|
|
|
list: $ => prec.left(seq(
|
2017-07-14 23:11:35 +00:00
|
|
|
$.statement,
|
|
|
|
choice('&&', '||'),
|
|
|
|
$.statement
|
2017-07-14 19:28:54 +00:00
|
|
|
)),
|
|
|
|
|
|
|
|
environment_variable_assignment: $ => seq(
|
|
|
|
rename($.leading_word, 'variable_name'),
|
|
|
|
'=',
|
|
|
|
rename($.word, 'argument')
|
|
|
|
),
|
|
|
|
|
2017-07-14 20:00:41 +00:00
|
|
|
expansion: $ => seq(
|
|
|
|
'$',
|
|
|
|
rename($.word, 'variable_name')
|
|
|
|
),
|
|
|
|
|
|
|
|
operator_expansion: $ => seq(
|
|
|
|
'${',
|
|
|
|
rename($.leading_word, 'variable_name'),
|
|
|
|
optional(seq(
|
|
|
|
choice(':', ':?', '='),
|
|
|
|
rename($.word, 'argument')
|
|
|
|
)),
|
|
|
|
'}'
|
|
|
|
),
|
|
|
|
|
2017-07-14 19:43:42 +00:00
|
|
|
file_redirect: $ => seq(
|
|
|
|
optional($.file_descriptor),
|
|
|
|
choice('<', '>', '<&', '>&'),
|
|
|
|
choice(
|
|
|
|
$.file_descriptor,
|
|
|
|
rename($.word, 'file_name')
|
|
|
|
)
|
|
|
|
),
|
|
|
|
|
2017-07-14 20:54:05 +00:00
|
|
|
heredoc_redirect: $ => seq(
|
|
|
|
choice('<<', '<<-'),
|
|
|
|
$.heredoc
|
|
|
|
),
|
|
|
|
|
2017-07-14 21:27:13 +00:00
|
|
|
heredoc: $ => choice(
|
|
|
|
$._simple_heredoc,
|
|
|
|
seq(
|
|
|
|
$._heredoc_beginning,
|
|
|
|
repeat(choice(
|
|
|
|
$.expansion,
|
|
|
|
$.operator_expansion,
|
|
|
|
$._heredoc_middle
|
|
|
|
)),
|
|
|
|
$._heredoc_end
|
|
|
|
)
|
|
|
|
),
|
|
|
|
|
2017-07-14 19:43:42 +00:00
|
|
|
file_descriptor: $ => token(prec(1, /\d+/)),
|
|
|
|
|
2017-07-14 21:39:28 +00:00
|
|
|
leading_word: $ => /[^\\\s#=|;:{}]+/,
|
2017-07-14 19:28:54 +00:00
|
|
|
|
2017-07-14 23:11:35 +00:00
|
|
|
word: $ => /[^#\\\s$<>{}&;]+/,
|
2017-07-14 21:34:49 +00:00
|
|
|
|
|
|
|
comment: $ => /#.*/,
|
2017-07-14 19:28:54 +00:00
|
|
|
}
|
|
|
|
});
|