Add double-paren expression

* Use the external scanner for regexes
* Add some missing operators

Fixes #22
Fixes #32
This commit is contained in:
Max Brunsfeld 2018-10-01 13:29:04 -07:00
parent 0123b9559f
commit 246bad66dd
6 changed files with 78723 additions and 73142 deletions

View File

@ -90,7 +90,7 @@ F="${G%% *}"
(string (expansion (subscript (variable_name) (word)))))
(variable_assignment
(variable_name)
(string (expansion (variable_name) (regex) (word) (word))))
(string (expansion (variable_name) (regex))))
(variable_assignment
(variable_name)
(string (expansion (variable_name) (word) (word)))))

View File

@ -34,6 +34,7 @@ module.exports = grammar({
$._empty_value,
$._concat,
$.variable_name, // Variable name followed by an operator like '=' or '+='
$.regex,
'}',
']',
'\n',
@ -229,7 +230,8 @@ module.exports = grammar({
test_command: $ => seq(
choice(
seq('[', $._expression, ']'),
seq('[[', $._expression, ']]')
seq('[[', $._expression, ']]'),
seq('((', $._expression, '))')
),
repeat(choice(
$.file_redirect,
@ -265,7 +267,7 @@ module.exports = grammar({
$._literal,
seq(
choice('=~', '=='),
choice($.regex, $._literal)
choice($._literal, $.regex)
)
)),
repeat(choice(
@ -338,13 +340,20 @@ module.exports = grammar({
$._literal,
$.unary_expression,
$.binary_expression,
$.postfix_expression,
$.parenthesized_expression
),
binary_expression: $ => prec.left(choice(
seq(
$._expression,
choice('==', '=', '=~', '!=', '<', '>', '||', '&&', $.test_operator),
choice(
'=', '==', '=~', '!=',
'+', '-', '+=', '-=',
'<', '>', '<=', '>=',
'||', '&&',
$.test_operator
),
$._expression
),
seq(
@ -359,6 +368,11 @@ module.exports = grammar({
$._expression
)),
postfix_expression: $ => seq(
$._expression,
choice('++', '--'),
),
parenthesized_expression: $ => seq(
'(',
$._expression,
@ -453,7 +467,7 @@ module.exports = grammar({
),
optional(seq(
token(prec(1, '/')),
alias($.regex_without_right_brace, $.regex)
optional($.regex)
)),
repeat(choice(
$._literal,
@ -488,10 +502,6 @@ module.exports = grammar({
test_operator: $ => token(prec(1, seq('-', /[a-zA-Z]+/))),
regex: $ => /([^"\s]|\\.)([^\s]|\\.)*/,
regex_without_right_brace: $ => /([^"\s}]|\\.)([^\s}]|\\.)*/,
_terminator: $ => choice(';', ';;', '\n', '&')
}
});

View File

@ -4,7 +4,6 @@ examples/bash-it/plugins/available/go.plugin.bash
examples/bash-it/install.sh
examples/bash-it/completion/available/svn.completion.bash
examples/bash-it/completion/available/docker-compose.completion.bash
examples/bash-it/completion/available/jboss7.completion.bash
examples/bash-it/completion/available/gh.completion.bash
examples/bash-it/completion/available/drush.completion.bash
examples/bash-it/completion/available/hub.completion.bash
@ -12,7 +11,6 @@ examples/bash-it/completion/available/docker-machine.completion.bash
examples/bash-it/completion/available/git.completion.bash
examples/bash-it/completion/available/defaults.completion.bash
examples/bash-it/completion/available/packer.completion.bash
examples/bash-it/completion/available/vault.completion.bash
examples/bash-it/completion/available/docker.completion.bash
examples/bash-it/completion/available/tmux.completion.bash
examples/bash-it/lib/preexec.bash

104
src/grammar.json vendored
View File

@ -858,6 +858,23 @@
"value": "]]"
}
]
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "(("
},
{
"type": "SYMBOL",
"name": "_expression"
},
{
"type": "STRING",
"value": "))"
}
]
}
]
},
@ -1031,11 +1048,11 @@
"members": [
{
"type": "SYMBOL",
"name": "regex"
"name": "_literal"
},
{
"type": "SYMBOL",
"name": "_literal"
"name": "regex"
}
]
}
@ -1326,6 +1343,10 @@
"type": "SYMBOL",
"name": "binary_expression"
},
{
"type": "SYMBOL",
"name": "postfix_expression"
},
{
"type": "SYMBOL",
"name": "parenthesized_expression"
@ -1350,11 +1371,11 @@
"members": [
{
"type": "STRING",
"value": "=="
"value": "="
},
{
"type": "STRING",
"value": "="
"value": "=="
},
{
"type": "STRING",
@ -1364,6 +1385,22 @@
"type": "STRING",
"value": "!="
},
{
"type": "STRING",
"value": "+"
},
{
"type": "STRING",
"value": "-"
},
{
"type": "STRING",
"value": "+="
},
{
"type": "STRING",
"value": "-="
},
{
"type": "STRING",
"value": "<"
@ -1372,6 +1409,14 @@
"type": "STRING",
"value": ">"
},
{
"type": "STRING",
"value": "<="
},
{
"type": "STRING",
"value": ">="
},
{
"type": "STRING",
"value": "||"
@ -1447,6 +1492,28 @@
]
}
},
"postfix_expression": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_expression"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "++"
},
{
"type": "STRING",
"value": "--"
}
]
}
]
},
"parenthesized_expression": {
"type": "SEQ",
"members": [
@ -1874,13 +1941,16 @@
}
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "regex_without_right_brace"
},
"named": true,
"value": "regex"
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "regex"
},
{
"type": "BLANK"
}
]
}
]
},
@ -2114,14 +2184,6 @@
}
}
},
"regex": {
"type": "PATTERN",
"value": "([^\"\\s]|\\\\.)([^\\s]|\\\\.)*"
},
"regex_without_right_brace": {
"type": "PATTERN",
"value": "([^\"\\s}]|\\\\.)([^\\s}]|\\\\.)*"
},
"_terminator": {
"type": "CHOICE",
"members": [
@ -2192,6 +2254,10 @@
"type": "SYMBOL",
"name": "variable_name"
},
{
"type": "SYMBOL",
"name": "regex"
},
{
"type": "STRING",
"value": "}"

151673
src/parser.c vendored

File diff suppressed because it is too large Load Diff

58
src/scanner.cc vendored
View File

@ -16,6 +16,7 @@ enum TokenType {
EMPTY_VALUE,
CONCAT,
VARIABLE_NAME,
REGEX,
CLOSING_BRACE,
CLOSING_BRACKET,
NEWLINE,
@ -202,6 +203,63 @@ struct Scanner {
return false;
}
if (valid_symbols[REGEX]) {
while (iswspace(lexer->lookahead)) skip(lexer);
if (
lexer->lookahead != '"' &&
lexer->lookahead != '\'' &&
lexer->lookahead != '$'
) {
struct State {
bool done;
uint32_t paren_depth;
uint32_t bracket_depth;
uint32_t brace_depth;
};
lexer->mark_end(lexer);
State state = {false, 0, 0, 0};
while (!state.done) {
switch (lexer->lookahead) {
case '\0':
return false;
case '(':
state.paren_depth++;
break;
case '[':
state.bracket_depth++;
break;
case '{':
state.bracket_depth++;
break;
case ')':
if (state.paren_depth == 0) state.done = true;
state.paren_depth--;
break;
case ']':
if (state.bracket_depth == 0) state.done = true;
state.bracket_depth--;
break;
case '}':
if (state.brace_depth == 0) state.done = true;
state.brace_depth--;
break;
}
if (!state.done) {
bool was_space = iswspace(lexer->lookahead);
advance(lexer);
if (!was_space) lexer->mark_end(lexer);
}
}
lexer->result_symbol = REGEX;
return true;
}
}
return false;
}