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))))) (string (expansion (subscript (variable_name) (word)))))
(variable_assignment (variable_assignment
(variable_name) (variable_name)
(string (expansion (variable_name) (regex) (word) (word)))) (string (expansion (variable_name) (regex))))
(variable_assignment (variable_assignment
(variable_name) (variable_name)
(string (expansion (variable_name) (word) (word))))) (string (expansion (variable_name) (word) (word)))))

View File

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

104
src/grammar.json vendored
View File

@ -858,6 +858,23 @@
"value": "]]" "value": "]]"
} }
] ]
},
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "(("
},
{
"type": "SYMBOL",
"name": "_expression"
},
{
"type": "STRING",
"value": "))"
}
]
} }
] ]
}, },
@ -1031,11 +1048,11 @@
"members": [ "members": [
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "regex" "name": "_literal"
}, },
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "_literal" "name": "regex"
} }
] ]
} }
@ -1326,6 +1343,10 @@
"type": "SYMBOL", "type": "SYMBOL",
"name": "binary_expression" "name": "binary_expression"
}, },
{
"type": "SYMBOL",
"name": "postfix_expression"
},
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "parenthesized_expression" "name": "parenthesized_expression"
@ -1350,11 +1371,11 @@
"members": [ "members": [
{ {
"type": "STRING", "type": "STRING",
"value": "==" "value": "="
}, },
{ {
"type": "STRING", "type": "STRING",
"value": "=" "value": "=="
}, },
{ {
"type": "STRING", "type": "STRING",
@ -1364,6 +1385,22 @@
"type": "STRING", "type": "STRING",
"value": "!=" "value": "!="
}, },
{
"type": "STRING",
"value": "+"
},
{
"type": "STRING",
"value": "-"
},
{
"type": "STRING",
"value": "+="
},
{
"type": "STRING",
"value": "-="
},
{ {
"type": "STRING", "type": "STRING",
"value": "<" "value": "<"
@ -1372,6 +1409,14 @@
"type": "STRING", "type": "STRING",
"value": ">" "value": ">"
}, },
{
"type": "STRING",
"value": "<="
},
{
"type": "STRING",
"value": ">="
},
{ {
"type": "STRING", "type": "STRING",
"value": "||" "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": { "parenthesized_expression": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
@ -1874,13 +1941,16 @@
} }
}, },
{ {
"type": "ALIAS", "type": "CHOICE",
"content": { "members": [
"type": "SYMBOL", {
"name": "regex_without_right_brace" "type": "SYMBOL",
}, "name": "regex"
"named": true, },
"value": "regex" {
"type": "BLANK"
}
]
} }
] ]
}, },
@ -2114,14 +2184,6 @@
} }
} }
}, },
"regex": {
"type": "PATTERN",
"value": "([^\"\\s]|\\\\.)([^\\s]|\\\\.)*"
},
"regex_without_right_brace": {
"type": "PATTERN",
"value": "([^\"\\s}]|\\\\.)([^\\s}]|\\\\.)*"
},
"_terminator": { "_terminator": {
"type": "CHOICE", "type": "CHOICE",
"members": [ "members": [
@ -2192,6 +2254,10 @@
"type": "SYMBOL", "type": "SYMBOL",
"name": "variable_name" "name": "variable_name"
}, },
{
"type": "SYMBOL",
"name": "regex"
},
{ {
"type": "STRING", "type": "STRING",
"value": "}" "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, EMPTY_VALUE,
CONCAT, CONCAT,
VARIABLE_NAME, VARIABLE_NAME,
REGEX,
CLOSING_BRACE, CLOSING_BRACE,
CLOSING_BRACKET, CLOSING_BRACKET,
NEWLINE, NEWLINE,
@ -202,6 +203,63 @@ struct Scanner {
return false; 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; return false;
} }