diff --git a/Userland/Shell/PosixLexer.cpp b/Userland/Shell/PosixLexer.cpp index a9ccbcbb58..716563f82e 100644 --- a/Userland/Shell/PosixLexer.cpp +++ b/Userland/Shell/PosixLexer.cpp @@ -642,20 +642,6 @@ ErrorOr 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::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::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 { diff --git a/Userland/Shell/PosixLexer.h b/Userland/Shell/PosixLexer.h index 8daaccaa8f..e82fc5ff28 100644 --- a/Userland/Shell/PosixLexer.h +++ b/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 m_state_change; diff --git a/Userland/Shell/PosixParser.cpp b/Userland/Shell/PosixParser.cpp index 00646cab46..dcdc1cfe32 100644 --- a/Userland/Shell/PosixParser.cpp +++ b/Userland/Shell/PosixParser.cpp @@ -188,7 +188,7 @@ void Parser::handle_heredoc_contents() ErrorOr> Parser::next_expanded_token(Optional 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> 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; }