#pragma once
#include <string>
#include <fstream>
#include <sstream>
#include "definition.hpp"
#include "location.hh"
#include "parser.hpp"

struct parse_driver;

void scanner_init(parse_driver* d, yyscan_t* scanner);
void scanner_destroy(yyscan_t* scanner);

class file_mgr {
    private:
        std::ostringstream string_stream;
        std::string file_contents;

        size_t file_offset;
        std::vector<size_t> line_offsets;
    public:
        file_mgr();

        void write(const char* buffer, size_t len);
        void mark_line();
        void finalize();

        size_t get_index(int line, int column) const;
        size_t get_line_end(int line) const;
        void print_location(
                std::ostream& stream,
                const yy::location& loc,
                bool highlight = true) const;
};

class parse_driver {
    private:
        std::string file_name;
        yy::location location;
        definition_group* global_defs;
        file_mgr* file_m;

    public:
        parse_driver(
                file_mgr& mgr,
                definition_group& defs,
                const std::string& file)
            : file_name(file), file_m(&mgr), global_defs(&defs) {}

        bool operator()();
        yy::location& get_current_location();
        file_mgr& get_file_manager() const;
        definition_group& get_global_defs() const;
};

#define YY_DECL yy::parser::symbol_type yylex(yyscan_t yyscanner, parse_driver& drv)

YY_DECL;