2017-07-12 04:17:05 +00:00
|
|
|
#pragma once
|
|
|
|
|
2021-11-29 09:47:21 +00:00
|
|
|
#include <Core/Defines.h>
|
2017-07-12 04:17:05 +00:00
|
|
|
#include <Parsers/Lexer.h>
|
|
|
|
|
2021-11-29 09:47:21 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2017-07-12 04:17:05 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
/** Parser operates on lazy stream of tokens.
|
|
|
|
* It could do lookaheads of any depth.
|
|
|
|
*/
|
|
|
|
|
2017-07-12 19:20:57 +00:00
|
|
|
/** Used as an input for parsers.
|
|
|
|
* All whitespace and comment tokens are transparently skipped.
|
|
|
|
*/
|
2017-07-12 04:17:05 +00:00
|
|
|
class Tokens
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
std::vector<Token> data;
|
|
|
|
Lexer lexer;
|
|
|
|
|
|
|
|
public:
|
2018-03-26 19:41:55 +00:00
|
|
|
Tokens(const char * begin, const char * end, size_t max_query_size = 0) : lexer(begin, end, max_query_size) {}
|
2017-07-12 04:17:05 +00:00
|
|
|
|
|
|
|
const Token & operator[] (size_t index)
|
|
|
|
{
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (index < data.size())
|
|
|
|
return data[index];
|
|
|
|
|
2017-07-13 01:12:13 +00:00
|
|
|
if (!data.empty() && data.back().isEnd())
|
2017-07-12 04:17:05 +00:00
|
|
|
return data.back();
|
|
|
|
|
|
|
|
Token token = lexer.nextToken();
|
|
|
|
|
2017-07-13 01:12:13 +00:00
|
|
|
if (token.isSignificant())
|
2017-07-12 04:17:05 +00:00
|
|
|
data.emplace_back(token);
|
|
|
|
}
|
|
|
|
}
|
2017-07-12 20:45:27 +00:00
|
|
|
|
|
|
|
const Token & max()
|
|
|
|
{
|
|
|
|
if (data.empty())
|
|
|
|
return (*this)[0];
|
|
|
|
return data.back();
|
|
|
|
}
|
2017-07-12 04:17:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/// To represent position in a token stream.
|
|
|
|
class TokenIterator
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
Tokens * tokens;
|
|
|
|
size_t index = 0;
|
|
|
|
|
|
|
|
public:
|
2019-08-03 11:02:40 +00:00
|
|
|
explicit TokenIterator(Tokens & tokens_) : tokens(&tokens_) {}
|
2017-07-12 04:17:05 +00:00
|
|
|
|
2021-11-29 09:47:21 +00:00
|
|
|
ALWAYS_INLINE const Token & get() { return (*tokens)[index]; }
|
|
|
|
ALWAYS_INLINE const Token & operator*() { return get(); }
|
|
|
|
ALWAYS_INLINE const Token * operator->() { return &get(); }
|
2017-07-12 04:17:05 +00:00
|
|
|
|
2021-11-29 09:47:21 +00:00
|
|
|
ALWAYS_INLINE TokenIterator & operator++()
|
|
|
|
{
|
|
|
|
++index;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
ALWAYS_INLINE TokenIterator & operator--()
|
|
|
|
{
|
|
|
|
--index;
|
|
|
|
return *this;
|
|
|
|
}
|
2017-07-12 19:20:57 +00:00
|
|
|
|
2021-11-29 09:47:21 +00:00
|
|
|
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; }
|
2017-07-12 04:17:05 +00:00
|
|
|
|
2021-11-29 09:47:21 +00:00
|
|
|
ALWAYS_INLINE bool isValid() { return get().type < TokenType::EndOfStream; }
|
2017-07-12 20:45:27 +00:00
|
|
|
|
2017-07-13 01:12:13 +00:00
|
|
|
/// Rightmost token we had looked.
|
2021-11-29 09:47:21 +00:00
|
|
|
ALWAYS_INLINE const Token & max() { return tokens->max(); }
|
2017-07-12 04:17:05 +00:00
|
|
|
};
|
|
|
|
|
2017-07-13 04:20:56 +00:00
|
|
|
|
|
|
|
/// Returns positions of unmatched parentheses.
|
2017-07-13 05:38:02 +00:00
|
|
|
using UnmatchedParentheses = std::vector<Token>;
|
2021-01-31 23:10:41 +00:00
|
|
|
UnmatchedParentheses checkUnmatchedParentheses(TokenIterator begin);
|
2017-07-13 04:20:56 +00:00
|
|
|
|
2017-07-12 04:17:05 +00:00
|
|
|
}
|