ClickHouse/dbms/src/Parsers/ExpressionElementParsers.cpp

371 lines
7.7 KiB
C++
Raw Normal View History

2010-06-24 19:12:10 +00:00
#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>
2011-08-28 08:50:27 +00:00
#include <DB/Parsers/ASTAsterisk.h>
2011-09-04 05:14:52 +00:00
#include <DB/Parsers/ASTOrderByElement.h>
2010-06-24 19:12:10 +00:00
#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;
2011-08-13 21:05:18 +00:00
function_node->children.push_back(contents_node);
2010-06-24 19:12:10 +00:00
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;
2010-06-25 19:55:19 +00:00
ASTExpressionList & expr_list = dynamic_cast<ASTExpressionList &>(*contents_node);
2010-06-24 19:12:10 +00:00
/// пустое выражение в скобках недопустимо
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;
2011-08-13 21:05:18 +00:00
function_node->children.push_back(contents_node);
2010-06-24 19:12:10 +00:00
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;
ParserIdentifier id_parser;
ParserString open("("), close(")");
ParserExpressionList contents;
ParserWhiteSpaceOrComments ws;
2010-06-25 16:36:13 +00:00
ASTPtr identifier = new ASTIdentifier;
ASTPtr expr_list = new ASTExpressionList;
2010-06-24 19:12:10 +00:00
2010-06-25 16:36:13 +00:00
if (!id_parser.parse(pos, end, identifier, expected))
2010-06-24 19:12:10 +00:00
return false;
ws.ignore(pos, end);
if (!open.ignore(pos, end, expected))
return false;
ws.ignore(pos, end);
2010-06-25 16:36:13 +00:00
contents.parse(pos, end, expr_list, expected);
2010-06-24 19:12:10 +00:00
ws.ignore(pos, end);
if (!close.ignore(pos, end, expected))
return false;
ASTFunction * function_node = new ASTFunction(StringRange(begin, pos));
2010-06-25 16:36:13 +00:00
function_node->name = dynamic_cast<ASTIdentifier &>(*identifier).name;
2011-08-18 18:48:00 +00:00
function_node->arguments = expr_list;
2011-08-13 21:05:18 +00:00
function_node->children.push_back(expr_list);
2010-06-24 19:12:10 +00:00
node = function_node;
return true;
}
bool ParserNull::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
Pos begin = pos;
2010-06-25 16:36:13 +00:00
ParserString nested_parser("NULL", true);
2010-06-24 19:12:10 +00:00
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;
}
2011-08-15 01:05:18 +00:00
static 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;
}
}
2010-06-24 19:12:10 +00:00
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;
}
2010-06-25 16:36:13 +00:00
++pos;
2010-06-24 19:12:10 +00:00
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;
2011-08-28 08:50:27 +00:00
ParserString asterisk_p("*");
2010-06-24 19:12:10 +00:00
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;
2011-08-28 08:50:27 +00:00
if (asterisk_p.parse(pos, end, node, expected))
{
node = new ASTAsterisk(StringRange(begin, pos));
return true;
}
pos = begin;
expected = "expression element: one of array, literal, function, identifier, asterisk, parenthised expression";
2010-06-24 19:12:10 +00:00
return false;
}
2011-09-04 05:14:52 +00:00
bool ParserOrderByElement::parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
{
Pos begin = pos;
ParserWhiteSpaceOrComments ws;
ParserLogicalOrExpression elem_p;
ParserString ascending("ASCENDING", true, true);
ParserString descending("DESCENDING", true, true);
ParserString asc("ASC", true, true);
ParserString desc("DESC", true, true);
ASTPtr expr_elem;
if (!elem_p.parse(pos, end, expr_elem, expected))
return false;
int direction = 1;
ws.ignore(pos, end);
if (descending.ignore(pos, end) || desc.ignore(pos, end))
direction = -1;
else
ascending.ignore(pos, end) || asc.ignore(pos, end);
node = new ASTOrderByElement(StringRange(begin, pos), direction);
node->children.push_back(expr_elem);
return true;
}
2010-06-24 19:12:10 +00:00
}