147 lines
5.8 KiB
C++
147 lines
5.8 KiB
C++
#include "highlighter.h"
|
|
#include "AttributeLexer.h"
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
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;
|
|
}
|