yacreader/YACReaderLibrary/db/query_lexer.cpp
2023-05-21 20:29:13 +02:00

132 lines
2.6 KiB
C++

#include "query_lexer.h"
QueryLexer::QueryLexer(const std::string &input)
: input(input)
{
}
Token QueryLexer::next()
{
while (isSpace(peek())) {
get();
}
switch (peek()) {
case '\0':
return Token(Token::Type::eof);
case '(':
case ')':
return single(Token::Type::opcode);
case ':':
return single(Token::Type::equal);
case '=':
return equal();
case '<':
return minor();
case '>':
return major();
case '"':
return quotedWord();
default:
return word();
}
}
char QueryLexer::peek()
{
return input[index];
}
char QueryLexer::get()
{
return input[index++];
}
Token QueryLexer::single(Token::Type type)
{
return Token(type, input.substr(index++, 1));
}
Token QueryLexer::word()
{
auto start = index;
get();
auto current = peek();
while (current != '\0' && !isSpace(current) && current != '"' && current != '(' && current != ')' && current != ':' && current != '=' && current != '<' && current != '>') {
get();
current = peek();
}
return Token(Token::Type::word, input.substr(start, index - start));
}
Token QueryLexer::quotedWord()
{
auto start = index;
get();
auto current = peek();
while (current != '\0' && current != '"') {
get();
current = peek();
}
if (current == '"') {
get();
return Token(Token::Type::quotedWord, input.substr(start, index - start));
}
// This should be a lexical error, but the grammar doesn't support it
return Token(Token::Type::eof);
}
Token QueryLexer::minor()
{
auto start = index;
get();
auto current = peek();
if (current == '=') {
get();
return Token(Token::Type::minorOrEqual, input.substr(start, index - start));
}
return Token(Token::Type::minor, input.substr(start, index - start));
}
Token QueryLexer::major()
{
auto start = index;
get();
auto current = peek();
if (current == '=') {
get();
return Token(Token::Type::majorOrEqual, input.substr(start, index - start));
}
return Token(Token::Type::major, input.substr(start, index - start));
}
Token QueryLexer::equal()
{
auto start = index;
get();
auto current = peek();
if (current == '=') {
get();
return Token(Token::Type::exactEqual, input.substr(start, index - start));
}
return Token(Token::Type::equal, input.substr(start, index - start));
}
bool QueryLexer::isSpace(char c)
{
switch (c) {
case ' ':
case '\t':
case '\r':
case '\n':
return true;
default:
return false;
}
}