PosixParser.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. * Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <Shell/AST.h>
  8. #include <Shell/PosixLexer.h>
  9. namespace Shell::Posix {
  10. class Parser {
  11. public:
  12. Parser(StringView input, bool interactive = false)
  13. : m_lexer(input)
  14. , m_in_interactive_mode(interactive)
  15. , m_eof_token(Token::eof())
  16. {
  17. fill_token_buffer();
  18. }
  19. RefPtr<AST::Node> parse();
  20. RefPtr<AST::Node> parse_word_list();
  21. struct Error {
  22. DeprecatedString message;
  23. Optional<AST::Position> position;
  24. };
  25. auto& errors() const { return m_errors; }
  26. private:
  27. Optional<Token> next_expanded_token();
  28. Vector<Token> perform_expansions(Vector<Token> tokens);
  29. void fill_token_buffer();
  30. Token const& peek() const
  31. {
  32. if (eof())
  33. return m_eof_token;
  34. return m_token_buffer[m_token_index];
  35. }
  36. Token const& consume()
  37. {
  38. if (eof())
  39. return m_eof_token;
  40. return m_token_buffer[m_token_index++];
  41. }
  42. void skip()
  43. {
  44. if (eof())
  45. return;
  46. m_token_index++;
  47. }
  48. bool eof() const
  49. {
  50. return m_token_index == m_token_buffer.size() || m_token_buffer[m_token_index].type == Token::Type::Eof;
  51. }
  52. struct CaseItemsResult {
  53. Vector<AST::Position> pipe_positions;
  54. NonnullRefPtrVector<AST::Node> nodes;
  55. };
  56. RefPtr<AST::Node> parse_complete_command();
  57. RefPtr<AST::Node> parse_list();
  58. RefPtr<AST::Node> parse_and_or();
  59. RefPtr<AST::Node> parse_pipeline();
  60. RefPtr<AST::Node> parse_pipe_sequence();
  61. RefPtr<AST::Node> parse_command();
  62. RefPtr<AST::Node> parse_compound_command();
  63. RefPtr<AST::Node> parse_subshell();
  64. RefPtr<AST::Node> parse_compound_list();
  65. RefPtr<AST::Node> parse_term();
  66. RefPtr<AST::Node> parse_for_clause();
  67. RefPtr<AST::Node> parse_case_clause();
  68. CaseItemsResult parse_case_list();
  69. RefPtr<AST::Node> parse_if_clause();
  70. RefPtr<AST::Node> parse_while_clause();
  71. RefPtr<AST::Node> parse_until_clause();
  72. RefPtr<AST::Node> parse_function_definition();
  73. RefPtr<AST::Node> parse_function_body();
  74. RefPtr<AST::Node> parse_brace_group();
  75. RefPtr<AST::Node> parse_do_group();
  76. RefPtr<AST::Node> parse_simple_command();
  77. RefPtr<AST::Node> parse_prefix();
  78. RefPtr<AST::Node> parse_suffix();
  79. RefPtr<AST::Node> parse_io_redirect();
  80. RefPtr<AST::Node> parse_redirect_list();
  81. RefPtr<AST::Node> parse_io_file(AST::Position, Optional<int> fd);
  82. RefPtr<AST::Node> parse_io_here(AST::Position, Optional<int> fd);
  83. RefPtr<AST::Node> parse_word();
  84. template<typename... Ts>
  85. void error(Token const& token, CheckedFormatString<Ts...> fmt, Ts&&... args)
  86. {
  87. m_errors.append(Error {
  88. DeprecatedString::formatted(fmt.view(), forward<Ts>(args)...),
  89. token.position,
  90. });
  91. }
  92. Lexer m_lexer;
  93. bool m_in_interactive_mode { false };
  94. Vector<Token, 2> m_token_buffer;
  95. size_t m_token_index { 0 };
  96. Vector<Token> m_previous_token_buffer;
  97. Vector<Error> m_errors;
  98. Token m_eof_token;
  99. bool m_disallow_command_prefix { true };
  100. };
  101. }