2011-10-31 06:37:12 +00:00
|
|
|
|
#pragma once
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
2011-08-15 01:05:18 +00:00
|
|
|
|
#include <string.h> /// strncmp, strncasecmp
|
2010-06-24 19:12:10 +00:00
|
|
|
|
|
|
|
|
|
#include <DB/Parsers/IParserBase.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
using Poco::SharedPtr;
|
|
|
|
|
|
|
|
|
|
|
2010-06-25 16:36:13 +00:00
|
|
|
|
/** Если прямо сейчас не s, то ошибка.
|
|
|
|
|
* Если word_boundary установлен в true, и последний символ строки - словарный (\w),
|
|
|
|
|
* то проверяется, что последующий символ строки не словарный.
|
2010-06-24 19:12:10 +00:00
|
|
|
|
*/
|
|
|
|
|
class ParserString : public IParserBase
|
|
|
|
|
{
|
|
|
|
|
private:
|
2010-06-24 19:37:23 +00:00
|
|
|
|
String s;
|
2010-06-25 16:36:13 +00:00
|
|
|
|
bool word_boundary;
|
2011-08-15 01:05:18 +00:00
|
|
|
|
bool case_insensitive;
|
2010-06-25 16:36:13 +00:00
|
|
|
|
|
|
|
|
|
inline bool is_word(char c)
|
|
|
|
|
{
|
|
|
|
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '_');
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
public:
|
2011-08-15 01:05:18 +00:00
|
|
|
|
ParserString(const String & s_, bool word_boundary_ = false, bool case_insensitive_ = false)
|
|
|
|
|
: s(s_), word_boundary(word_boundary_), case_insensitive(case_insensitive_) {}
|
2010-06-25 16:36:13 +00:00
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
protected:
|
|
|
|
|
String getName() { return s; }
|
|
|
|
|
|
|
|
|
|
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
2011-08-15 01:05:18 +00:00
|
|
|
|
if (static_cast<ssize_t>(s.size()) > end - pos || (case_insensitive ? strncasecmp : strncmp)(pos, s.data(), s.size()))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
return false;
|
|
|
|
|
else
|
|
|
|
|
{
|
2010-06-25 16:36:13 +00:00
|
|
|
|
if (word_boundary && s.size() && is_word(*s.rbegin())
|
|
|
|
|
&& pos + s.size() != end && is_word(pos[s.size()]))
|
|
|
|
|
return false;
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
pos += s.size();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** пробельные символы
|
|
|
|
|
*/
|
|
|
|
|
class ParserWhiteSpace : public IParserBase
|
|
|
|
|
{
|
2011-10-31 06:37:12 +00:00
|
|
|
|
public:
|
|
|
|
|
ParserWhiteSpace(bool allow_newlines_ = true) : allow_newlines(allow_newlines_) {}
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
protected:
|
2011-10-31 06:37:12 +00:00
|
|
|
|
bool allow_newlines;
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
String getName() { return "white space"; }
|
|
|
|
|
|
|
|
|
|
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
|
|
|
|
Pos begin = pos;
|
2011-10-31 06:37:12 +00:00
|
|
|
|
while (*pos == ' ' || *pos == '\t' || (allow_newlines && *pos == '\n') || *pos == '\r' || *pos == '\f')
|
2010-06-24 19:12:10 +00:00
|
|
|
|
++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;
|
2010-06-25 19:55:19 +00:00
|
|
|
|
while (end - pos >= 2 && (pos[0] != '*' || pos[1] != '/'))
|
2010-06-24 19:12:10 +00:00
|
|
|
|
++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
|
|
|
|
|
{
|
2011-10-31 06:37:12 +00:00
|
|
|
|
public:
|
|
|
|
|
ParserWhiteSpaceOrComments(bool allow_newlines_outside_comments_ = true) : allow_newlines_outside_comments(allow_newlines_outside_comments_) {}
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
protected:
|
2011-10-31 06:37:12 +00:00
|
|
|
|
bool allow_newlines_outside_comments;
|
|
|
|
|
|
2010-06-24 19:12:10 +00:00
|
|
|
|
String getName() { return "white space or comments"; }
|
|
|
|
|
|
|
|
|
|
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, String & expected)
|
|
|
|
|
{
|
2011-10-31 06:37:12 +00:00
|
|
|
|
ParserWhiteSpace p1(allow_newlines_outside_comments);
|
2010-06-24 19:12:10 +00:00
|
|
|
|
ParserComment p2;
|
|
|
|
|
|
|
|
|
|
bool res = false;
|
|
|
|
|
while (p1.ignore(pos, end, expected) || p2.ignore(pos, end, expected))
|
|
|
|
|
res = true;
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|