#include "RegexLexer.h"

#include <sstream>
#include <iostream>

namespace { //The automaton data
    typedef std::size_t State;

    State REJECT = 37;

    unsigned char TRANS_IDX[256] = { (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)1, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)2, (unsigned char)3, (unsigned char)4, (unsigned char)5, (unsigned char)0, (unsigned char)6, (unsigned char)7, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)8, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)9, (unsigned char)10, (unsigned char)11, (unsigned char)12, (unsigned char)0, (unsigned char)0, (unsigned char)13, (unsigned char)14, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)15, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)16, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)17, (unsigned char)18, (unsigned char)19, (unsigned char)0, (unsigned char)20, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)21, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0, (unsigned char)0,  };

    State TABLE[38 - 1][22] = { 
        {  35,  14,  33,  34,  29,  30,  35,  28,  31,  1,  9,  36,  35,  35,  35,  35,  35,  35,  35,  35,  35,  32,  },
        
        {  5,  5,  5,  5,  5,  5,  4,  5,  5,  5,  5,  3,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  },
        
        {  5,  5,  5,  5,  5,  5,  4,  5,  5,  5,  5,  3,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  },
        
        {  5,  5,  5,  5,  5,  5,  4,  5,  5,  5,  5,  8,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  },
        
        {  5,  5,  5,  5,  5,  5,  7,  5,  5,  5,  5,  8,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  },
        
        {  5,  5,  5,  5,  5,  5,  6,  5,  5,  5,  5,  8,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  },
        
        {  4,  4,  4,  4,  4,  4,  37,  4,  4,  4,  4,  8,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  8,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  22,  23,  19,  20,  37,  27,  26,  24,  18,  25,  37,  15,  13,  16,  11,  12,  14,  10,  17,  21,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
        
        {  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  37,  },
         };

    RegexLexer::TokenType TOKENS[38] = {  RegexLexer::nonmatching,  RegexLexer::ERROR,  RegexLexer::nonmatching,  RegexLexer::nonmatching,  RegexLexer::nonmatching,  RegexLexer::nonmatching,  RegexLexer::nonmatching,  RegexLexer::nonmatching,  RegexLexer::CHAR_CLASS,  RegexLexer::ERROR,  RegexLexer::TAB,  RegexLexer::NEWLINE,  RegexLexer::CARRIAGE_RETURN,  RegexLexer::BACKSPACE,  RegexLexer::SPACE,  RegexLexer::BELL,  RegexLexer::FORMFEED,  RegexLexer::VTAB,  RegexLexer::BACKSLASH,  RegexLexer::ESCAPED_STAR,  RegexLexer::ESCAPED_PLUS,  RegexLexer::ESCAPED_PIPE,  RegexLexer::ESCAPED_LPAREN,  RegexLexer::ESCAPED_RPAREN,  RegexLexer::ESCAPED_LBRACKET,  RegexLexer::ESCAPED_RBRACKET,  RegexLexer::ESCAPED_QUESTIONMARK,  RegexLexer::ESCAPED_DOT,  RegexLexer::DOT,  RegexLexer::STAR,  RegexLexer::PLUS,  RegexLexer::QUESTIONMARK,  RegexLexer::PIPE,  RegexLexer::LPAREN,  RegexLexer::RPAREN,  RegexLexer::CHAR,  RegexLexer::ERROR,  RegexLexer::nonmatching,  };
}

RegexLexer::RegexLexer(std::istream& in) : m_offset(0), m_input(in) {

}

RegexLexer::~RegexLexer() {
}

RegexLexer::Token RegexLexer::nextToken() {
    TokenType type = ignore;
    std::string token;

    while (type == ignore) {
        State state = 0;
        std::size_t match_length = 0;
        token = "";

        while (!m_input.eof() && state != REJECT) {
            char c = m_input.peek();
            if (m_input.eof())
                break;

            token += c;

            state = TABLE[state][TRANS_IDX[(unsigned char)c]];
            if (TOKENS[state])
            {
                match_length = token.length();
                type = TOKENS[state];
            }
            m_input.get();
            ++m_offset;
        }

        std::size_t sdiff = token.length() - match_length;
        for (std::size_t i = 0; i < sdiff; i++)
        {
            m_input.putback(token[token.length() - i - 1]);
        }
        m_offset -= sdiff;

        if (!type || !match_length) {
            if (m_input.eof())
                throw NoMoreTokens();
            throw NoMatch();
        }

        token = token.substr(0, match_length);
    }

    Token t;
    t.type = type;
    t.content = token;
    return t;
}

void RegexLexer::skip(std::size_t n) {
    for (size_t i = 0; i < n; i++) {
        m_input.get();
        ++m_offset;
    }
}

char RegexLexer::peek() {
    if (m_input.eof())
        throw NoMoreTokens();
    return m_input.peek();
}

std::size_t RegexLexer::getByteOffset() {
    return m_offset;
}
