diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 174b63c4be..8aa5dcdee3 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -53,44 +53,99 @@ URL ParsingContext::complete_url(String const& addr) const return m_document ? m_document->url().complete_url(addr) : URL::create_with_url_or_path(addr); } +template +TokenStream::TokenStream(Vector const& tokens) + : m_tokens(tokens) + , m_eof(make_eof()) +{ +} + +template +TokenStream::~TokenStream() +{ +} + +template +bool TokenStream::has_next_token() +{ + return (size_t)(m_iterator_offset + 1) < m_tokens.size(); +} + +template +T const& TokenStream::peek_token() +{ + if (!has_next_token()) + return m_eof; + + return m_tokens.at(m_iterator_offset + 1); +} + +template +T const& TokenStream::next_token() +{ + if (!has_next_token()) + return m_eof; + + ++m_iterator_offset; + + return m_tokens.at(m_iterator_offset); +} + +template +T const& TokenStream::current_token() +{ + if ((size_t)m_iterator_offset >= m_tokens.size()) + return m_eof; + + return m_tokens.at(m_iterator_offset); +} + +template +void TokenStream::reconsume_current_input_token() +{ + VERIFY(m_iterator_offset >= 0); + --m_iterator_offset; +} + +template +void TokenStream::skip_whitespace() +{ + while (peek_token().is(Token::Type::Whitespace)) + next_token(); +} + +template<> +Token TokenStream::make_eof() +{ + return Tokenizer::create_eof_token(); +} + +template<> +StyleComponentValueRule TokenStream::make_eof() +{ + return StyleComponentValueRule(Tokenizer::create_eof_token()); +} + +template +void TokenStream::dump_all_tokens() +{ + dbgln("Dumping all tokens:"); + for (auto& token : m_tokens) + dbgln("{}", token.to_string()); +} + Parser::Parser(ParsingContext const& context, StringView const& input, String const& encoding) : m_context(context) , m_tokenizer(input, encoding) + , m_tokens(m_tokenizer.parse()) + , m_token_stream(TokenStream(m_tokens)) { - m_tokens = m_tokenizer.parse(); } Parser::~Parser() { } -Token Parser::peek_token() -{ - size_t next_offset = m_iterator_offset + 1; - - if (next_offset < m_tokens.size()) { - return m_tokens.at(next_offset); - } - - return m_tokens.at(m_iterator_offset); -} - -Token Parser::next_token() -{ - if (m_iterator_offset < (int)m_tokens.size() - 1) { - ++m_iterator_offset; - } - - auto token = m_tokens.at(m_iterator_offset); - - return token; -} - -Token Parser::current_token() -{ - return m_tokens.at(m_iterator_offset); -} - NonnullRefPtr Parser::parse_as_stylesheet() { auto parser_rules = consume_a_list_of_rules(true); @@ -440,18 +495,6 @@ Optional Parser::parse_single_selector(Vector return Selector(move(selectors)); } -void Parser::dump_all_tokens() -{ - dbgln("Dumping all tokens:"); - for (auto& token : m_tokens) - dbgln("{}", token.to_string()); -} - -void Parser::reconsume_current_input_token() -{ - --m_iterator_offset; -} - NonnullRefPtrVector Parser::consume_a_list_of_rules(bool top_level) { NonnullRefPtrVector rules; diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index d4257b479d..63764b252b 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -39,6 +39,30 @@ private: const DOM::Document* m_document { nullptr }; }; +template +class TokenStream { +public: + explicit TokenStream(Vector const&); + ~TokenStream(); + + bool has_next_token(); + T const& next_token(); + T const& peek_token(); + T const& current_token(); + void reconsume_current_input_token(); + + void skip_whitespace(); + + void dump_all_tokens(); + +private: + Vector const& m_tokens; + int m_iterator_offset { -1 }; + + T make_eof(); + T m_eof; +}; + class Parser { public: Parser(ParsingContext const&, StringView const& input, String const& encoding = "utf-8"); @@ -82,13 +106,11 @@ public: static Optional as_valid_border_style(String input) { return input; } static Optional as_valid_border_image_repeat(String input) { return input; } - void dump_all_tokens(); - private: - Token next_token(); - Token peek_token(); - Token current_token(); - void reconsume_current_input_token(); + Token next_token() { return m_token_stream.next_token(); } + Token peek_token() { return m_token_stream.peek_token(); } + Token current_token() { return m_token_stream.current_token(); } + void reconsume_current_input_token() { m_token_stream.reconsume_current_input_token(); } NonnullRefPtrVector consume_a_list_of_rules(bool top_level); NonnullRefPtr consume_an_at_rule(); @@ -106,7 +128,7 @@ private: Tokenizer m_tokenizer; Vector m_tokens; - int m_iterator_offset { -1 }; + TokenStream m_token_stream; }; } diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Tokenizer.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Tokenizer.cpp index 162720f260..c01dd8bad7 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Tokenizer.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Tokenizer.cpp @@ -269,6 +269,11 @@ Token Tokenizer::create_new_token(Token::Type type) return token; } +Token Tokenizer::create_eof_token() +{ + return create_new_token(Token::Type::EndOfFile); +} + Token Tokenizer::create_value_token(Token::Type type, String value) { Token token; diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Tokenizer.h b/Userland/Libraries/LibWeb/CSS/Parser/Tokenizer.h index 8baec2bc04..41872a64af 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Tokenizer.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Tokenizer.h @@ -70,6 +70,8 @@ public: [[nodiscard]] Vector parse(); + [[nodiscard]] static Token create_eof_token(); + private: [[nodiscard]] u32 next_code_point(); [[nodiscard]] u32 peek_code_point(size_t offset = 0) const;