summaryrefslogtreecommitdiff
path: root/Shell/Parser.cpp
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-10-25 10:42:03 +0330
committerAndreas Kling <kling@serenityos.org>2020-10-29 11:53:01 +0100
commit1a4ac3531f2cf23a5e74cc6d1b8fa24004b70e8d (patch)
tree847e12ba16d19049ab9e2bf9c36afa11d4d99ff0 /Shell/Parser.cpp
parent0801b1fada4d1eacdde3dc4aff04b9ee9eb73bf8 (diff)
downloadserenity-1a4ac3531f2cf23a5e74cc6d1b8fa24004b70e8d.zip
Shell: Allow parts of globs to be named in match expressions
This patchset allows a match expression to have a list of names for its glob parts, which are assigned to the matched values in the body of the match. For example, ```sh stuff=foobarblahblah/target_{1..30} for $stuff { match $it { */* as (dir sub) { echo "doing things with $sub in $dir" make -C $dir $sub # or whatever... } } } ``` With this, match expressions are now significantly more powerful!
Diffstat (limited to 'Shell/Parser.cpp')
-rw-r--r--Shell/Parser.cpp32
1 files changed, 30 insertions, 2 deletions
diff --git a/Shell/Parser.cpp b/Shell/Parser.cpp
index 464f5ff465..a6a59f5412 100644
--- a/Shell/Parser.cpp
+++ b/Shell/Parser.cpp
@@ -752,10 +752,12 @@ AST::MatchEntry Parser::parse_match_entry()
NonnullRefPtrVector<AST::Node> patterns;
Vector<AST::Position> pipe_positions;
+ Optional<Vector<String>> match_names;
+ Optional<AST::Position> match_as_position;
auto pattern = parse_match_pattern();
if (!pattern)
- return { {}, {}, create<AST::SyntaxError>("Expected a pattern in 'match' body") };
+ return { {}, {}, {}, {}, create<AST::SyntaxError>("Expected a pattern in 'match' body") };
patterns.append(pattern.release_nonnull());
@@ -782,6 +784,32 @@ AST::MatchEntry Parser::parse_match_entry()
consume_while(is_any_of(" \t\n"));
+ auto as_start_position = m_offset;
+ auto as_start_line = line();
+ if (expect("as")) {
+ match_as_position = AST::Position { as_start_position, m_offset, as_start_line, line() };
+ consume_while(is_any_of(" \t\n"));
+ if (!expect('(')) {
+ if (!error)
+ error = create<AST::SyntaxError>("Expected an explicit list of identifiers after a pattern 'as'");
+ } else {
+ match_names = Vector<String>();
+ for (;;) {
+ consume_while(is_whitespace);
+ auto name = consume_while(is_word_character);
+ if (name.is_empty())
+ break;
+ match_names.value().append(move(name));
+ }
+
+ if (!expect(')')) {
+ if (!error)
+ error = create<AST::SyntaxError>("Expected a close paren ')' to end the identifier list of pattern 'as'");
+ }
+ }
+ consume_while(is_any_of(" \t\n"));
+ }
+
if (!expect('{')) {
if (!error)
error = create<AST::SyntaxError>("Expected an open brace '{' to start a match entry body");
@@ -799,7 +827,7 @@ AST::MatchEntry Parser::parse_match_entry()
else if (error)
body = error;
- return { move(patterns), move(pipe_positions), move(body) };
+ return { move(patterns), move(match_names), move(match_as_position), move(pipe_positions), move(body) };
}
RefPtr<AST::Node> Parser::parse_match_pattern()