2017-07-14 19:28:54 +00:00
|
|
|
module.exports = grammar({
|
|
|
|
name: 'bash',
|
|
|
|
|
|
|
|
inline: $ => [$.control_operator],
|
|
|
|
|
|
|
|
rules: {
|
|
|
|
program: $ => repeat($.command),
|
|
|
|
|
|
|
|
command: $ => seq(
|
|
|
|
choice(
|
|
|
|
$.simple_command,
|
|
|
|
$.pipeline,
|
|
|
|
$.list
|
|
|
|
),
|
|
|
|
$.control_operator
|
|
|
|
),
|
|
|
|
|
|
|
|
simple_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+/,
|
|
|
|
repeat(rename($.word, 'argument'))
|
2017-07-14 19:43:42 +00:00
|
|
|
)),
|
|
|
|
repeat(
|
|
|
|
$.file_redirect
|
|
|
|
)
|
2017-07-14 19:28:54 +00:00
|
|
|
),
|
|
|
|
|
|
|
|
pipeline: $ => prec.left(seq(
|
|
|
|
$.simple_command,
|
|
|
|
choice('|', '|&'),
|
|
|
|
$.simple_command
|
|
|
|
)),
|
|
|
|
|
|
|
|
list: $ => prec.left(seq(
|
|
|
|
choice(
|
|
|
|
$.simple_command,
|
|
|
|
$.list,
|
|
|
|
$.pipeline
|
|
|
|
),
|
|
|
|
choice('&&', ';'),
|
|
|
|
choice(
|
|
|
|
$.simple_command,
|
|
|
|
$.pipeline
|
|
|
|
)
|
|
|
|
)),
|
|
|
|
|
|
|
|
environment_variable_assignment: $ => seq(
|
|
|
|
rename($.leading_word, 'variable_name'),
|
|
|
|
'=',
|
|
|
|
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')
|
|
|
|
)
|
|
|
|
),
|
|
|
|
|
|
|
|
file_descriptor: $ => token(prec(1, /\d+/)),
|
|
|
|
|
2017-07-14 19:28:54 +00:00
|
|
|
leading_word: $ => /[^\s=|;]+/,
|
|
|
|
|
2017-07-14 19:43:42 +00:00
|
|
|
word: $ => /[^\s<>&]+/,
|
2017-07-14 19:28:54 +00:00
|
|
|
|
|
|
|
control_operator: $ => choice(
|
|
|
|
'\n',
|
|
|
|
';;'
|
|
|
|
)
|
|
|
|
}
|
|
|
|
});
|