#pragma once
#ifndef LEXER_{{name}}_H
#define LEXER_{{name}}_H

#include <exception>
#include <istream>
#include <string>

class {{name}} {
    public:
        class NoMoreTokens : public std::exception {};
        class NoMatch : public std::exception {};

        enum TokenType {
            nonmatching,
            {{#token_types}}
            {{type}},
            {{/token_types}}
        };

        struct Token {
            TokenType type;
            std::string content;
        };
        
        {{name}}(std::istream& in);
        ~{{name}}();

        /**
         * Get the next token
         *
         * @throws NoMoreTokens if no more tokens are available
         * @throws NoMatch if no match was found
         */
        Token nextToken();

        /**
         * Skip the following `n` bytes.
         *
         * @param n The number of bytes to skip
         */
        void skip(std::size_t n);

        /**
         * Peek at the current head of the input stream, useful in error reporting when a character mismatches for example
         *
         * @throws NoMoreTokens if the input stream is at an end
         */
        char peek();

        /**
         * Get the current byte offset
         */
        std::size_t getByteOffset();

    private:
        std::size_t m_offset;
        std::istream& m_input;
};

#endif //LEXER_{{name}}_H
