ClickHouse/dbms/include/DB/Parsers/CommonParsers.h

172 lines
3.8 KiB
C
Raw Normal View History

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:
const char * s;
size_t s_size;
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:
ParserString(const char * s_, bool word_boundary_ = false, bool case_insensitive_ = false)
: s(s_), s_size(strlen(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:
const char * getName() const { return s; }
2010-06-24 19:12:10 +00:00
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, const char *& expected)
2010-06-24 19:12:10 +00:00
{
if (static_cast<ssize_t>(s_size) > end - pos || (case_insensitive ? strncasecmp : strncmp)(pos, s, s_size))
2010-06-24 19:12:10 +00:00
return false;
else
{
if (word_boundary && s_size && is_word(s[s_size - 1])
&& pos + s_size != end && is_word(pos[s_size]))
2010-06-25 16:36:13 +00:00
return false;
pos += s_size;
2010-06-24 19:12:10 +00:00
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;
const char * getName() const { return "white space"; }
2010-06-24 19:12:10 +00:00
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, const char *& expected)
2010-06-24 19:12:10 +00:00
{
Pos begin = pos;
while (pos < end && (*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:
const char * getName() const { return "C-style comment"; }
2010-06-24 19:12:10 +00:00
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, const char *& expected)
2010-06-24 19:12:10 +00:00
{
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:
const char * getName() const { return "SQL-style comment"; }
2010-06-24 19:12:10 +00:00
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, const char *& expected)
2010-06-24 19:12:10 +00:00
{
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:
const char * getName() const { return "comment"; }
2010-06-24 19:12:10 +00:00
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, const char *& expected)
2010-06-24 19:12:10 +00:00
{
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;
const char * getName() const { return "white space or comments"; }
2010-06-24 19:12:10 +00:00
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, const char *& expected)
2010-06-24 19:12:10 +00:00
{
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;
}
};
}