Bladeren bron

Shell: Add support for the '!' POSIX pipeline prefix

This prefix simply inverts the exit code of the pipeline, which we
implement using the 'not' builtin.
Ali Mohammad Pur 2 jaren geleden
bovenliggende
commit
da7bf5f785
2 gewijzigde bestanden met toevoegingen van 26 en 3 verwijderingen
  1. 25 2
      Userland/Shell/PosixParser.cpp
  2. 1 1
      Userland/Shell/PosixParser.h

+ 25 - 2
Userland/Shell/PosixParser.cpp

@@ -769,15 +769,38 @@ ErrorOr<RefPtr<AST::Node>> Parser::parse_and_or()
 
 ErrorOr<RefPtr<AST::Node>> Parser::parse_pipeline()
 {
-    return parse_pipe_sequence();
+    while (peek().type == Token::Type::Newline)
+        skip();
+
+    auto is_negated = false;
+    if (peek().type == Token::Type::Bang) {
+        is_negated = true;
+        skip();
+    }
+
+    return parse_pipe_sequence(is_negated);
 }
 
-ErrorOr<RefPtr<AST::Node>> Parser::parse_pipe_sequence()
+ErrorOr<RefPtr<AST::Node>> Parser::parse_pipe_sequence(bool is_negated)
 {
     auto node = TRY(parse_command());
     if (!node)
         return RefPtr<AST::Node> {};
 
+    if (is_negated) {
+        if (is<AST::CastToCommand>(node.ptr())) {
+            node = make_ref_counted<AST::CastToCommand>(
+                node->position(),
+                make_ref_counted<AST::ListConcatenate>(
+                    node->position(),
+                    Vector<NonnullRefPtr<AST::Node>> {
+                        make_ref_counted<AST::BarewordLiteral>(
+                            node->position(),
+                            "not"_short_string),
+                        *static_cast<AST::CastToCommand&>(*node).inner() }));
+        }
+    }
+
     for (;;) {
         if (peek().type != Token::Type::Pipe)
             break;

+ 1 - 1
Userland/Shell/PosixParser.h

@@ -71,7 +71,7 @@ private:
     ErrorOr<RefPtr<AST::Node>> parse_list();
     ErrorOr<RefPtr<AST::Node>> parse_and_or();
     ErrorOr<RefPtr<AST::Node>> parse_pipeline();
-    ErrorOr<RefPtr<AST::Node>> parse_pipe_sequence();
+    ErrorOr<RefPtr<AST::Node>> parse_pipe_sequence(bool is_negated);
     ErrorOr<RefPtr<AST::Node>> parse_command();
     ErrorOr<RefPtr<AST::Node>> parse_compound_command();
     ErrorOr<RefPtr<AST::Node>> parse_subshell();