#include "highlighter.h" #include "AttributeLexer.h" #include #include Highlighter::Highlighter(std::istream &file) { m_lexer = new XMLLexer(file); colormap[CONTENT] = Undefined; // The abstract base class shouldn't have default colors colormap[ELEMENT] = Undefined; colormap[ATTRIBUTE] = Undefined; colormap[ATTRIBURE_CONTENT] = Undefined; colormap[BRACKET] = Undefined; colormap[nonmatching] = Undefined; colormap[COMMENT] = Undefined; } Highlighter::~Highlighter() { delete m_lexer; } void Highlighter::process() { while (true) { // Wait until the NoMoreTokens exception is thrown try { XMLLexer::Token token = m_lexer->nextToken(); // Get the next token Token newtoken; newtoken.content = token.content; switch(token.type) { // setup local tokentype case XMLLexer::TokenType::CONTENT: newtoken.type = CONTENT; break; case XMLLexer::TokenType::TAG: newtoken.type = TAG; break; case XMLLexer::TokenType::COMMENT: newtoken.type = COMMENT; break; default: newtoken.type = nonmatching; break; } newtoken.color = colormap.find(newtoken.type)->second; // get the appropriate color m_tokens.push_back(newtoken); } catch (XMLLexer::NoMoreTokens &err) { break; // We reached the end of the file } catch (XMLLexer::NoMatch& err) { // No match was found, setup a new token with 1 character and tokentype nonmatching + skip this character Token newtoken; newtoken.content = m_lexer->peek(); m_lexer->skip(1); newtoken.type = nonmatching; m_tokens.push_back(newtoken); } } auto tokens = std::move(m_tokens); m_tokens.clear(); for(auto &tagtoken: tokens) { if(tagtoken.type == TAG && !tagtoken.content.empty()) { // If the token was a tag, use a second lexer to find attributes etc. std::istringstream content(tagtoken.content); AttributeLexer attributelexer(content); while (true) { try { AttributeLexer::Token token = attributelexer.nextToken(); Token newtoken; newtoken.content = token.content; switch(token.type) { case AttributeLexer::TokenType::ELEMENT: newtoken.type = ELEMENT; break; case AttributeLexer::TokenType::BRACKET: newtoken.type = BRACKET; break; case AttributeLexer::TokenType::ATTRIBUTE: newtoken.type = ATTRIBUTE; break; case AttributeLexer::TokenType::ATTRIBUTE_CONTENT_DOUBLE_QUOTES: newtoken.type = ATTRIBURE_CONTENT; break; case AttributeLexer::TokenType::ATTRIBUTE_CONTENT_SINGLE_QUOTES: newtoken.type = ATTRIBURE_CONTENT; break; default: newtoken.type = nonmatching; break; } newtoken.color = colormap.find(newtoken.type)->second; m_tokens.push_back(newtoken); } catch (AttributeLexer::NoMoreTokens &err) { break; } catch (AttributeLexer::NoMatch& err) { Token newtoken; newtoken.content = attributelexer.peek(); attributelexer.skip(1); newtoken.type = nonmatching; m_tokens.push_back(newtoken); } } } else { m_tokens.push_back(tagtoken); } } } ConsoleHighlighter::ConsoleHighlighter(std::istream &file): Highlighter(file) { colormap[CONTENT] = White; // Fill in the colors we want to use for each tokentype colormap[ELEMENT] = Blue; // Change these for different colors colormap[TAG] = Magenta; colormap[ATTRIBUTE] = Yellow; colormap[ATTRIBURE_CONTENT] = Green; colormap[BRACKET] = Blue; colormap[nonmatching] = Black; colormap[COMMENT] = Black; process(); } void ConsoleHighlighter::highlight(std::ostream &os) { for(auto &token: m_tokens) { // Go over all tokens and print them out with the right color switch(token.color) { case Yellow: os << "\033[1;33m" << token.content << "\033[0m"; break; case Black: os << "\033[1;30m" << token.content << "\033[0m"; break; case Red: os << "\033[1;31m" << token.content << "\033[0m"; break; case Green: os << "\033[1;32m" << token.content << "\033[0m"; break; case Blue: os << "\033[1;34m" << token.content << "\033[0m"; break; case Magenta: os << "\033[1;35m" << token.content << "\033[0m"; break; case Cyan: os << "\033[1;36m" << token.content << "\033[0m"; break; case White: os << "\033[1;37m" << token.content << "\033[0m"; break; default: os << token.content; } } os << std::endl; }