parent
46cf157ad8
commit
bdaf31057b
|
@ -181,3 +181,25 @@ EOF
|
||||||
---
|
---
|
||||||
|
|
||||||
(program (redirected_statement (command (command_name (word))) (heredoc_redirect (heredoc_start))) (heredoc_body))
|
(program (redirected_statement (command (command_name (word))) (heredoc_redirect (heredoc_start))) (heredoc_body))
|
||||||
|
|
||||||
|
======================================
|
||||||
|
Quoted Heredocs
|
||||||
|
======================================
|
||||||
|
|
||||||
|
cat << 'EOF'
|
||||||
|
a=$b
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat << "EOF"
|
||||||
|
a=$b
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat << \EOF
|
||||||
|
EOF
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(program
|
||||||
|
(redirected_statement (command (command_name (word))) (heredoc_redirect (heredoc_start))) (heredoc_body)
|
||||||
|
(redirected_statement (command (command_name (word))) (heredoc_redirect (heredoc_start))) (heredoc_body (simple_expansion (variable_name)))
|
||||||
|
(redirected_statement (command (command_name (word))) (heredoc_redirect (heredoc_start))) (heredoc_body))
|
||||||
|
|
|
@ -318,6 +318,7 @@ module.exports = grammar({
|
||||||
repeat(choice(
|
repeat(choice(
|
||||||
$.expansion,
|
$.expansion,
|
||||||
$.simple_expansion,
|
$.simple_expansion,
|
||||||
|
$.command_substitution,
|
||||||
$._heredoc_body_middle
|
$._heredoc_body_middle
|
||||||
)),
|
)),
|
||||||
$._heredoc_body_end
|
$._heredoc_body_end
|
||||||
|
|
|
@ -10,7 +10,6 @@ examples/bash-it/completion/available/defaults.completion.bash
|
||||||
examples/bash-it/completion/available/docker.completion.bash
|
examples/bash-it/completion/available/docker.completion.bash
|
||||||
examples/bash-it/completion/available/tmux.completion.bash
|
examples/bash-it/completion/available/tmux.completion.bash
|
||||||
examples/bash-it/lib/preexec.bash
|
examples/bash-it/lib/preexec.bash
|
||||||
examples/bash-it/lib/composure.bash
|
|
||||||
examples/bash-it/themes/hawaii50/hawaii50.theme.bash
|
examples/bash-it/themes/hawaii50/hawaii50.theme.bash
|
||||||
examples/bash-it/themes/colors.theme.bash
|
examples/bash-it/themes/colors.theme.bash
|
||||||
examples/bash-it/themes/morris/morris.theme.bash
|
examples/bash-it/themes/morris/morris.theme.bash
|
||||||
|
|
|
@ -1269,6 +1269,10 @@
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "simple_expansion"
|
"name": "simple_expansion"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "command_substitution"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "_heredoc_body_middle"
|
"name": "_heredoc_body_middle"
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -32,14 +32,53 @@ struct Scanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned serialize(char *buffer) {
|
unsigned serialize(char *buffer) {
|
||||||
if (heredoc_delimiter.size() >= TREE_SITTER_SERIALIZATION_BUFFER_SIZE) return 0;
|
if (heredoc_delimiter.length() + 2 >= TREE_SITTER_SERIALIZATION_BUFFER_SIZE) return 0;
|
||||||
heredoc_delimiter.copy(buffer, heredoc_delimiter.length());
|
buffer[0] = heredoc_is_raw;
|
||||||
return heredoc_delimiter.length();
|
buffer[1] = started_heredoc;
|
||||||
|
heredoc_delimiter.copy(&buffer[2], heredoc_delimiter.length());
|
||||||
|
return heredoc_delimiter.length() + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deserialize(const char *buffer, unsigned length) {
|
void deserialize(const char *buffer, unsigned length) {
|
||||||
if (length == 0) heredoc_delimiter.clear();
|
if (length == 0) {
|
||||||
else heredoc_delimiter.assign(buffer, buffer + length);
|
heredoc_is_raw = false;
|
||||||
|
started_heredoc = false;
|
||||||
|
heredoc_delimiter.clear();
|
||||||
|
} else {
|
||||||
|
heredoc_is_raw = buffer[0];
|
||||||
|
started_heredoc = buffer[1];
|
||||||
|
heredoc_delimiter.assign(&buffer[2], &buffer[length]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool scan_heredoc_start(TSLexer *lexer) {
|
||||||
|
while (iswspace(lexer->lookahead)) skip(lexer);
|
||||||
|
|
||||||
|
lexer->result_symbol = HEREDOC_START;
|
||||||
|
heredoc_is_raw = lexer->lookahead == '\'';
|
||||||
|
started_heredoc = false;
|
||||||
|
heredoc_delimiter.clear();
|
||||||
|
|
||||||
|
if (lexer->lookahead == '\\') {
|
||||||
|
advance(lexer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t quote = 0;
|
||||||
|
if (heredoc_is_raw || lexer->lookahead == '"') {
|
||||||
|
quote = lexer->lookahead;
|
||||||
|
advance(lexer);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (iswalpha(lexer->lookahead)) {
|
||||||
|
heredoc_delimiter += lexer->lookahead;
|
||||||
|
advance(lexer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lexer->lookahead == quote) {
|
||||||
|
advance(lexer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return !heredoc_delimiter.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scan_heredoc_end_identifier(TSLexer *lexer) {
|
bool scan_heredoc_end_identifier(TSLexer *lexer) {
|
||||||
|
@ -57,8 +96,15 @@ struct Scanner {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
switch (lexer->lookahead) {
|
switch (lexer->lookahead) {
|
||||||
case '\0': {
|
case '\0': {
|
||||||
|
if (did_advance) {
|
||||||
|
heredoc_is_raw = false;
|
||||||
|
started_heredoc = false;
|
||||||
|
heredoc_delimiter.clear();
|
||||||
lexer->result_symbol = end_type;
|
lexer->result_symbol = end_type;
|
||||||
return did_advance;
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case '\\': {
|
case '\\': {
|
||||||
|
@ -69,14 +115,25 @@ struct Scanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
case '$': {
|
case '$': {
|
||||||
|
if (heredoc_is_raw) {
|
||||||
|
did_advance = true;
|
||||||
|
advance(lexer);
|
||||||
|
break;
|
||||||
|
} else if (did_advance) {
|
||||||
lexer->result_symbol = middle_type;
|
lexer->result_symbol = middle_type;
|
||||||
return did_advance;
|
started_heredoc = true;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case '\n': {
|
case '\n': {
|
||||||
did_advance = true;
|
did_advance = true;
|
||||||
advance(lexer);
|
advance(lexer);
|
||||||
if (scan_heredoc_end_identifier(lexer)) {
|
if (scan_heredoc_end_identifier(lexer)) {
|
||||||
|
heredoc_is_raw = false;
|
||||||
|
started_heredoc = false;
|
||||||
heredoc_delimiter.clear();
|
heredoc_delimiter.clear();
|
||||||
lexer->result_symbol = end_type;
|
lexer->result_symbol = end_type;
|
||||||
return true;
|
return true;
|
||||||
|
@ -122,25 +179,16 @@ struct Scanner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid_symbols[HEREDOC_BODY_BEGINNING] && !heredoc_delimiter.empty()) {
|
if (valid_symbols[HEREDOC_BODY_BEGINNING] && !heredoc_delimiter.empty() && !started_heredoc) {
|
||||||
return scan_heredoc_content(lexer, HEREDOC_BODY_BEGINNING, SIMPLE_HEREDOC_BODY);
|
return scan_heredoc_content(lexer, HEREDOC_BODY_BEGINNING, SIMPLE_HEREDOC_BODY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid_symbols[HEREDOC_BODY_MIDDLE] && !heredoc_delimiter.empty()) {
|
if (valid_symbols[HEREDOC_BODY_MIDDLE] && !heredoc_delimiter.empty() && started_heredoc) {
|
||||||
return scan_heredoc_content(lexer, HEREDOC_BODY_MIDDLE, HEREDOC_BODY_END);
|
return scan_heredoc_content(lexer, HEREDOC_BODY_MIDDLE, HEREDOC_BODY_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid_symbols[HEREDOC_START]) {
|
if (valid_symbols[HEREDOC_START]) {
|
||||||
while (iswspace(lexer->lookahead)) skip(lexer);
|
return scan_heredoc_start(lexer);
|
||||||
|
|
||||||
lexer->result_symbol = HEREDOC_START;
|
|
||||||
heredoc_delimiter.clear();
|
|
||||||
while (iswalpha(lexer->lookahead)) {
|
|
||||||
heredoc_delimiter += lexer->lookahead;
|
|
||||||
advance(lexer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return !heredoc_delimiter.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid_symbols[VARIABLE_NAME] || valid_symbols[FILE_DESCRIPTOR]) {
|
if (valid_symbols[VARIABLE_NAME] || valid_symbols[FILE_DESCRIPTOR]) {
|
||||||
|
@ -271,6 +319,8 @@ struct Scanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
string heredoc_delimiter;
|
string heredoc_delimiter;
|
||||||
|
bool heredoc_is_raw;
|
||||||
|
bool started_heredoc;
|
||||||
string current_leading_word;
|
string current_leading_word;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue