mirror of
https://github.com/RGBCube/serenity
synced 2025-05-16 19:55:06 +00:00
Shell: Allow a command sequence to be delimited by newlines
This commit is contained in:
parent
639c1a1737
commit
034be8e74c
3 changed files with 26 additions and 10 deletions
|
@ -102,6 +102,11 @@ static constexpr auto is_not(char c)
|
||||||
return [c](char ch) { return ch != c; };
|
return [c](char ch) { return ch != c; };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr auto is_any_of(StringView s)
|
||||||
|
{
|
||||||
|
return [s](char ch) { return s.contains(ch); };
|
||||||
|
}
|
||||||
|
|
||||||
static inline char to_byte(char a, char b)
|
static inline char to_byte(char a, char b)
|
||||||
{
|
{
|
||||||
char buf[3] { a, b, 0 };
|
char buf[3] { a, b, 0 };
|
||||||
|
@ -139,6 +144,15 @@ RefPtr<AST::Node> Parser::parse_sequence()
|
||||||
auto rule_start = push_start();
|
auto rule_start = push_start();
|
||||||
auto var_decls = parse_variable_decls();
|
auto var_decls = parse_variable_decls();
|
||||||
|
|
||||||
|
switch (peek()) {
|
||||||
|
case ';':
|
||||||
|
case '\n':
|
||||||
|
consume_while(is_any_of("\n;"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
auto pipe_seq = parse_pipe_sequence();
|
auto pipe_seq = parse_pipe_sequence();
|
||||||
if (!pipe_seq)
|
if (!pipe_seq)
|
||||||
return var_decls;
|
return var_decls;
|
||||||
|
@ -150,7 +164,8 @@ RefPtr<AST::Node> Parser::parse_sequence()
|
||||||
|
|
||||||
switch (peek()) {
|
switch (peek()) {
|
||||||
case ';':
|
case ';':
|
||||||
consume();
|
case '\n':
|
||||||
|
consume_while(is_any_of("\n;"));
|
||||||
if (auto expr = parse_sequence()) {
|
if (auto expr = parse_sequence()) {
|
||||||
return create<AST::Sequence>(move(pipe_seq), move(expr)); // Sequence
|
return create<AST::Sequence>(move(pipe_seq), move(expr)); // Sequence
|
||||||
}
|
}
|
||||||
|
@ -429,7 +444,7 @@ RefPtr<AST::Node> Parser::parse_expression()
|
||||||
return expr;
|
return expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (strchr("&|[]){} ;<>", starting_char) != nullptr)
|
if (strchr("&|[]){} ;<>\n", starting_char) != nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (isdigit(starting_char)) {
|
if (isdigit(starting_char)) {
|
||||||
|
@ -710,7 +725,7 @@ RefPtr<AST::Node> Parser::parse_bareword()
|
||||||
auto rule_start = push_start();
|
auto rule_start = push_start();
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
auto is_acceptable_bareword_character = [](char c) {
|
auto is_acceptable_bareword_character = [](char c) {
|
||||||
return strchr("\\\"'*$&#|()[]{} ?;<>", c) == nullptr;
|
return strchr("\\\"'*$&#|()[]{} ?;<>\n", c) == nullptr;
|
||||||
};
|
};
|
||||||
while (!at_end()) {
|
while (!at_end()) {
|
||||||
char ch = peek();
|
char ch = peek();
|
||||||
|
|
|
@ -100,11 +100,15 @@ private:
|
||||||
constexpr auto the_grammar = R"(
|
constexpr auto the_grammar = R"(
|
||||||
toplevel :: sequence?
|
toplevel :: sequence?
|
||||||
|
|
||||||
sequence :: variable_decls? pipe_sequence ';' sequence
|
sequence :: variable_decls? pipe_sequence terminator sequence
|
||||||
| variable_decls? pipe_sequence '&'
|
| variable_decls? pipe_sequence '&'
|
||||||
| variable_decls? pipe_sequence '&' '&' sequence
|
| variable_decls? pipe_sequence '&' '&' sequence
|
||||||
| variable_decls? pipe_sequence '|' '|' sequence
|
| variable_decls? pipe_sequence '|' '|' sequence
|
||||||
| variable_decls? pipe_sequence
|
| variable_decls? pipe_sequence
|
||||||
|
| variable_decls? terminator pipe_sequence
|
||||||
|
|
||||||
|
terminator :: ';'
|
||||||
|
| '\n'
|
||||||
|
|
||||||
variable_decls :: identifier '=' expression (' '+ variable_decls)? ' '*
|
variable_decls :: identifier '=' expression (' '+ variable_decls)? ' '*
|
||||||
| identifier '=' '(' pipe_sequence ')' (' '+ variable_decls)? ' '*
|
| identifier '=' '(' pipe_sequence ')' (' '+ variable_decls)? ' '*
|
||||||
|
@ -118,6 +122,7 @@ command :: redirection command
|
||||||
redirection :: number? '>'{1,2} ' '* string_composite
|
redirection :: number? '>'{1,2} ' '* string_composite
|
||||||
| number? '<' ' '* string_composite
|
| number? '<' ' '* string_composite
|
||||||
| number? '>' '&' number
|
| number? '>' '&' number
|
||||||
|
| number? '>' '&' '-'
|
||||||
|
|
||||||
list_expression :: ' '* expression (' '+ list_expression)?
|
list_expression :: ' '* expression (' '+ list_expression)?
|
||||||
|
|
||||||
|
|
|
@ -497,12 +497,8 @@ bool Shell::run_file(const String& filename)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto file = file_result.value();
|
auto file = file_result.value();
|
||||||
for (;;) {
|
auto data = file->read_all();
|
||||||
auto line = file->read_line(4096);
|
run_command(data);
|
||||||
if (line.is_null())
|
|
||||||
break;
|
|
||||||
run_command(String::copy(line, Chomp));
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void Shell::take_back_stdin()
|
void Shell::take_back_stdin()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue