/*
    SuperCollider Qt IDE
    Copyright (c) 2012 Jakob Leben & Tim Blechmann
    http://www.audiosynth.com

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
*/

#pragma once

#include "../widgets/code_editor/tokens.hpp"

#include <QVector>
#include <QRegularExpression>
#include <QString>

namespace ScIDE {

class ScLexer {
public:
    enum State {
        InCode = 0,
        InString = 1,
        InSymbol = 2,
        InComment = 100
        // NOTE: Values higher than InComment are reserved for multi line comments,
        // and indicate the comment nesting level!
    };

    static void initLexicalRules();

private:
    struct LexicalRule {
        LexicalRule(): type(Token::Unknown) {}
        LexicalRule(Token::Type t, const QString& s): type(t), expr(s) {}

        Token::Type type;
        QRegularExpression expr;
    };

    static void initKeywordsRules();
    static void initBuiltinsRules();

    static QVector<LexicalRule> mLexicalRules;

public:
    ScLexer(const QString& text, int offset = 0, int state = InCode): mText(text), mOffset(offset), mState(state) {}

    const QString& text() const { return mText; }

    int state() const { return mState; }
    void setState(int state) { mState = state; }

    int offset() const { return mOffset; }
    void setOffset(int offset) { mOffset = offset; }

    Token::Type nextToken(int& length);

private:
    Token::Type nextTokenInCode(int& length);
    Token::Type nextTokenInString(int& length);
    Token::Type nextTokenInSymbol(int& length);
    Token::Type nextTokenInComment(int& length);

    const QString& mText;
    int mOffset;
    int mState;
};

}
