Generalize case statement parsing
* Fix handling of '|' in case items * Don't require ;; for last case item Fixes #8
This commit is contained in:
parent
2a5b01b885
commit
87b3276186
|
@ -115,6 +115,10 @@ case "opt" in
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
case "$Z" in
|
||||||
|
ab*|cd*) ef
|
||||||
|
esac
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
(program
|
(program
|
||||||
|
@ -122,7 +126,10 @@ esac
|
||||||
(case_item (word)
|
(case_item (word)
|
||||||
(command (command_name (word)) (word)))
|
(command (command_name (word)) (word)))
|
||||||
(case_item (word)
|
(case_item (word)
|
||||||
(command (command_name (word)) (word)))))
|
(command (command_name (word)) (word))))
|
||||||
|
(case_statement (string (simple_expansion (variable_name)))
|
||||||
|
(case_item (word) (word)
|
||||||
|
(command (command_name (word))))))
|
||||||
|
|
||||||
===============================
|
===============================
|
||||||
Subshells
|
Subshells
|
||||||
|
|
13
grammar.js
13
grammar.js
|
@ -5,7 +5,7 @@ const SPECIAL_CHARACTERS = [
|
||||||
'\\[', '\\]',
|
'\\[', '\\]',
|
||||||
'(', ')',
|
'(', ')',
|
||||||
'`', '$',
|
'`', '$',
|
||||||
'&', ';',
|
'|', '&', ';',
|
||||||
'\\',
|
'\\',
|
||||||
'\\s',
|
'\\s',
|
||||||
'#',
|
'#',
|
||||||
|
@ -120,7 +120,10 @@ module.exports = grammar({
|
||||||
optional($._terminator),
|
optional($._terminator),
|
||||||
'in',
|
'in',
|
||||||
$._terminator,
|
$._terminator,
|
||||||
|
optional(seq(
|
||||||
repeat($.case_item),
|
repeat($.case_item),
|
||||||
|
alias($.last_case_item, $.case_item),
|
||||||
|
)),
|
||||||
'esac'
|
'esac'
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -132,6 +135,14 @@ module.exports = grammar({
|
||||||
';;'
|
';;'
|
||||||
),
|
),
|
||||||
|
|
||||||
|
last_case_item: $ => seq(
|
||||||
|
$._expression,
|
||||||
|
repeat(seq('|', $._expression)),
|
||||||
|
')',
|
||||||
|
repeat($._terminated_statement),
|
||||||
|
optional(';;')
|
||||||
|
),
|
||||||
|
|
||||||
function_definition: $ => seq(
|
function_definition: $ => seq(
|
||||||
choice(
|
choice(
|
||||||
seq('function', $.word, optional(seq('(', ')'))),
|
seq('function', $.word, optional(seq('(', ')'))),
|
||||||
|
|
|
@ -116,6 +116,26 @@
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "do_group"
|
"name": "do_group"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "REPEAT",
|
||||||
|
"content": {
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "file_redirect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "heredoc_redirect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "herestring_redirect"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -257,6 +277,12 @@
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "_terminator"
|
"name": "_terminator"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "REPEAT",
|
"type": "REPEAT",
|
||||||
"content": {
|
"content": {
|
||||||
|
@ -264,6 +290,22 @@
|
||||||
"name": "case_item"
|
"name": "case_item"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "ALIAS",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "last_case_item"
|
||||||
|
},
|
||||||
|
"named": true,
|
||||||
|
"value": "case_item"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": "esac"
|
"value": "esac"
|
||||||
|
@ -310,6 +352,54 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"last_case_item": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "_expression"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "REPEAT",
|
||||||
|
"content": {
|
||||||
|
"type": "SEQ",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": "|"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "_expression"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": ")"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "REPEAT",
|
||||||
|
"content": {
|
||||||
|
"type": "SYMBOL",
|
||||||
|
"name": "_terminated_statement"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "CHOICE",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"type": "STRING",
|
||||||
|
"value": ";;"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "BLANK"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"function_definition": {
|
"function_definition": {
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
"members": [
|
"members": [
|
||||||
|
@ -1130,15 +1220,10 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "CHOICE",
|
"type": "CHOICE",
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"type": "SEQ",
|
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "SYMBOL",
|
"type": "SYMBOL",
|
||||||
"name": "_expression"
|
"name": "_expression"
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "BLANK"
|
"type": "BLANK"
|
||||||
|
@ -1168,14 +1253,14 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"type": "REPEAT",
|
||||||
|
"content": {
|
||||||
"type": "CHOICE",
|
"type": "CHOICE",
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "SEQ",
|
"type": "SYMBOL",
|
||||||
"members": [
|
"name": "_expression"
|
||||||
{
|
},
|
||||||
"type": "CHOICE",
|
|
||||||
"members": [
|
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": ":"
|
"value": ":"
|
||||||
|
@ -1203,32 +1288,13 @@
|
||||||
{
|
{
|
||||||
"type": "STRING",
|
"type": "STRING",
|
||||||
"value": "-"
|
"value": "-"
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "CHOICE",
|
"type": "STRING",
|
||||||
"members": [
|
"value": "#"
|
||||||
{
|
|
||||||
"type": "SEQ",
|
|
||||||
"members": [
|
|
||||||
{
|
|
||||||
"type": "SYMBOL",
|
|
||||||
"name": "_expression"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "BLANK"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "BLANK"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1376,7 +1442,7 @@
|
||||||
"members": [
|
"members": [
|
||||||
{
|
{
|
||||||
"type": "PATTERN",
|
"type": "PATTERN",
|
||||||
"value": "[^'\"<>{}\\[\\]()`$&;\\\\\\s#]"
|
"value": "[^'\"<>{}\\[\\]()`$|&;\\\\\\s#]"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "SEQ",
|
"type": "SEQ",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -86,6 +86,7 @@ struct Scanner {
|
||||||
bool scan(TSLexer *lexer, const bool *valid_symbols) {
|
bool scan(TSLexer *lexer, const bool *valid_symbols) {
|
||||||
if (valid_symbols[CONCAT]) {
|
if (valid_symbols[CONCAT]) {
|
||||||
if (!(
|
if (!(
|
||||||
|
lexer->lookahead == 0 ||
|
||||||
iswspace(lexer->lookahead) ||
|
iswspace(lexer->lookahead) ||
|
||||||
lexer->lookahead == '>' ||
|
lexer->lookahead == '>' ||
|
||||||
lexer->lookahead == '<' ||
|
lexer->lookahead == '<' ||
|
||||||
|
@ -93,8 +94,8 @@ struct Scanner {
|
||||||
lexer->lookahead == '(' ||
|
lexer->lookahead == '(' ||
|
||||||
lexer->lookahead == ';' ||
|
lexer->lookahead == ';' ||
|
||||||
lexer->lookahead == '&' ||
|
lexer->lookahead == '&' ||
|
||||||
|
lexer->lookahead == '|' ||
|
||||||
lexer->lookahead == '`' ||
|
lexer->lookahead == '`' ||
|
||||||
lexer->lookahead == 0 ||
|
|
||||||
(lexer->lookahead == '}' && valid_symbols[CLOSING_BRACE]) ||
|
(lexer->lookahead == '}' && valid_symbols[CLOSING_BRACE]) ||
|
||||||
(lexer->lookahead == ']' && valid_symbols[CLOSING_BRACKET])
|
(lexer->lookahead == ']' && valid_symbols[CLOSING_BRACKET])
|
||||||
)) {
|
)) {
|
||||||
|
|
Loading…
Reference in New Issue