tree-sitter-bash/grammar.js

267 lines
4.8 KiB
JavaScript
Raw Normal View History

2017-07-14 19:28:54 +00:00
module.exports = grammar({
name: 'bash',
2017-07-16 05:13:55 +00:00
inline: $ => [
$.statement,
$.terminator,
$.expression,
$._variable_name
],
2017-07-14 19:28:54 +00:00
2017-07-14 20:54:05 +00:00
externals: $ => [
$._simple_heredoc,
$._heredoc_beginning,
$._heredoc_middle,
$._heredoc_end,
2017-07-15 00:41:14 +00:00
$.file_descriptor,
$._empty_value
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,
2017-07-14 23:29:28 +00:00
$.terminator
2017-07-14 23:11:35 +00:00
),
2017-07-16 05:13:55 +00:00
// Statements
2017-07-14 23:11:35 +00:00
statement: $ => choice(
$.environment_variable_assignment,
2017-07-14 23:11:35 +00:00
$.command,
$.bracket_command,
2017-07-15 00:51:06 +00:00
$.for_statement,
2017-07-14 23:11:35 +00:00
$.while_statement,
2017-07-14 23:18:46 +00:00
$.if_statement,
2017-07-14 23:29:28 +00:00
$.case_statement,
2017-07-14 23:11:35 +00:00
$.pipeline,
2017-07-15 00:32:55 +00:00
$.list,
2017-07-15 00:35:51 +00:00
$.subshell,
$.function_definition
2017-07-14 23:11:35 +00:00
),
2017-07-15 00:51:06 +00:00
for_statement: $ => seq(
'for',
2017-07-16 05:13:55 +00:00
$.word,
2017-07-15 00:51:06 +00:00
'in',
$._terminated_statement,
$.do_group
),
2017-07-14 23:11:35 +00:00
while_statement: $ => seq(
'while',
$._terminated_statement,
$.do_group
),
2017-07-14 23:29:28 +00:00
do_group: $ => seq(
'do',
repeat($._terminated_statement),
'done'
),
2017-07-14 23:18:46 +00:00
if_statement: $ => seq(
'if',
$._terminated_statement,
'then',
repeat($._terminated_statement),
repeat($.elif_clause),
optional($.else_clause),
'fi'
),
elif_clause: $ => seq(
'elif',
$._terminated_statement,
'then',
repeat($._terminated_statement)
),
else_clause: $ => seq(
'else',
repeat($._terminated_statement)
),
2017-07-14 23:29:28 +00:00
case_statement: $ => seq(
'case',
2017-07-16 05:13:55 +00:00
$.expression,
2017-07-14 23:29:28 +00:00
optional($.terminator),
'in',
$.terminator,
repeat($.case_item),
'esac'
),
case_item: $ => seq(
2017-07-16 05:13:55 +00:00
$.expression,
2017-07-14 23:29:28 +00:00
')',
2017-07-14 23:11:35 +00:00
repeat($._terminated_statement),
2017-07-15 00:32:55 +00:00
';;'
2017-07-14 19:28:54 +00:00
),
2017-07-15 00:35:51 +00:00
function_definition: $ => seq(
optional('function'),
rename($.leading_word, 'command_name'),
'(',
')',
2017-07-16 05:13:55 +00:00
$.compound_statement
2017-07-15 00:35:51 +00:00
),
2017-07-16 05:13:55 +00:00
compound_statement: $ => seq(
2017-07-15 00:35:51 +00:00
'{',
repeat($._terminated_statement),
'}'
),
2017-07-16 05:13:55 +00:00
subshell: $ => seq(
'(',
repeat($._terminated_statement),
')'
),
pipeline: $ => prec.left(1, seq(
$.statement,
choice('|', '|&'),
$.statement
)),
list: $ => prec.left(seq(
$.statement,
choice('&&', '||'),
$.statement
)),
bracket_command: $ => choice(
2017-07-16 05:13:55 +00:00
seq('[', repeat1($.expression), ']'),
seq('[[', repeat1($.expression), ']]')
),
2017-07-16 05:13:55 +00:00
// Commands
command: $ => prec.left(seq(
2017-07-14 19:43:42 +00:00
repeat(choice(
$.environment_variable_assignment,
$.file_redirect
)),
2017-07-15 00:32:55 +00:00
choice(
rename(choice($.leading_word), 'command_name'),
':',
2017-07-16 05:13:55 +00:00
$.string,
$.raw_string,
2017-07-15 00:51:06 +00:00
$.command_substitution
2017-07-15 00:32:55 +00:00
),
2017-07-14 19:28:54 +00:00
optional(seq(
/\s+/,
2017-07-16 05:13:55 +00:00
repeat($.expression)
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
)),
environment_variable_assignment: $ => seq(
rename($.leading_word, 'variable_name'),
'=',
2017-07-15 00:41:14 +00:00
choice(
2017-07-16 05:13:55 +00:00
$.expression,
2017-07-15 00:41:14 +00:00
$._empty_value
)
),
2017-07-16 05:13:55 +00:00
file_redirect: $ => seq(
optional($.file_descriptor),
choice('<', '>', '>>', '&>', '&>>', '<&', '>&'),
$.expression
),
heredoc_redirect: $ => seq(
choice('<<', '<<-'),
$.heredoc
),
heredoc: $ => choice(
$._simple_heredoc,
seq(
$._heredoc_beginning,
repeat(choice(
$.expansion,
$.simple_expansion,
$._heredoc_middle
)),
$._heredoc_end
)
),
// Expressions
expression: $ => choice(
$.word,
$.string,
$.raw_string,
$.expansion,
2017-07-16 05:13:55 +00:00
$.simple_expansion,
$.command_substitution
2017-07-14 19:28:54 +00:00
),
2017-07-16 05:13:55 +00:00
string: $ => seq(
'"',
repeat(choice(
2017-07-16 05:13:55 +00:00
/[^"$]+/,
$.expansion,
2017-07-16 05:13:55 +00:00
$.simple_expansion,
$.command_substitution
)),
'"'
),
2017-07-16 05:13:55 +00:00
raw_string: $ => /'[^']*'/,
2017-07-16 05:13:55 +00:00
simple_expansion: $ => seq(
2017-07-14 20:00:41 +00:00
'$',
2017-07-15 00:32:55 +00:00
choice(
2017-07-16 05:13:55 +00:00
rename($.simple_variable_name, 'variable_name'),
$.special_variable_name
2017-07-15 00:32:55 +00:00
)
2017-07-14 20:00:41 +00:00
),
2017-07-16 05:13:55 +00:00
expansion: $ => seq(
2017-07-14 20:00:41 +00:00
'${',
2017-07-16 05:13:55 +00:00
$._variable_name,
2017-07-14 20:00:41 +00:00
optional(seq(
2017-07-15 00:32:55 +00:00
choice(':', ':?', '=', ':-'),
2017-07-16 05:13:55 +00:00
$.expression
2017-07-14 20:00:41 +00:00
)),
'}'
),
2017-07-16 05:13:55 +00:00
_variable_name: $ => choice(
rename($.leading_word, 'variable_name'),
$.special_variable_name
),
2017-07-16 05:13:55 +00:00
command_substitution: $ => choice(
seq('$(', $.command, ')'),
seq('`', $.command, '`')
2017-07-14 19:43:42 +00:00
),
2017-07-16 05:13:55 +00:00
leading_word: $ => /[^`"\\\s#=|;:{}()]+/,
2017-07-14 20:54:05 +00:00
2017-07-16 05:13:55 +00:00
word: $ => /[^"`#\\\s$<>{}&;()]+/,
2017-07-16 05:13:55 +00:00
comment: $ => /#.*/,
2017-07-14 19:28:54 +00:00
2017-07-16 05:13:55 +00:00
simple_variable_name: $ => /\w+/,
2017-07-14 21:34:49 +00:00
2017-07-16 05:13:55 +00:00
special_variable_name: $ => choice('*', '@', '#', '?', '-', '$', '!', '0', '_'),
2017-07-14 23:29:28 +00:00
2017-07-15 00:32:55 +00:00
terminator: $ => choice(';', ';;', '\n', '&'),
2017-07-14 19:28:54 +00:00
}
});