TokenStream.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. * Copyright (c) 2020-2021, the SerenityOS developers.
  3. * Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/Format.h>
  9. #include <AK/Vector.h>
  10. #include <LibWeb/CSS/Parser/Tokenizer.h>
  11. namespace Web::CSS::Parser {
  12. template<typename T>
  13. class TokenStream {
  14. public:
  15. class StateTransaction {
  16. public:
  17. explicit StateTransaction(TokenStream<T>& token_stream)
  18. : m_token_stream(token_stream)
  19. , m_saved_iterator_offset(token_stream.m_iterator_offset)
  20. {
  21. }
  22. ~StateTransaction()
  23. {
  24. if (!m_commit)
  25. m_token_stream.m_iterator_offset = m_saved_iterator_offset;
  26. }
  27. StateTransaction create_child() { return StateTransaction(*this); }
  28. void commit()
  29. {
  30. m_commit = true;
  31. if (m_parent)
  32. m_parent->commit();
  33. }
  34. private:
  35. explicit StateTransaction(StateTransaction& parent)
  36. : m_parent(&parent)
  37. , m_token_stream(parent.m_token_stream)
  38. , m_saved_iterator_offset(parent.m_token_stream.m_iterator_offset)
  39. {
  40. }
  41. StateTransaction* m_parent { nullptr };
  42. TokenStream<T>& m_token_stream;
  43. int m_saved_iterator_offset { 0 };
  44. bool m_commit { false };
  45. };
  46. explicit TokenStream(Vector<T> const& tokens)
  47. : m_tokens(tokens)
  48. , m_eof(make_eof())
  49. {
  50. }
  51. TokenStream(TokenStream<T> const&) = delete;
  52. ~TokenStream() = default;
  53. bool has_next_token()
  54. {
  55. return (size_t)(m_iterator_offset + 1) < m_tokens.size();
  56. }
  57. T const& next_token()
  58. {
  59. if (!has_next_token())
  60. return m_eof;
  61. ++m_iterator_offset;
  62. return m_tokens.at(m_iterator_offset);
  63. }
  64. T const& peek_token(int offset = 0)
  65. {
  66. if (!has_next_token())
  67. return m_eof;
  68. return m_tokens.at(m_iterator_offset + offset + 1);
  69. }
  70. T const& current_token()
  71. {
  72. if ((size_t)m_iterator_offset >= m_tokens.size())
  73. return m_eof;
  74. return m_tokens.at(m_iterator_offset);
  75. }
  76. void reconsume_current_input_token()
  77. {
  78. if (m_iterator_offset >= 0)
  79. --m_iterator_offset;
  80. }
  81. StateTransaction begin_transaction() { return StateTransaction(*this); }
  82. void skip_whitespace()
  83. {
  84. while (peek_token().is(Token::Type::Whitespace))
  85. next_token();
  86. }
  87. size_t token_count() const { return m_tokens.size(); }
  88. size_t remaining_token_count() const { return token_count() - m_iterator_offset - 1; }
  89. void dump_all_tokens()
  90. {
  91. dbgln("Dumping all tokens:");
  92. for (size_t i = 0; i < m_tokens.size(); ++i) {
  93. auto& token = m_tokens[i];
  94. if ((i - 1) == (size_t)m_iterator_offset)
  95. dbgln("-> {}", token.to_debug_string());
  96. else
  97. dbgln(" {}", token.to_debug_string());
  98. }
  99. }
  100. private:
  101. Vector<T> const& m_tokens;
  102. int m_iterator_offset { -1 };
  103. T make_eof()
  104. {
  105. if constexpr (IsSame<T, Token>) {
  106. return Tokenizer::create_eof_token();
  107. }
  108. if constexpr (IsSame<T, ComponentValue>) {
  109. return ComponentValue(Tokenizer::create_eof_token());
  110. }
  111. }
  112. T m_eof;
  113. };
  114. }