mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-23 16:12:01 +00:00
dbms: development.
This commit is contained in:
parent
1677287005
commit
8fc01e90d7
18
dbms/include/DB/Columns/Columns.h
Normal file
18
dbms/include/DB/Columns/Columns.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef DBMS_COLUMNS_COLUMNS_H
|
||||
#define DBMS_COLUMNS_COLUMNS_H
|
||||
|
||||
#include <vector>
|
||||
#include <Poco/SharedPtr.h>
|
||||
#include <DB/Columns/IColumn.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using Poco::SharedPtr;
|
||||
|
||||
typedef std::vector<SharedPtr<IColumn> > Columns;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
#ifndef DBMS_CORE_ICOLUMN_H
|
||||
#define DBMS_CORE_ICOLUMN_H
|
||||
#ifndef DBMS_COLUMNS_ICOLUMN_H
|
||||
#define DBMS_COLUMNS_ICOLUMN_H
|
||||
|
||||
#include <Poco/SharedPtr.h>
|
||||
|
||||
|
15
dbms/include/DB/Core/ColumnNumbers.h
Normal file
15
dbms/include/DB/Core/ColumnNumbers.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef DBMS_CORE_COLUMN_NUMBERS_H
|
||||
#define DBMS_CORE_COLUMN_NUMBERS_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
typedef std::vector<size_t> ColumnNumbers;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -42,6 +42,8 @@ namespace ErrorCodes
|
||||
CANNOT_READ_COMPRESSED_CHUNK,
|
||||
ATTEMPT_TO_READ_AFTER_EOF,
|
||||
CANNOT_READ_ALL_DATA,
|
||||
TOO_MUCH_ARGUMENTS_FOR_FUNCTION,
|
||||
TOO_LESS_ARGUMENTS_FOR_FUNCTION,
|
||||
};
|
||||
}
|
||||
|
||||
|
29
dbms/include/DB/Parsers/ASTExpressionList.h
Normal file
29
dbms/include/DB/Parsers/ASTExpressionList.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef DBMS_PARSERS_ASTEXPRESSIONLIST_H
|
||||
#define DBMS_PARSERS_ASTEXPRESSIONLIST_H
|
||||
|
||||
#include <DB/Parsers/IAST.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using Poco::SharedPtr;
|
||||
|
||||
|
||||
/** Список выражений типа "a, b + c, f(d)"
|
||||
*/
|
||||
class ASTExpressionList : public IAST
|
||||
{
|
||||
public:
|
||||
StringRange range;
|
||||
ASTs children;
|
||||
|
||||
ASTExpressionList(StringRange range_) : range(range_) {}
|
||||
|
||||
/** Получить кусок текста, откуда был получен этот элемент. */
|
||||
StringRange getRange() { return range; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
29
dbms/include/DB/Parsers/ASTFunction.h
Normal file
29
dbms/include/DB/Parsers/ASTFunction.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef DBMS_PARSERS_ASTFUNCTION_H
|
||||
#define DBMS_PARSERS_ASTFUNCTION_H
|
||||
|
||||
#include <DB/Parsers/IAST.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Применение функции или оператора
|
||||
*/
|
||||
class ASTFunction : public IAST
|
||||
{
|
||||
public:
|
||||
StringRange range;
|
||||
/// имя функции
|
||||
String name;
|
||||
/// параметры
|
||||
ASTPtr arguments;
|
||||
|
||||
ASTFunction(StringRange range_) : range(range_) {}
|
||||
|
||||
/** Получить кусок текста, откуда был получен этот элемент. */
|
||||
StringRange getRange() { return range; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
27
dbms/include/DB/Parsers/ASTIdentifier.h
Normal file
27
dbms/include/DB/Parsers/ASTIdentifier.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef DBMS_PARSERS_ASTIDENTIFIER_H
|
||||
#define DBMS_PARSERS_ASTIDENTIFIER_H
|
||||
|
||||
#include <DB/Parsers/IAST.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Идентификатор (столбца или алиас, или именованый элемент кортежа)
|
||||
*/
|
||||
class ASTIdentifier : public IAST
|
||||
{
|
||||
public:
|
||||
StringRange range;
|
||||
/// имя
|
||||
String name;
|
||||
|
||||
ASTIdentifier(StringRange range_, const String & name_) : range(range_), name(name_) {}
|
||||
|
||||
/** Получить кусок текста, откуда был получен этот элемент. */
|
||||
StringRange getRange() { return range; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
28
dbms/include/DB/Parsers/ASTLiteral.h
Normal file
28
dbms/include/DB/Parsers/ASTLiteral.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef DBMS_PARSERS_ASTLITERAL_H
|
||||
#define DBMS_PARSERS_ASTLITERAL_H
|
||||
|
||||
#include <DB/Core/Field.h>
|
||||
#include <DB/Parsers/IAST.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Литерал (атомарный) - число, строка, NULL
|
||||
*/
|
||||
class ASTLiteral : public IAST
|
||||
{
|
||||
public:
|
||||
StringRange range;
|
||||
/// значение
|
||||
Field value;
|
||||
|
||||
ASTLiteral(StringRange range_, const Field & value_) : range(range_), value(value_) {}
|
||||
|
||||
/** Получить кусок текста, откуда был получен этот элемент. */
|
||||
StringRange getRange() { return range; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
27
dbms/include/DB/Parsers/ASTSelectQuery.h
Normal file
27
dbms/include/DB/Parsers/ASTSelectQuery.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef DBMS_PARSERS_ASTSELECTQUERY_H
|
||||
#define DBMS_PARSERS_ASTSELECTQUERY_H
|
||||
|
||||
#include <DB/Parsers/IAST.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
/** SELECT запрос
|
||||
*/
|
||||
class ASTSelectQuery : public IAST
|
||||
{
|
||||
public:
|
||||
StringRange range;
|
||||
ASTPtr select, from, where, group, having, order, limit;
|
||||
|
||||
ASTSelectQuery(StringRange range_) : range(range_) {}
|
||||
|
||||
/** Получить кусок текста, откуда был получен этот элемент. */
|
||||
StringRange getRange() { return range; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
169
dbms/include/DB/Parsers/CommonParsers.h
Normal file
169
dbms/include/DB/Parsers/CommonParsers.h
Normal file
@ -0,0 +1,169 @@
|
||||
#ifndef DBMS_PARSERS_COMMONPARSERS_H
|
||||
#define DBMS_PARSERS_COMMONPARSERS_H
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <DB/Parsers/IParserBase.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using Poco::SharedPtr;
|
||||
|
||||
|
||||
/** если прямо сейчас не s, то ошибка
|
||||
*/
|
||||
class ParserString : public IParserBase
|
||||
{
|
||||
private:
|
||||
const String & s;
|
||||
public:
|
||||
ParserString(const String & s_) : s(s_) {}
|
||||
protected:
|
||||
String getName() { return s; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
if (static_cast<ssize_t>(s.size()) < end - pos || std::strncmp(pos, s.data(), s.size()))
|
||||
return false;
|
||||
else
|
||||
{
|
||||
pos += s.size();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** если сейчас словарный символ - то ошибка
|
||||
* понимается только латиница
|
||||
*/
|
||||
class ParserNotWordCharOrEnd : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "non-word character"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
if (pos == end)
|
||||
return true;
|
||||
|
||||
if ((*pos >= 'a' && *pos <= 'z') || (*pos >= 'A' && *pos <= 'Z') || (*pos >= '0' && *pos <= '9') || *pos == '_')
|
||||
return false;
|
||||
|
||||
++pos;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** пробельные символы
|
||||
*/
|
||||
class ParserWhiteSpace : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "white space"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
Pos begin = pos;
|
||||
while (*pos == ' ' || *pos == '\t' || *pos == '\n' || *pos == '\r' || *pos == '\f')
|
||||
++pos;
|
||||
|
||||
return pos != begin;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ParserCStyleComment : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "C-style comment"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
if (end - pos >= 4 && pos[0] == '/' && pos[1] == '*')
|
||||
{
|
||||
pos += 2;
|
||||
while (end - pos >= 2 && pos[0] != '*' && pos[1] != '/')
|
||||
++pos;
|
||||
|
||||
if (end - pos < 2)
|
||||
{
|
||||
expected = "closing of C-style comment '*/'";
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos += 2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ParserSQLStyleComment : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "SQL-style comment"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
if (end - pos >= 2 && pos[0] == '-' && pos[1] == '-')
|
||||
{
|
||||
pos += 2;
|
||||
while (pos != end && *pos != '\n')
|
||||
++pos;
|
||||
|
||||
if (pos != end)
|
||||
++pos;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** комментарии '--' или c-style
|
||||
*/
|
||||
class ParserComment : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "comment"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
ParserCStyleComment p1;
|
||||
ParserSQLStyleComment p2;
|
||||
|
||||
return p1.ignore(pos, end, expected)
|
||||
|| p2.ignore(pos, end, expected);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ParserWhiteSpaceOrComments : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "white space or comments"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
ParserWhiteSpace p1;
|
||||
ParserComment p2;
|
||||
|
||||
bool res = false;
|
||||
while (p1.ignore(pos, end, expected) || p2.ignore(pos, end, expected))
|
||||
res = true;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
124
dbms/include/DB/Parsers/ExpressionElementParsers.h
Normal file
124
dbms/include/DB/Parsers/ExpressionElementParsers.h
Normal file
@ -0,0 +1,124 @@
|
||||
#ifndef DBMS_PARSERS_EXPRESSIONELEMENTPARSERS_H
|
||||
#define DBMS_PARSERS_EXPRESSIONELEMENTPARSERS_H
|
||||
|
||||
#include <DB/Parsers/IParserBase.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
class ParserArray : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "array"; }
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
|
||||
};
|
||||
|
||||
|
||||
/** Если в скобках выражение из одного элемента - возвращает в node этот элемент;
|
||||
* иначе возвращает функцию tuple от содержимого скобок.
|
||||
*/
|
||||
class ParserParenthesisExpression : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "expression in parenthesis"; }
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
|
||||
};
|
||||
|
||||
|
||||
/** Идентификатор, например, x_yz123
|
||||
*/
|
||||
class ParserIdentifier : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "identifier"; }
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
|
||||
};
|
||||
|
||||
|
||||
/** Функция, например, f(x, y, z)
|
||||
*/
|
||||
class ParserFunction : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "function"; }
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
|
||||
};
|
||||
|
||||
|
||||
/** NULL.
|
||||
*/
|
||||
class ParserNull : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "NULL"; }
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
|
||||
};
|
||||
|
||||
|
||||
/** Число.
|
||||
*/
|
||||
class ParserNumber : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "number"; }
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
|
||||
};
|
||||
|
||||
|
||||
/** Строка в одинарных кавычках.
|
||||
*/
|
||||
class ParserStringLiteral : public IParserBase
|
||||
{
|
||||
private:
|
||||
inline char parseEscapeSequence(char c)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case 'b':
|
||||
return '\b';
|
||||
case 'f':
|
||||
return '\f';
|
||||
case 'n':
|
||||
return '\n';
|
||||
case 'r':
|
||||
return '\r';
|
||||
case 't':
|
||||
return '\t';
|
||||
case '0':
|
||||
return '\0';
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
String getName() { return "string literal"; }
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
|
||||
};
|
||||
|
||||
|
||||
/** Литерал - одно из: NULL, UInt64, Int64, Float64, String.
|
||||
*/
|
||||
class ParserLiteral : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "literal"; }
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
|
||||
};
|
||||
|
||||
|
||||
/** Элемент выражения - одно из: выражение в круглых скобках, массив, литерал, функция, идентификатор.
|
||||
*/
|
||||
class ParserExpressionElement : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "element of expression"; }
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,119 +0,0 @@
|
||||
#ifndef DBMS_PARSERS_EXPRESSION_H
|
||||
#define DBMS_PARSERS_EXPRESSION_H
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
#include <boost/variant/recursive_wrapper.hpp>
|
||||
#include <boost/fusion/include/adapt_struct.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <DB/Core/Types.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Expression - это выражение, которое может стоять в запросе между SELECT и FROM
|
||||
* Здесь представлен парсер этого выражения (пока без операторов).
|
||||
* PS. Код довольно сложный :(
|
||||
*/
|
||||
|
||||
/** Типы данных, которые образуются автоматически в результате парсинга.
|
||||
* Они должны быть в отдельном или глобальном namespace из-за BOOST_FUSION_ADAPT_STRUCT.
|
||||
*
|
||||
* spirit может собирать типы данных - результаты парсинга (атрибуты) автоматически,
|
||||
* или можно использовать свои типы и заполнять их вручную с помощью семантических действий.
|
||||
* Здесь используется вариант - автоматически.
|
||||
* (но стоит на будущее иметь ввиду, что его очень сложно заставить скомпилироваться)
|
||||
*/
|
||||
namespace ExpressionGrammarTypes
|
||||
{
|
||||
/// с тем, какой конкретно тип у числа, будем разбираться потом
|
||||
typedef Float64 NumberConstant; /// 1, -1, 0.1
|
||||
typedef String StringConstant; /// 'abc', 'ab\'c', 'abc\\'
|
||||
typedef Null NullConstant; /// NULL, null, NuLl
|
||||
|
||||
typedef boost::variant<
|
||||
NumberConstant,
|
||||
StringConstant,
|
||||
NullConstant> Constant;
|
||||
|
||||
typedef String Name; /// x, sum, width
|
||||
|
||||
struct Function; /// forward declaration для рекурсии
|
||||
typedef boost::variant<
|
||||
boost::recursive_wrapper<Function>,
|
||||
Constant,
|
||||
Name> Node; /// элемент выражения
|
||||
|
||||
typedef std::vector<Node> Expression; /// выражение - набор элементов через запятую
|
||||
|
||||
struct Function /// f(x), sum(a, 10), concat('a', 'bc')
|
||||
{
|
||||
Name name; /// sum
|
||||
Expression args; /// a, 10
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** Необходимо, чтобы struct Function был совместим с boost::fusion::vector (он же boost::tuple),
|
||||
* который образуется автоматически при парсинге.
|
||||
* Должно быть в глобальном namespace.
|
||||
*/
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
DB::ExpressionGrammarTypes::Function,
|
||||
(DB::ExpressionGrammarTypes::Name, name)
|
||||
(DB::ExpressionGrammarTypes::Expression, args)
|
||||
)
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace ascii = boost::spirit::ascii;
|
||||
|
||||
|
||||
/** Грамматика */
|
||||
template <typename Iterator>
|
||||
struct ExpressionGrammar : qi::grammar<Iterator, ExpressionGrammarTypes::Expression(), ascii::space_type>
|
||||
{
|
||||
ExpressionGrammar() : ExpressionGrammar::base_type(expression)
|
||||
{
|
||||
using qi::lexeme;
|
||||
using qi::raw;
|
||||
using qi::alpha;
|
||||
using qi::alnum;
|
||||
using qi::double_;
|
||||
using qi::eps;
|
||||
using qi::no_case;
|
||||
using qi::char_;
|
||||
using qi::_val;
|
||||
using qi::_1;
|
||||
|
||||
expression %= node % ',';
|
||||
node %= function | constant | name;
|
||||
name %= raw[lexeme[alpha >> -*(alnum | '_')]];
|
||||
constant %= number | string | null;
|
||||
function %= name >> '(' >> expression >> ')';
|
||||
number %= double_;
|
||||
null = eps[_val = boost::none] >> no_case["NULL"];
|
||||
string %= raw[lexeme['\'' >> *((char_ - (char_('\\') | '\'')) | (char_('\'') >> char_)) >> '\'']];
|
||||
}
|
||||
|
||||
qi::rule<Iterator, ExpressionGrammarTypes::Expression(), ascii::space_type> expression;
|
||||
qi::rule<Iterator, ExpressionGrammarTypes::Node(), ascii::space_type> node;
|
||||
qi::rule<Iterator, ExpressionGrammarTypes::Constant(), ascii::space_type> constant;
|
||||
qi::rule<Iterator, ExpressionGrammarTypes::Name(), ascii::space_type> name;
|
||||
qi::rule<Iterator, ExpressionGrammarTypes::Function(), ascii::space_type> function;
|
||||
qi::rule<Iterator, ExpressionGrammarTypes::NumberConstant(), ascii::space_type> number;
|
||||
qi::rule<Iterator, ExpressionGrammarTypes::StringConstant(), ascii::space_type> string;
|
||||
qi::rule<Iterator, ExpressionGrammarTypes::NullConstant(), ascii::space_type> null;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
280
dbms/include/DB/Parsers/ExpressionListParsers.h
Normal file
280
dbms/include/DB/Parsers/ExpressionListParsers.h
Normal file
@ -0,0 +1,280 @@
|
||||
#ifndef DBMS_PARSERS_EXPRESSIONLISTPARSERS_H
|
||||
#define DBMS_PARSERS_EXPRESSIONLISTPARSERS_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <boost/assign/list_of.hpp>
|
||||
|
||||
#include <DB/Parsers/IParserBase.h>
|
||||
#include <DB/Parsers/CommonParsers.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Оператор и соответствующая ему функция. Например, "+" -> "plus" */
|
||||
typedef std::map<String, String> Operators_t;
|
||||
|
||||
|
||||
/** Выражение с инфиксным бинарным лево-ассоциативным оператором.
|
||||
* Например, a + b - c + d.
|
||||
* NOTE: если оператор словесный (например, OR), то после него не требуется границы слова.
|
||||
* то есть, можно написать a = b ORx = y.
|
||||
*/
|
||||
class ParserLeftAssociativeBinaryOperatorList : public IParserBase
|
||||
{
|
||||
private:
|
||||
const Operators_t & operators;
|
||||
ParserPtr elem_parser;
|
||||
|
||||
public:
|
||||
/** operators_ - допустимые операторы и соответствующие им функции
|
||||
*/
|
||||
ParserLeftAssociativeBinaryOperatorList(const Operators_t & operators_, ParserPtr elem_parser_)
|
||||
: operators(operators_), elem_parser(elem_parser_)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
String getName() { return "list, delimited by binary operators"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
|
||||
};
|
||||
|
||||
|
||||
/** Выражение с префиксным унарным оператором.
|
||||
* Например, NOT x.
|
||||
* NOTE: если оператор словесный (например, NOT), то после него не требуется границы слова.
|
||||
* то есть, можно написать NOTx.
|
||||
*/
|
||||
class ParserPrefixUnaryOperatorExpression : public IParserBase
|
||||
{
|
||||
private:
|
||||
const Operators_t & operators;
|
||||
ParserPtr elem_parser;
|
||||
|
||||
public:
|
||||
/** operators_ - допустимые операторы и соответствующие им функции
|
||||
*/
|
||||
ParserPrefixUnaryOperatorExpression(const Operators_t & operators_, ParserPtr elem_parser_)
|
||||
: operators(operators_), elem_parser(elem_parser_)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
String getName() { return "expression with prefix unary operator"; }
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
|
||||
};
|
||||
|
||||
|
||||
class ParserAccessExpression : public IParserBase
|
||||
{
|
||||
private:
|
||||
ParserPtr elem_parser;
|
||||
ParserLeftAssociativeBinaryOperatorList operator_parser;
|
||||
public:
|
||||
ParserAccessExpression();
|
||||
|
||||
protected:
|
||||
String getName() { return "acess expression"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
return operator_parser.parse(pos, end, node, expected);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ParserUnaryMinusExpression : public IParserBase
|
||||
{
|
||||
private:
|
||||
ParserPtr elem_parser;
|
||||
ParserPrefixUnaryOperatorExpression operator_parser;
|
||||
public:
|
||||
ParserUnaryMinusExpression()
|
||||
: elem_parser(new ParserAccessExpression),
|
||||
operator_parser(boost::assign::map_list_of("-", "negate"), elem_parser)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
String getName() { return "unary minus expression"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
return operator_parser.parse(pos, end, node, expected);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ParserMultiplicativeExpression : public IParserBase
|
||||
{
|
||||
private:
|
||||
ParserPtr elem_parser;
|
||||
ParserLeftAssociativeBinaryOperatorList operator_parser;
|
||||
public:
|
||||
ParserMultiplicativeExpression()
|
||||
: elem_parser(new ParserUnaryMinusExpression),
|
||||
operator_parser(boost::assign::map_list_of
|
||||
("*", "multiply")
|
||||
("/", "divide")
|
||||
("%", "modulo"),
|
||||
elem_parser)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
String getName() { return "multiplicative expression"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
return operator_parser.parse(pos, end, node, expected);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ParserAdditiveExpression : public IParserBase
|
||||
{
|
||||
private:
|
||||
ParserPtr elem_parser;
|
||||
ParserLeftAssociativeBinaryOperatorList operator_parser;
|
||||
public:
|
||||
ParserAdditiveExpression()
|
||||
: elem_parser(new ParserMultiplicativeExpression),
|
||||
operator_parser(boost::assign::map_list_of
|
||||
("+", "plus")
|
||||
("-", "minus"),
|
||||
elem_parser)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
String getName() { return "additive expression"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
return operator_parser.parse(pos, end, node, expected);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ParserComparisonExpression : public IParserBase
|
||||
{
|
||||
private:
|
||||
ParserPtr elem_parser;
|
||||
ParserLeftAssociativeBinaryOperatorList operator_parser;
|
||||
public:
|
||||
ParserComparisonExpression()
|
||||
: elem_parser(new ParserAdditiveExpression),
|
||||
operator_parser(boost::assign::map_list_of
|
||||
("==", "equals")
|
||||
("!=", "notEquals")
|
||||
("<>", "notEquals")
|
||||
("<=", "lessOrEquals")
|
||||
(">=", "greaterOrEquals")
|
||||
("<", "less")
|
||||
(">", "greater")
|
||||
("=", "equals"),
|
||||
elem_parser)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
String getName() { return "comparison expression"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
return operator_parser.parse(pos, end, node, expected);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ParserLogicalNotExpression : public IParserBase
|
||||
{
|
||||
private:
|
||||
ParserPtr elem_parser;
|
||||
ParserPrefixUnaryOperatorExpression operator_parser;
|
||||
public:
|
||||
ParserLogicalNotExpression()
|
||||
: elem_parser(new ParserComparisonExpression),
|
||||
operator_parser(boost::assign::map_list_of("NOT", "not"), elem_parser)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
String getName() { return "logical-NOT expression"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
return operator_parser.parse(pos, end, node, expected);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ParserLogicalAndExpression : public IParserBase
|
||||
{
|
||||
private:
|
||||
ParserPtr elem_parser;
|
||||
ParserLeftAssociativeBinaryOperatorList operator_parser;
|
||||
public:
|
||||
ParserLogicalAndExpression()
|
||||
: elem_parser(new ParserLogicalNotExpression),
|
||||
operator_parser(boost::assign::map_list_of("AND", "and"), elem_parser)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
String getName() { return "logical-AND expression"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
return operator_parser.parse(pos, end, node, expected);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ParserLogicalOrExpression : public IParserBase
|
||||
{
|
||||
private:
|
||||
ParserPtr elem_parser;
|
||||
ParserLeftAssociativeBinaryOperatorList operator_parser;
|
||||
public:
|
||||
ParserLogicalOrExpression()
|
||||
: elem_parser(new ParserLogicalAndExpression),
|
||||
operator_parser(boost::assign::map_list_of("OR", "or"), elem_parser)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
String getName() { return "logical-OR expression"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
return operator_parser.parse(pos, end, node, expected);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Список выражений, разделённых запятыми, возможно пустой. */
|
||||
class ParserExpressionList : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "list of expressions"; }
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
|
||||
};
|
||||
|
||||
|
||||
class ParserNotEmptyExpressionList : public IParserBase
|
||||
{
|
||||
private:
|
||||
ParserExpressionList nested_parser;
|
||||
protected:
|
||||
String getName() { return "not empty list of expressions"; }
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
33
dbms/include/DB/Parsers/IAST.h
Normal file
33
dbms/include/DB/Parsers/IAST.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef DBMS_PARSERS_IAST_H
|
||||
#define DBMS_PARSERS_IAST_H
|
||||
|
||||
#include <list>
|
||||
#include <Poco/SharedPtr.h>
|
||||
|
||||
#include <DB/Core/Types.h>
|
||||
#include <DB/Parsers/StringRange.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using Poco::SharedPtr;
|
||||
|
||||
|
||||
/** Элемент синтаксического дерева (в дальнейшем - направленного ациклического графа с элементами семантики)
|
||||
*/
|
||||
class IAST
|
||||
{
|
||||
public:
|
||||
/** Получить кусок текста, откуда был получен этот элемент. */
|
||||
virtual StringRange getRange() = 0;
|
||||
virtual ~IAST() {}
|
||||
};
|
||||
|
||||
|
||||
typedef Poco::SharedPtr<IAST> ASTPtr;
|
||||
typedef std::list<ASTPtr> ASTs;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
71
dbms/include/DB/Parsers/IParser.h
Normal file
71
dbms/include/DB/Parsers/IParser.h
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef DBMS_PARSERS_IPARSER_H
|
||||
#define DBMS_PARSERS_IPARSER_H
|
||||
|
||||
#include <list>
|
||||
#include <Poco/SharedPtr.h>
|
||||
|
||||
#include <DB/Core/Types.h>
|
||||
#include <DB/Parsers/IAST.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using Poco::SharedPtr;
|
||||
|
||||
|
||||
/** Интерфейс для классов-парсеров
|
||||
*/
|
||||
class IParser
|
||||
{
|
||||
public:
|
||||
typedef const char * Pos;
|
||||
|
||||
/** Получить текст о том, что парсит этот парсер. */
|
||||
virtual String getName() = 0;
|
||||
|
||||
/** Распарсить кусок текста с позиции pos, но не дальше конца строки (end - позиция после конца строки),
|
||||
* переместить указатель pos на максимальное место, до которого удалось распарсить,
|
||||
* вернуть в случае успеха true и результат в node, если он нужен, иначе false,
|
||||
* в expected записать, что ожидалось в максимальной позиции,
|
||||
* до которой удалось распарсить, если парсинг был неуспешным,
|
||||
* или что парсит этот парсер, если парсинг был успешным.
|
||||
* Везде предполагается, что строка, в которую входит диапазон [begin, end) 0-terminated.
|
||||
*/
|
||||
virtual bool parse(Pos & pos, Pos end, ASTPtr & node, String & expected) = 0;
|
||||
|
||||
bool ignore(Pos & pos, Pos end, String & expected)
|
||||
{
|
||||
ASTPtr ignore_node;
|
||||
return parse(pos, end, ignore_node, expected);
|
||||
}
|
||||
|
||||
bool ignore(Pos & pos, Pos end)
|
||||
{
|
||||
String expected;
|
||||
return ignore(pos, end, expected);
|
||||
}
|
||||
|
||||
/** То же самое, но не двигать позицию и не записывать результат в node.
|
||||
*/
|
||||
bool check(Pos & pos, Pos end, String & expected)
|
||||
{
|
||||
Pos begin = pos;
|
||||
ASTPtr node;
|
||||
if (!parse(pos, end, node, expected))
|
||||
{
|
||||
pos = begin;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual ~IParser() {}
|
||||
};
|
||||
|
||||
typedef SharedPtr<IParser> ParserPtr;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
30
dbms/include/DB/Parsers/IParserBase.h
Normal file
30
dbms/include/DB/Parsers/IParserBase.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef DBMS_PARSERS_IPARSERBASE_H
|
||||
#define DBMS_PARSERS_IPARSERBASE_H
|
||||
|
||||
#include <list>
|
||||
#include <Poco/SharedPtr.h>
|
||||
|
||||
#include <DB/Core/Types.h>
|
||||
#include <DB/Parsers/IParser.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Базовый класс для большинства парсеров
|
||||
*/
|
||||
class IParserBase : public IParser
|
||||
{
|
||||
public:
|
||||
bool parse(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
expected = getName();
|
||||
return parseImpl(pos, end, node, expected);
|
||||
}
|
||||
protected:
|
||||
virtual bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
51
dbms/include/DB/Parsers/ParserSelectQuery.h
Normal file
51
dbms/include/DB/Parsers/ParserSelectQuery.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef DBMS_PARSERS_PARSERSELECTQUERY_H
|
||||
#define DBMS_PARSERS_PARSERSELECTQUERY_H
|
||||
|
||||
#include <DB/Parsers/ASTSelectQuery.h>
|
||||
#include <DB/Parsers/IParserBase.h>
|
||||
#include <DB/Parsers/CommonParsers.h>
|
||||
#include <DB/Parsers/ExpressionListParsers.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
class ParserSelectQuery : public IParserBase
|
||||
{
|
||||
protected:
|
||||
String getName() { return "SELECT query"; }
|
||||
|
||||
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
Pos begin = pos;
|
||||
|
||||
ASTPtr select_expression_list;
|
||||
|
||||
ParserWhiteSpaceOrComments ws;
|
||||
ParserString s("SELECT");
|
||||
ParserNotWordCharOrEnd nw;
|
||||
ParserNotEmptyExpressionList exp_list;
|
||||
|
||||
ws.ignore(pos, end);
|
||||
|
||||
if (!(s.ignore(pos, end, expected)
|
||||
&& nw.check(pos, end, expected)))
|
||||
return false;
|
||||
|
||||
ws.ignore(pos, end);
|
||||
|
||||
if (!exp_list.parse(pos, end, select_expression_list, expected))
|
||||
return false;
|
||||
|
||||
ASTSelectQuery * select_query = new ASTSelectQuery(StringRange(begin, pos));
|
||||
node = select_query;
|
||||
select_query->select = select_expression_list;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
14
dbms/include/DB/Parsers/StringRange.h
Normal file
14
dbms/include/DB/Parsers/StringRange.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef DBMS_PARSERS_STRINGRANGE_H
|
||||
#define DBMS_PARSERS_STRINGRANGE_H
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
typedef std::pair<const char *, const char *> StringRange;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
308
dbms/src/Parsers/ExpressionElementParsers.cpp
Normal file
308
dbms/src/Parsers/ExpressionElementParsers.cpp
Normal file
@ -0,0 +1,308 @@
|
||||
#include <errno.h>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <DB/Parsers/IAST.h>
|
||||
#include <DB/Parsers/ASTExpressionList.h>
|
||||
#include <DB/Parsers/ASTFunction.h>
|
||||
#include <DB/Parsers/ASTIdentifier.h>
|
||||
#include <DB/Parsers/ASTLiteral.h>
|
||||
|
||||
#include <DB/Parsers/CommonParsers.h>
|
||||
#include <DB/Parsers/ExpressionListParsers.h>
|
||||
|
||||
#include <DB/Parsers/ExpressionElementParsers.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
bool ParserArray::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
Pos begin = pos;
|
||||
ASTPtr contents_node;
|
||||
ParserString open("["), close("]");
|
||||
ParserExpressionList contents;
|
||||
ParserWhiteSpaceOrComments ws;
|
||||
|
||||
if (!open.ignore(pos, end, expected))
|
||||
return false;
|
||||
|
||||
ws.ignore(pos, end);
|
||||
contents.parse(pos, end, contents_node, expected);
|
||||
ws.ignore(pos, end);
|
||||
|
||||
if (!close.ignore(pos, end, expected))
|
||||
return false;
|
||||
|
||||
ASTFunction * function_node = new ASTFunction(StringRange(begin, pos));
|
||||
function_node->name = "array";
|
||||
function_node->arguments = contents_node;
|
||||
node = function_node;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ParserParenthesisExpression::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
Pos begin = pos;
|
||||
ASTPtr contents_node;
|
||||
ParserString open("("), close(")");
|
||||
ParserExpressionList contents;
|
||||
ParserWhiteSpaceOrComments ws;
|
||||
|
||||
if (!open.ignore(pos, end, expected))
|
||||
return false;
|
||||
|
||||
ws.ignore(pos, end);
|
||||
contents.parse(pos, end, contents_node, expected);
|
||||
ws.ignore(pos, end);
|
||||
|
||||
if (!close.ignore(pos, end, expected))
|
||||
return false;
|
||||
|
||||
ASTExpressionList & expr_list = dynamic_cast<ASTExpressionList &>(*node);
|
||||
|
||||
/// пустое выражение в скобках недопустимо
|
||||
if (expr_list.children.empty())
|
||||
{
|
||||
expected = "not empty list of expressions in parenthesis";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (expr_list.children.size() == 1)
|
||||
{
|
||||
node = expr_list.children.front();
|
||||
}
|
||||
else
|
||||
{
|
||||
ASTFunction * function_node = new ASTFunction(StringRange(begin, pos));
|
||||
function_node->name = "tuple";
|
||||
function_node->arguments = contents_node;
|
||||
node = function_node;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ParserIdentifier::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
Pos begin = pos;
|
||||
|
||||
while (pos != end
|
||||
&& ((*pos >= 'a' && *pos <= 'z')
|
||||
|| (*pos >= 'A' && *pos <= 'Z')
|
||||
|| (*pos == '_')
|
||||
|| (pos != begin && *pos >= '0' && *pos <= '9')))
|
||||
++pos;
|
||||
|
||||
if (pos != begin)
|
||||
{
|
||||
node = new ASTIdentifier(StringRange(begin, pos), String(begin, pos - begin));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ParserFunction::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
Pos begin = pos;
|
||||
ASTPtr contents_node;
|
||||
|
||||
ParserIdentifier id_parser;
|
||||
ParserString open("("), close(")");
|
||||
ParserExpressionList contents;
|
||||
ParserWhiteSpaceOrComments ws;
|
||||
|
||||
ASTIdentifier * p_identifier = new ASTIdentifier(StringRange(begin, pos), "");
|
||||
ASTIdentifier & identifier = *p_identifier;
|
||||
ASTPtr identifier_node = p_identifier;
|
||||
|
||||
ASTPtr expr_list_node = new ASTExpressionList(StringRange(begin, pos));
|
||||
|
||||
if (!id_parser.parse(pos, end, identifier_node, expected))
|
||||
return false;
|
||||
|
||||
ws.ignore(pos, end);
|
||||
|
||||
if (!open.ignore(pos, end, expected))
|
||||
return false;
|
||||
|
||||
ws.ignore(pos, end);
|
||||
contents.parse(pos, end, expr_list_node, expected);
|
||||
ws.ignore(pos, end);
|
||||
|
||||
if (!close.ignore(pos, end, expected))
|
||||
return false;
|
||||
|
||||
ASTFunction * function_node = new ASTFunction(StringRange(begin, pos));
|
||||
function_node->name = identifier.name;
|
||||
function_node->arguments = expr_list_node;
|
||||
node = function_node;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ParserNull::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
Pos begin = pos;
|
||||
ParserString nested_parser("NULL");
|
||||
if (nested_parser.parse(pos, end, node, expected))
|
||||
{
|
||||
node = new ASTLiteral(StringRange(StringRange(begin, pos)), Null());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ParserNumber::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
Field res;
|
||||
|
||||
Pos begin = pos;
|
||||
if (pos == end)
|
||||
return false;
|
||||
|
||||
Float64 float_value = std::strtod(pos, const_cast<char**>(&pos));
|
||||
if (pos == begin || errno == ERANGE)
|
||||
{
|
||||
expected = "number (this cause range error)";
|
||||
return false;
|
||||
}
|
||||
res = float_value;
|
||||
|
||||
/// попробуем использовать более точный тип - UInt64 или Int64
|
||||
|
||||
Pos pos_integer = begin;
|
||||
if (float_value < 0)
|
||||
{
|
||||
Int64 int_value = std::strtoll(pos_integer, const_cast<char**>(&pos_integer), 0);
|
||||
if (pos_integer == pos && errno != ERANGE)
|
||||
res = int_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt64 uint_value = std::strtoull(pos_integer, const_cast<char**>(&pos_integer), 0);
|
||||
if (pos_integer == pos && errno != ERANGE)
|
||||
res = uint_value;
|
||||
}
|
||||
|
||||
node = new ASTLiteral(StringRange(begin, pos), res);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ParserStringLiteral::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
Pos begin = pos;
|
||||
String s;
|
||||
|
||||
if (pos == end || *pos != '\'')
|
||||
{
|
||||
expected = "opening single quote";
|
||||
return false;
|
||||
}
|
||||
|
||||
while (pos != end)
|
||||
{
|
||||
size_t bytes = 0;
|
||||
for (; pos + bytes != end; ++bytes)
|
||||
if (pos[bytes] == '\\' || pos[bytes] == '\'')
|
||||
break;
|
||||
|
||||
s.append(pos, bytes);
|
||||
pos += bytes;
|
||||
|
||||
if (*pos == '\'')
|
||||
{
|
||||
++pos;
|
||||
node = new ASTLiteral(StringRange(begin, pos), s);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (*pos == '\\')
|
||||
{
|
||||
++pos;
|
||||
if (pos == end)
|
||||
{
|
||||
expected = "escape sequence";
|
||||
return false;
|
||||
}
|
||||
s += parseEscapeSequence(*pos);
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
expected = "closing single quote";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ParserLiteral::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
Pos begin = pos;
|
||||
|
||||
ParserNull null_p;
|
||||
ParserNumber num_p;
|
||||
ParserStringLiteral str_p;
|
||||
|
||||
if (null_p.parse(pos, end, node, expected))
|
||||
return true;
|
||||
pos = begin;
|
||||
|
||||
if (num_p.parse(pos, end, node, expected))
|
||||
return true;
|
||||
pos = begin;
|
||||
|
||||
if (str_p.parse(pos, end, node, expected))
|
||||
return true;
|
||||
pos = begin;
|
||||
|
||||
expected = "literal: one of NULL, number, single quoted string";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ParserExpressionElement::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
Pos begin = pos;
|
||||
|
||||
ParserParenthesisExpression paren_p;
|
||||
ParserArray array_p;
|
||||
ParserLiteral lit_p;
|
||||
ParserFunction fun_p;
|
||||
ParserIdentifier id_p;
|
||||
|
||||
if (paren_p.parse(pos, end, node, expected))
|
||||
return true;
|
||||
pos = begin;
|
||||
|
||||
if (array_p.parse(pos, end, node, expected))
|
||||
return true;
|
||||
pos = begin;
|
||||
|
||||
if (lit_p.parse(pos, end, node, expected))
|
||||
return true;
|
||||
pos = begin;
|
||||
|
||||
if (fun_p.parse(pos, end, node, expected))
|
||||
return true;
|
||||
pos = begin;
|
||||
|
||||
if (id_p.parse(pos, end, node, expected))
|
||||
return true;
|
||||
pos = begin;
|
||||
|
||||
expected = "expression element: one of array, literal, function, identifier, parenthised expression";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
202
dbms/src/Parsers/ExpressionListParsers.cpp
Normal file
202
dbms/src/Parsers/ExpressionListParsers.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
#include <DB/Parsers/IAST.h>
|
||||
#include <DB/Parsers/ASTExpressionList.h>
|
||||
#include <DB/Parsers/ASTFunction.h>
|
||||
|
||||
#include <DB/Parsers/CommonParsers.h>
|
||||
#include <DB/Parsers/ExpressionElementParsers.h>
|
||||
|
||||
#include <DB/Parsers/ExpressionListParsers.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
bool ParserLeftAssociativeBinaryOperatorList::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
bool first = true;
|
||||
ParserWhiteSpaceOrComments ws;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
ASTPtr elem;
|
||||
if (!elem_parser->parse(pos, end, elem, expected))
|
||||
break;
|
||||
|
||||
node = elem;
|
||||
}
|
||||
else
|
||||
{
|
||||
ws.ignore(pos, end);
|
||||
|
||||
/// пробуем найти какой-нибудь из допустимых операторов
|
||||
Pos begin = pos;
|
||||
Operators_t::const_iterator it;
|
||||
for (it = operators.begin(); it != operators.end(); ++it)
|
||||
{
|
||||
ParserString op(it->first);
|
||||
if (op.ignore(pos, end, expected))
|
||||
break;
|
||||
}
|
||||
|
||||
if (it == operators.end())
|
||||
break;
|
||||
|
||||
ws.ignore(pos, end);
|
||||
|
||||
/// функция, соответствующая оператору
|
||||
ASTFunction * p_function = new ASTFunction(StringRange(pos, pos));
|
||||
ASTFunction & function = *p_function;
|
||||
ASTPtr function_node = p_function;
|
||||
|
||||
/// аргументы функции
|
||||
ASTExpressionList * p_exp_list = new ASTExpressionList(StringRange(pos, pos));
|
||||
ASTExpressionList & exp_list = *p_exp_list;
|
||||
ASTPtr exp_list_node = p_exp_list;
|
||||
|
||||
ASTPtr elem;
|
||||
if (!elem_parser->parse(pos, end, elem, expected))
|
||||
return false;
|
||||
|
||||
/// первым аргументом функции будет предыдущий элемент, вторым - следующий
|
||||
function.range.first = begin;
|
||||
function.range.second = pos;
|
||||
function.name = it->second;
|
||||
function.arguments = exp_list_node;
|
||||
|
||||
exp_list.children.push_back(node);
|
||||
exp_list.children.push_back(elem);
|
||||
exp_list.range.second = pos;
|
||||
|
||||
/** специальное исключение для оператора доступа к элементу массива x[y], который
|
||||
* содержит инфиксную часть '[' и суффиксную ']' (задаётся в виде '[')
|
||||
*/
|
||||
if (it->first == "[")
|
||||
{
|
||||
ParserString rest_p("]");
|
||||
|
||||
ws.ignore(pos, end);
|
||||
if (!rest_p.ignore(pos, end, expected))
|
||||
return false;
|
||||
}
|
||||
|
||||
node = function_node;
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ParserPrefixUnaryOperatorExpression::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
ParserWhiteSpaceOrComments ws;
|
||||
|
||||
ws.ignore(pos, end);
|
||||
|
||||
/// пробуем найти какой-нибудь из допустимых операторов
|
||||
Pos begin = pos;
|
||||
Operators_t::const_iterator it;
|
||||
for (it = operators.begin(); it != operators.end(); ++it)
|
||||
{
|
||||
ParserString op(it->first);
|
||||
if (op.ignore(pos, end, expected))
|
||||
break;
|
||||
}
|
||||
|
||||
if (it == operators.end())
|
||||
return false;
|
||||
|
||||
ws.ignore(pos, end);
|
||||
|
||||
/// функция, соответствующая оператору
|
||||
ASTFunction * p_function = new ASTFunction(StringRange(pos, pos));
|
||||
ASTFunction & function = *p_function;
|
||||
ASTPtr function_node = p_function;
|
||||
|
||||
/// аргументы функции
|
||||
ASTExpressionList * p_exp_list = new ASTExpressionList(StringRange(pos, pos));
|
||||
ASTExpressionList & exp_list = *p_exp_list;
|
||||
ASTPtr exp_list_node = p_exp_list;
|
||||
|
||||
ASTPtr elem;
|
||||
if (!elem_parser->parse(pos, end, elem, expected))
|
||||
return false;
|
||||
|
||||
function.range.first = begin;
|
||||
function.range.second = pos;
|
||||
function.name = it->second;
|
||||
function.arguments = exp_list_node;
|
||||
|
||||
exp_list.children.push_back(elem);
|
||||
exp_list.range.second = pos;
|
||||
|
||||
node = function_node;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
ParserAccessExpression::ParserAccessExpression()
|
||||
: elem_parser(new ParserExpressionElement),
|
||||
operator_parser(boost::assign::map_list_of
|
||||
(".", "tupleElement")
|
||||
("[", "arrayElement"),
|
||||
elem_parser)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool ParserExpressionList::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
bool first = true;
|
||||
ParserLogicalOrExpression nested_parser;
|
||||
ParserWhiteSpaceOrComments ws;
|
||||
ParserString comma(",");
|
||||
|
||||
ASTExpressionList * p_expr_list = new ASTExpressionList(StringRange(pos, pos));
|
||||
ASTExpressionList & expr_list = *p_expr_list;
|
||||
node = p_expr_list;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
ASTPtr elem;
|
||||
if (!nested_parser.parse(pos, end, elem, expected))
|
||||
break;
|
||||
|
||||
expr_list.children.push_back(elem);
|
||||
}
|
||||
else
|
||||
{
|
||||
ws.ignore(pos, end);
|
||||
if (!comma.ignore(pos, end, expected))
|
||||
break;
|
||||
ws.ignore(pos, end);
|
||||
|
||||
ASTPtr elem;
|
||||
if (!nested_parser.parse(pos, end, elem, expected))
|
||||
return false;
|
||||
|
||||
expr_list.children.push_back(elem);
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ParserNotEmptyExpressionList::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
||||
{
|
||||
return nested_parser.parse(pos, end, node, expected)
|
||||
&& !dynamic_cast<ASTExpressionList &>(*node).children.empty();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
|
||||
#include <DB/Parsers/ExpressionGrammar.h>
|
||||
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace ascii = boost::spirit::ascii;
|
||||
|
||||
typedef DB::ExpressionGrammarTypes::Expression Expr;
|
||||
|
||||
class dumpConst : public boost::static_visitor<>
|
||||
{
|
||||
public:
|
||||
void operator() (const DB::ExpressionGrammarTypes::NumberConstant & x) const
|
||||
{
|
||||
std::cout << "Number: " << x << std::endl;
|
||||
}
|
||||
|
||||
void operator() (const DB::ExpressionGrammarTypes::StringConstant & x) const
|
||||
{
|
||||
std::cout << "String: " << x << std::endl;
|
||||
}
|
||||
|
||||
void operator() (const DB::ExpressionGrammarTypes::NullConstant & x) const
|
||||
{
|
||||
std::cout << "Null" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
class dumpNode : public boost::static_visitor<>
|
||||
{
|
||||
public:
|
||||
void operator() (const DB::ExpressionGrammarTypes::Constant & x) const
|
||||
{
|
||||
boost::apply_visitor(dumpConst(), x);
|
||||
}
|
||||
|
||||
void operator() (const DB::ExpressionGrammarTypes::Name & x) const
|
||||
{
|
||||
std::cout << "Name: " << x << std::endl;
|
||||
}
|
||||
|
||||
void operator() (const DB::ExpressionGrammarTypes::Function & x) const
|
||||
{
|
||||
std::cout << "Function, name: " << x.name << ", args: " << std::endl;
|
||||
for (Expr::const_iterator it = x.args.begin(); it != x.args.end(); ++it)
|
||||
boost::apply_visitor(dumpNode(), *it);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
void dumpResult(const Expr & value)
|
||||
{
|
||||
|
||||
for (Expr::const_iterator it = value.begin(); it != value.end(); ++it)
|
||||
boost::apply_visitor(dumpNode(), *it);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
typedef std::string::const_iterator iterator_t;
|
||||
|
||||
DB::ExpressionGrammar<iterator_t> parser;
|
||||
DB::ExpressionGrammarTypes::Expression value;
|
||||
|
||||
std::string s = "ab1, b, f(c), 0, g(h(i), 1), -1, NULL, null, 'abc'";
|
||||
iterator_t it = s.begin();
|
||||
iterator_t end = s.end();
|
||||
|
||||
bool res = boost::spirit::qi::phrase_parse(it, end, parser, ascii::space, value);
|
||||
|
||||
std::cout << res << '\t' << s.substr(0, it - s.begin()) << std::endl;
|
||||
dumpResult(value);
|
||||
|
||||
return 0;
|
||||
}
|
32
dbms/src/Parsers/tests/parsers.cpp
Normal file
32
dbms/src/Parsers/tests/parsers.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <strconvert/escape_manip.h>
|
||||
|
||||
#include <DB/Parsers/ASTSelectQuery.h>
|
||||
#include <DB/Parsers/ParserSelectQuery.h>
|
||||
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
DB::ParserSelectQuery parser;
|
||||
DB::ASTPtr ast;
|
||||
std::string input = "SELECT 1, 2, 3";
|
||||
std::string expected;
|
||||
|
||||
const char * begin = input.data();
|
||||
const char * end = begin + input.size();
|
||||
const char * pos = begin;
|
||||
|
||||
if (parser.parse(pos, end, ast, expected))
|
||||
{
|
||||
std::cout << "Success." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Failed at position " << (pos - begin) << ": "
|
||||
<< strconvert::quote_fast << input.substr(pos - begin, 10)
|
||||
<< ", expected " << expected << "." << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user