#pragma once #include #include #include #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); struct parse_driver { std::string file_name; std::ifstream file_stream; std::ostringstream string_stream; yy::location location; size_t file_offset; std::vector line_offsets; definition_group global_defs; std::string read_file; parse_driver(const std::string& file) : file_name(file), file_offset(0) {} bool run_parse() { file_stream.open(file_name); if(!file_stream.good()) return false; line_offsets.push_back(0); yyscan_t scanner; scanner_init(this, &scanner); yy::parser parser(scanner, *this); parser(); scanner_destroy(&scanner); read_file = string_stream.str(); return true; } int get() { int new_char = file_stream.get(); if(new_char == EOF) return EOF; file_offset++; if(new_char == '\n') line_offsets.push_back(file_offset); string_stream.put(new_char); return new_char; } size_t get_index(int line, int column) { assert(line > 0); assert(line <= line_offsets.size()); size_t file_offset = line_offsets[line-1]; file_offset += column - 1; return file_offset; } size_t get_line_end(int line) { if(line > line_offsets.size()) return read_file.size(); return get_index(line+1, 1); } void print_highlighted_location(std::ostream& stream, const yy::location& loc) { size_t print_start = get_index(loc.begin.line, 1); size_t highlight_start = get_index(loc.begin.line, loc.begin.column); size_t highlight_end = get_index(loc.end.line, loc.end.column); size_t print_end = get_line_end(loc.end.line); const char* content = read_file.c_str(); stream.write(content + print_start, highlight_start - print_start); stream << "\033[4;31m"; stream.write(content + highlight_start, highlight_end - highlight_start); stream << "\033[0m"; stream.write(content + highlight_end, print_end - highlight_end); } }; #define YY_DECL yy::parser::symbol_type yylex(yyscan_t yyscanner, parse_driver& drv) YY_DECL;