#pragma once #include #include #include #include namespace DB { /** Parser operates on lazy stream of tokens. * It could do lookaheads of any depth. */ /** Used as an input for parsers. * All whitespace and comment tokens are transparently skipped. */ class Tokens { private: std::vector data; std::size_t last_accessed_index = 0; public: Tokens(const char * begin, const char * end, size_t max_query_size = 0, bool skip_insignificant = true); ALWAYS_INLINE inline const Token & operator[](size_t index) { assert(index < data.size()); last_accessed_index = std::max(last_accessed_index, index); return data[index]; } ALWAYS_INLINE inline const Token & max() { return data[last_accessed_index]; } }; /// To represent position in a token stream. class TokenIterator { private: Tokens * tokens; size_t index = 0; public: explicit TokenIterator(Tokens & tokens_) : tokens(&tokens_) {} ALWAYS_INLINE const Token & get() { return (*tokens)[index]; } ALWAYS_INLINE const Token & operator*() { return get(); } ALWAYS_INLINE const Token * operator->() { return &get(); } ALWAYS_INLINE TokenIterator & operator++() { ++index; return *this; } ALWAYS_INLINE TokenIterator & operator--() { --index; return *this; } ALWAYS_INLINE bool operator<(const TokenIterator & rhs) const { return index < rhs.index; } ALWAYS_INLINE bool operator<=(const TokenIterator & rhs) const { return index <= rhs.index; } ALWAYS_INLINE bool operator==(const TokenIterator & rhs) const { return index == rhs.index; } ALWAYS_INLINE bool operator!=(const TokenIterator & rhs) const { return index != rhs.index; } ALWAYS_INLINE bool isValid() { return get().type < TokenType::EndOfStream; } /// Rightmost token we had looked. ALWAYS_INLINE const Token & max() { return tokens->max(); } }; /// Returns positions of unmatched parentheses. using UnmatchedParentheses = std::vector; UnmatchedParentheses checkUnmatchedParentheses(TokenIterator begin); }