Prechádzať zdrojové kódy

Shell: Treat '(' and '{' as operators in POSIX mode

Ali Mohammad Pur 1 rok pred
rodič
commit
764ea6104e

+ 15 - 15
Userland/Shell/PosixLexer.cpp

@@ -642,20 +642,6 @@ ErrorOr<Lexer::ReductionResult> Lexer::reduce_start()
         };
     }
 
-    if (!m_state.escaping && is_part_of_operator(""sv, m_lexer.peek())) {
-        auto tokens = TRY(Token::maybe_from_state(m_state));
-        m_state.buffer.clear();
-        m_state.buffer.append(consume());
-        m_state.expansions.clear();
-        m_state.position.start_offset = m_state.position.end_offset;
-        m_state.position.start_line = m_state.position.end_line;
-
-        return ReductionResult {
-            .tokens = move(tokens),
-            .next_reduction = Reduction::Operator,
-        };
-    }
-
     if (!m_state.escaping && consume_specific('\'')) {
         m_state.buffer.append('\'');
         return ReductionResult {
@@ -708,7 +694,7 @@ ErrorOr<Lexer::ReductionResult> Lexer::reduce_start()
         };
     }
 
-    if (!m_state.escaping && is_any_of("})"sv)(m_lexer.peek())) {
+    if (!m_state.escaping && m_state.in_skip_mode && is_any_of("})"sv)(m_lexer.peek())) {
         // That's an eof for us.
         return ReductionResult {
             .tokens = {},
@@ -716,6 +702,20 @@ ErrorOr<Lexer::ReductionResult> Lexer::reduce_start()
         };
     }
 
+    if (!m_state.escaping && is_part_of_operator(""sv, m_lexer.peek())) {
+        auto tokens = TRY(Token::maybe_from_state(m_state));
+        m_state.buffer.clear();
+        m_state.buffer.append(consume());
+        m_state.expansions.clear();
+        m_state.position.start_offset = m_state.position.end_offset;
+        m_state.position.start_line = m_state.position.end_line;
+
+        return ReductionResult {
+            .tokens = move(tokens),
+            .next_reduction = Reduction::Operator,
+        };
+    }
+
     m_state.escaping = false;
     m_state.buffer.append(consume());
     return ReductionResult {

+ 10 - 0
Userland/Shell/PosixLexer.h

@@ -197,6 +197,7 @@ struct State {
     StringBuilder buffer {};
     Reduction previous_reduction { Reduction::Start };
     bool escaping { false };
+    bool in_skip_mode { false };
     AST::Position position {
         .start_offset = 0,
         .end_offset = 0,
@@ -320,6 +321,14 @@ struct Token {
             return Token::Type::Less;
         if (name == "\n"sv)
             return Token::Type::Newline;
+        if (name == "("sv)
+            return Token::Type::OpenParen;
+        if (name == "{"sv)
+            return Token::Type::OpenBrace;
+        if (name == ")"sv)
+            return Token::Type::CloseParen;
+        if (name == "}"sv)
+            return Token::Type::CloseBrace;
 
         return {};
     }
@@ -431,6 +440,7 @@ private:
         explicit SkipTokens(Lexer& lexer)
             : m_state_change(lexer.m_state, lexer.m_state)
         {
+            lexer.m_state.in_skip_mode = true;
         }
 
         TemporaryChange<State> m_state_change;

+ 3 - 2
Userland/Shell/PosixParser.cpp

@@ -188,7 +188,7 @@ void Parser::handle_heredoc_contents()
 
 ErrorOr<Optional<Token>> Parser::next_expanded_token(Optional<Reduction> starting_reduction)
 {
-    while (m_token_buffer.find_if([](auto& token) { return token.type == Token::Type::Eof; }).is_end()) {
+    while (m_token_buffer.is_empty() || m_token_buffer.last().type != Token::Type::Eof) {
         auto tokens = TRY(m_lexer.batch_next(starting_reduction));
         auto expanded = perform_expansions(move(tokens));
         m_token_buffer.extend(expanded);
@@ -1749,7 +1749,8 @@ ErrorOr<RefPtr<AST::Node>> Parser::parse_word()
             case '\'':
                 if (in_quote == Quote::Single) {
                     in_quote = Quote::None;
-                    TRY(append_string_literal(string.substring_view(*run_start, i - *run_start)));
+                    if (run_start.has_value())
+                        TRY(append_string_literal(string.substring_view(*run_start, i - *run_start)));
                     run_start = i + 1;
                     continue;
                 }