Website Summary Files Commits Branches @commit @diff @stats
path: root / homework / 81625 / cpp2html / src
diff options
context:
space:
mode:
Commit26e5f891d537b5d4fc2890c9cdbeb73d5748d568 (patch)
Author
 thetedgt <44469837+thetedgt@users.noreply.github.com>
2018-11-03 13:34:18 +0200
Committer
 Martin Dobrev <martindobrev0@gmail.com>
2018-11-03 13:34:18 +0200
Files702aa5c2110f0fb7afccebe3bf894747a70e94c0 /homework/81625/cpp2html/src
IPL-26e5f891d537b5d4fc2890c9cdbeb73d5748d568.tar
IPL-26e5f891d537b5d4fc2890c9cdbeb73d5748d568.tar.gz
IPL-26e5f891d537b5d4fc2890c9cdbeb73d5748d568.zip
Parent0b0962d77111cacc8c1f1a265eb1211e7d44fea4 (diff)
homework 1 (#27)
3 files changed, 1019 insertions, 0 deletions
-rw-r--r--homework/81625/cpp2html/src/Lexer.cpp689
-rw-r--r--homework/81625/cpp2html/src/Lexer.h223
-rw-r--r--homework/81625/cpp2html/src/main.cpp107
diff --git a/homework/81625/cpp2html/src/Lexer.cpp b/homework/81625/cpp2html/src/Lexer.cpp
new file mode 100644
index 0000000..63d208b
--- /dev/null
+++ b/homework/81625/cpp2html/src/Lexer.cpp
@@ -0,0 +1,689 @@
+#include "Lexer.h"
+
+bool isDigit(char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+bool isLowerCase(char c)
+{
+ return c >= 'a' && c <= 'z';
+}
+
+bool isCapitalCase(char c)
+{
+ return c >= 'A' && c <= 'Z';
+}
+
+
+Tokenizer::Tokenizer(const char* code) :
+ line(1), column(0), codeIndex(0), code(code), state(State::SUCCESS)
+{
+ keywords["alignas"] = TokenType::ALIGNAS;
+ keywords["alignof"] = TokenType::ALIGNOF;
+ keywords["and"] = TokenType::AND;
+ keywords["and_eq"] = TokenType::AND_EQ;
+ keywords["asm"] = TokenType::ASM;
+ keywords["auto"] = TokenType::AUTO;
+ keywords["bitand"] = TokenType::BITAND;
+ keywords["bitor"] = TokenType::BITOR;
+ keywords["bool"] = TokenType::BOOL;
+ keywords["break"] = TokenType::BREAK;
+ keywords["case"] = TokenType::CASE;
+ keywords["catch"] = TokenType::CATCH;
+ keywords["char"] = TokenType::CHAR;
+ keywords["char16_t"] = TokenType::CHAR16_T;
+ keywords["char32_t"] = TokenType::CHAR32_T;
+ keywords["class"] = TokenType::CLASS;
+ keywords["compl"] = TokenType::COMPL;
+ keywords["const"] = TokenType::CONST;
+ keywords["constexpr"] = TokenType::CONSTEXPR;
+ keywords["const_cast"] = TokenType::CONST_CAST;
+ keywords["continue"] = TokenType::CONTINUE;
+ keywords["decltype"] = TokenType::DECLTYPE;
+ keywords["default"] = TokenType::DEFAULT;
+ keywords["delete"] = TokenType::DELETE;
+ keywords["do"] = TokenType::DO;
+ keywords["double"] = TokenType::DOUBLE;
+ keywords["dynamic_cast"] = TokenType::DYNAMIC_CAST;
+ keywords["else"] = TokenType::ELSE;
+ keywords["enum"] = TokenType::ENUM;
+ keywords["explicit"] = TokenType::EXPLICIT;
+ keywords["export"] = TokenType::EXPORT;
+ keywords["extern"] = TokenType::EXTERN;
+ keywords["false"] = TokenType::FALSE;
+ keywords["float"] = TokenType::FLOAT;
+ keywords["for"] = TokenType::FOR;
+ keywords["friend"] = TokenType::FRIEND;
+ keywords["goto"] = TokenType::GOTO;
+ keywords["if"] = TokenType::IF;
+ keywords["inline"] = TokenType::INLINE;
+ keywords["int"] = TokenType::INT;
+ keywords["long"] = TokenType::LONG;
+ keywords["mutable"] = TokenType::MUTABLE;
+ keywords["namespace"] = TokenType::NAMESPACE;
+ keywords["new"] = TokenType::NEW;
+ keywords["noexcept"] = TokenType::NOEXCEPT;
+ keywords["not"] = TokenType::NOT;
+ keywords["not_eq"] = TokenType::NOT_EQ;
+ keywords["nullptr"] = TokenType::NULLPTR;
+ keywords["operator"] = TokenType::OPERATOR;
+ keywords["or"] = TokenType::OR;
+ keywords["or_eq"] = TokenType::OR_EQ;
+ keywords["private"] = TokenType::PRIVATE;
+ keywords["protected"] = TokenType::PROTECTED;
+ keywords["public"] = TokenType::PUBLIC;
+ keywords["register"] = TokenType::REGISTER;
+ keywords["reinterpret_cast"]= TokenType::REINTERPRET_CAST;
+ keywords["return"] = TokenType::RETURN;
+ keywords["short"] = TokenType::SHORT;
+ keywords["signed"] = TokenType::SIGNED;
+ keywords["sizeof"] = TokenType::SIZEOF;
+ keywords["static"] = TokenType::STATIC;
+ keywords["static_assert"] = TokenType::STATIC_ASSERT;
+ keywords["static_cast"] = TokenType::STATIC_CAST;
+ keywords["struct"] = TokenType::STRUCT;
+ keywords["switch"] = TokenType::SWITCH;
+ keywords["template"] = TokenType::TEMPLATE;
+ keywords["this"] = TokenType::THIS;
+ keywords["thread_local"] = TokenType::THREAD_LOCAL;
+ keywords["throw"] = TokenType::THROW;
+ keywords["true"] = TokenType::TRUE;
+ keywords["try"] = TokenType::TRY;
+ keywords["typedef"] = TokenType::TYPEDEF;
+ keywords["typeid"] = TokenType::TYPEID;
+ keywords["typename"] = TokenType::TYPENAME;
+ keywords["union"] = TokenType::UNION;
+ keywords["unsigned"] = TokenType::UNSIGNED;
+ keywords["using"] = TokenType::USING;
+ keywords["virtual"] = TokenType::VIRTUAL;
+ keywords["void"] = TokenType::VOID;
+ keywords["volatile"] = TokenType::VOLATILE;
+ keywords["wchar_t"] = TokenType::WCHAR_T;
+ keywords["while"] = TokenType::WHILE;
+ keywords["xor"] = TokenType::XOR;
+ keywords["xor_eq"] = TokenType::XOR_EQ;
+
+ preprocessors["#define"] = TokenType::PRE_DEFINE;
+ preprocessors["#undef"] = TokenType::PRE_UNDEF;
+ preprocessors["#include"] = TokenType::PRE_INCLUDE;
+ preprocessors["#if"] = TokenType::PRE_IF;
+ preprocessors["#ifdef"] = TokenType::PRE_IFDEF;
+ preprocessors["#ifndef"] = TokenType::PRE_IFNDEF;
+ preprocessors["#else"] = TokenType::PRE_ELSE;
+ preprocessors["#elif"] = TokenType::PRE_ELIF;
+ preprocessors["#endif"] = TokenType::PRE_ENDIF;
+ preprocessors["#line"] = TokenType::PRE_LINE;
+ preprocessors["#error"] = TokenType::PRE_ERROR;
+ preprocessors["#pragma"] = TokenType::PRE_PRAGMA;
+}
+
+bool Tokenizer::isAtEOF() const
+{
+ return code[codeIndex] == '\0';
+}
+
+bool Tokenizer::match(char c) const
+{
+ return code[codeIndex] == c;
+}
+
+bool Tokenizer::isStateError() const
+{
+ return state == State::ERROR;
+}
+
+bool Tokenizer::isStateSuccess() const
+{
+ return state == State::SUCCESS;
+}
+
+bool Tokenizer::tokenize(std::vector<Token> &tokens)
+{
+ Token token;
+ do
+ {
+ token = nextToken();
+ if(token.type == TokenType::INVALID)
+ {
+ return false;
+ }
+ tokens.push_back(token);
+
+ } while(token.type != TokenType::Eof);
+
+ return true;
+}
+
+void Tokenizer::skipWhiteSpaces()
+{
+ while(true)
+ {
+ if(code[codeIndex] == ' ' || code[codeIndex] == '\t')
+ {
+ column++;
+ }
+ else if(code[codeIndex] == '\n')
+ {
+ column = 0;
+ line++;
+ }
+ else
+ {
+ break;
+ }
+ codeIndex++;
+ }
+}
+
+void Tokenizer::nextSymbol()
+{
+ codeIndex++;
+ column++;
+}
+
+void Tokenizer::prevSymbol()
+{
+ codeIndex--;
+ column--;
+}
+
+double Tokenizer::parseNumber()
+{
+ try
+ {
+ size_t bytes = 0;
+ double d = std::stod(code + codeIndex, &bytes);
+ codeIndex += static_cast<unsigned>(bytes);
+ column += static_cast<unsigned>(bytes);
+ state = State::SUCCESS;
+ return d;
+ }
+ catch(std::invalid_argument &e)
+ {
+ state = State::FAIL;
+ return 0;
+ }
+ catch(std::out_of_range &e)
+ {
+ state = State::ERROR;
+ return 0;
+ }
+}
+
+std::string Tokenizer::parseComment()
+{
+ if(code[codeIndex] == '/')
+ {
+ unsigned start = codeIndex;
+ nextSymbol();
+ if(code[codeIndex] == '/')
+ {
+ nextSymbol();
+ while(code[codeIndex] != '\n')
+ {
+ nextSymbol();
+ }
+ state = State::SUCCESS;
+ return std::string(code, start, codeIndex-start);
+ }
+ if(code[codeIndex] == '*')
+ {
+ nextSymbol();
+ bool flag = true;
+ while(flag)
+ {
+ while(code[codeIndex] != '*' && !isAtEOF())
+ {
+ nextSymbol();
+ }
+
+ if(isAtEOF())
+ {
+ state = State::ERROR;
+ return "";
+ }
+
+ nextSymbol();
+ if(code[codeIndex] == '/')
+ {
+ nextSymbol();
+ flag = false;
+ }
+ }
+ state = State::SUCCESS;
+ return std::string(code, start, codeIndex-start);
+ }
+ }
+
+ state = State::FAIL;
+ return "";
+}
+
+std::string Tokenizer::parseString()
+{
+ // not a string
+ if(code[codeIndex] != '\'' && code[codeIndex] != '"' )
+ {
+ state = State::FAIL;
+ return "";
+ }
+
+ const char bound = code[codeIndex];
+ const unsigned start = codeIndex;
+
+ nextSymbol();
+ while(true)
+ {
+ while(code[codeIndex] != bound && !isAtEOF() && code[codeIndex] != '\n')
+ {
+ nextSymbol();
+ }
+
+ if(code[codeIndex] == bound)
+ {
+ // escaping character
+ if(code[codeIndex-1] != '\\')
+ {
+ nextSymbol();
+ state = State::SUCCESS;
+ return std::string(code, start, codeIndex-start);
+ }
+ else
+ {
+ codeIndex++;
+ }
+ }
+ else break;
+ }
+
+ // not a correct string
+ state = State::ERROR;
+ return "";
+}
+
+Token Tokenizer::parseKeyword()
+{
+ if(!isLowerCase(code[codeIndex]))
+ {
+ state = State::FAIL;
+ return produceToken(TokenType::INVALID);
+ }
+
+ const unsigned start = codeIndex;
+ nextSymbol();
+ while(isLowerCase(code[codeIndex]) || isDigit(code[codeIndex]) || code[codeIndex] == '_')
+ {
+ nextSymbol();
+ }
+
+ const std::string key = std::string(code, start, codeIndex-start);
+ const auto keyword = keywords.find(key);
+
+ if(keyword == keywords.end())
+ {
+ column -= codeIndex-start;
+ codeIndex = start;
+ state = State::FAIL;
+ return produceToken(TokenType::INVALID);
+ }
+
+ state = State::SUCCESS;
+ return produceToken(keyword->second, keyword->first);
+}
+
+Token Tokenizer::parsePreprocessor()
+{
+ // not a preprocessor
+ if(code[codeIndex] != '#')
+ {
+ state = State::FAIL;
+ return produceToken(TokenType::INVALID);
+ }
+
+ const unsigned start = codeIndex;
+ nextSymbol();
+ while(isLowerCase(code[codeIndex]))
+ {
+ nextSymbol();
+ }
+
+ const std::string key = std::string(code, start, codeIndex-start);
+ const auto preproc = preprocessors.find(key);
+
+ if(preproc == preprocessors.end())
+ {
+ column -= codeIndex-start;
+ codeIndex = start;
+ state = State::FAIL;
+ return produceToken(TokenType::INVALID);
+ }
+ state = State::SUCCESS;
+ return produceToken(preproc->second, preproc->first);
+}
+
+std::string Tokenizer::parseIdentifier()
+{
+ if(!isLowerCase(code[codeIndex]) && !isCapitalCase(code[codeIndex]) && code[codeIndex] != '_')
+ {
+ state = State::FAIL;
+ return "";
+ }
+
+ const unsigned start = codeIndex;
+
+ nextSymbol();
+ while(isLowerCase(code[codeIndex]) || isCapitalCase(code[codeIndex]) ||
+ isDigit(code[codeIndex]) || code[codeIndex] == '_')
+ {
+ nextSymbol();
+ }
+
+ state = State::SUCCESS;
+ return std::string(code, start, codeIndex-start);
+}
+
+Token Tokenizer::produceToken(TokenType type, std::string lexeme, double val)
+{
+ return Token{type, line, lexeme, val};
+}
+
+Token Tokenizer::produceToken(TokenType type)
+{
+ switch(type)
+ {
+ case TokenType::LEFT_PAREN: return produceToken(type, "(");
+ case TokenType::RIGHT_PAREN: return produceToken(type, ")");
+ case TokenType::LEFT_BRACKET: return produceToken(type, "[");
+ case TokenType::RIGHT_BRACKET: return produceToken(type, "]");
+ case TokenType::LEFT_CUR_BRAC: return produceToken(type, "{");
+ case TokenType::RIGHT_CUR_BRAC: return produceToken(type, "}");
+ case TokenType::PLUS: return produceToken(type, "+");
+ case TokenType::MINUS: return produceToken(type, "-");
+ case TokenType::MULTIPLICATION: return produceToken(type, "*");
+ case TokenType::DIVIDE: return produceToken(type, "/");
+ case TokenType::MODULO: return produceToken(type, "%");
+ case TokenType::LESSER: return produceToken(type, "<");
+ case TokenType::GREATER: return produceToken(type, ">");
+ case TokenType::ASSIGN: return produceToken(type, "=");
+ case TokenType::SEMI_COLON: return produceToken(type, ";");
+ case TokenType::QUESTION_MARK: return produceToken(type, "?");
+ case TokenType::EXCLAMATION_MARK: return produceToken(type, "!");
+ case TokenType::COLON: return produceToken(type, ":");
+ case TokenType::BITWISE_AND: return produceToken(type, "&");
+ case TokenType::BITWISE_OR: return produceToken(type, "|");
+ case TokenType::BITWISE_XOR: return produceToken(type, "^");
+ case TokenType::BITWISE_NOT: return produceToken(type, "~");
+ case TokenType::DOT: return produceToken(type, ".");
+ case TokenType::SCOPE: return produceToken(type, "::");
+ case TokenType::PLUS_PLUS: return produceToken(type, "++");
+ case TokenType::MINUS_MINUS: return produceToken(type, "--");
+ case TokenType::PTR_ARROW: return produceToken(type, "->");
+ case TokenType::LEFT_BITWISE_SHIFT: return produceToken(type, "<<");
+ case TokenType::RIGHT_BITWISE_SHIFT: return produceToken(type, ">>");
+ case TokenType::EQUAL: return produceToken(type, "==");
+ case TokenType::NOT_EQUAL: return produceToken(type, "!=");
+ case TokenType::LESS_EQUAL: return produceToken(type, "<=");
+ case TokenType::GREATER_EQUAL: return produceToken(type, ">=");
+ case TokenType::LOGIC_AND: return produceToken(type, "&&");
+ case TokenType::LOGIC_OR: return produceToken(type, "||");
+ case TokenType::MOD_EQUAL: return produceToken(type, "%=");
+ case TokenType::MULT_EQUAL: return produceToken(type, "*=");
+ case TokenType::DIV_EQUAL: return produceToken(type, "/=");
+ case TokenType::PLUS_EQUAL: return produceToken(type, "+=");
+ case TokenType::MINUS_EQUAL: return produceToken(type, "-=");
+ case TokenType::BIT_AND_EQUAL: return produceToken(type, "&=");
+ case TokenType::BIT_OR_EQUAL: return produceToken(type, "|=");
+ case TokenType::BIT_XOR_EQUAL: return produceToken(type, "^=");
+ case TokenType::LEFT_SHIFT_EQUAL: return produceToken(type, "<<=");
+ case TokenType::RIGHT_SHIFT_EQUAL: return produceToken(type, ">>=");
+ default: return produceToken(type, "");
+ }
+}
+
+Token Tokenizer::nextToken()
+{
+ if(isAtEOF())
+ {
+ return produceToken(TokenType::Eof);
+ }
+
+ skipWhiteSpaces();
+
+ // comments
+ std::string comment = parseComment();
+ if(isStateSuccess())
+ {
+ return produceToken(TokenType::COMMENT, comment);
+ }
+
+ // preprocessors
+ Token preproc = parsePreprocessor();
+ if(isStateSuccess())
+ {
+ return preproc;
+ }
+
+ switch(code[codeIndex])
+ {
+ case '(':
+ nextSymbol();
+ return produceToken(TokenType::LEFT_PAREN);
+ case ')':
+ nextSymbol();
+ return produceToken(TokenType::RIGHT_PAREN);
+ case '[':
+ nextSymbol();
+ return produceToken(TokenType::LEFT_BRACKET);
+ case ']':
+ nextSymbol();
+ return produceToken(TokenType::RIGHT_BRACKET);
+ case '{':
+ nextSymbol();
+ return produceToken(TokenType::LEFT_CUR_BRAC);
+ case '}':
+ nextSymbol();
+ return produceToken(TokenType::RIGHT_CUR_BRAC);
+ case '+':
+ nextSymbol();
+ if(match('+'))
+ {
+ nextSymbol();
+ return produceToken(TokenType::PLUS_PLUS);
+ }
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::PLUS_EQUAL);
+ }
+ return produceToken(TokenType::PLUS);
+ case '-':
+ nextSymbol();
+ if(match('-'))
+ {
+ nextSymbol();
+ return produceToken(TokenType::MINUS_MINUS);
+ }
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::MINUS_EQUAL);
+ }
+ if(match('>'))
+ {
+ nextSymbol();
+ return produceToken(TokenType::PTR_ARROW);
+ }
+ return produceToken(TokenType::MINUS);
+ case '*':
+ nextSymbol();
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::MULT_EQUAL);
+ }
+ return produceToken(TokenType::MULTIPLICATION);
+ case '/':
+ nextSymbol();
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::DIV_EQUAL);
+ }
+ return produceToken(TokenType::DIVIDE);
+ case '%':
+ nextSymbol();
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::MOD_EQUAL);
+ }
+ return produceToken(TokenType::MODULO);
+ case '<':
+ nextSymbol();
+ if(match('<'))
+ {
+ nextSymbol();
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::LEFT_SHIFT_EQUAL);
+ }
+ return produceToken(TokenType::LEFT_BITWISE_SHIFT);
+ }
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::LESS_EQUAL);
+ }
+ return produceToken(TokenType::LESSER);
+ case '>':
+ nextSymbol();
+ if(match('>'))
+ {
+ nextSymbol();
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::RIGHT_SHIFT_EQUAL);
+ }
+ return produceToken(TokenType::RIGHT_BITWISE_SHIFT);
+ }
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::GREATER_EQUAL);
+ }
+ return produceToken(TokenType::GREATER);
+ case '=':
+ nextSymbol();
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::EQUAL);
+ }
+ return produceToken(TokenType::ASSIGN);
+ case ';':
+ nextSymbol();
+ return produceToken(TokenType::SEMI_COLON);
+ case '?':
+ nextSymbol();
+ return produceToken(TokenType::QUESTION_MARK);
+ case '!':
+ nextSymbol();
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::NOT_EQUAL);
+ }
+ return produceToken(TokenType::EXCLAMATION_MARK);
+ case ':':
+ nextSymbol();
+ if(match(':'))
+ {
+ nextSymbol();
+ return produceToken(TokenType::SCOPE);
+ }
+ return produceToken(TokenType::COLON);
+ case '&':
+ nextSymbol();
+ if(match('&'))
+ {
+ nextSymbol();
+ return produceToken(TokenType::LOGIC_AND);
+ }
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::BIT_AND_EQUAL);
+ }
+ return produceToken(TokenType::BITWISE_AND);
+ case '|':
+ nextSymbol();
+ if(match('|'))
+ {
+ nextSymbol();
+ return produceToken(TokenType::LOGIC_AND);
+ }
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::BIT_OR_EQUAL);
+ }
+ return produceToken(TokenType::BITWISE_OR);
+ case '^':
+ nextSymbol();
+ if(match('='))
+ {
+ nextSymbol();
+ return produceToken(TokenType::BIT_XOR_EQUAL);
+ }
+ return produceToken(TokenType::BITWISE_XOR);
+ case '~':
+ nextSymbol();
+ return produceToken(TokenType::BITWISE_NOT);
+ case '.':
+ nextSymbol();
+ return produceToken(TokenType::DOT);
+ default: break;
+ }
+
+ // number literals
+ double num = parseNumber();
+ if(isStateSuccess())
+ {
+ return produceToken(TokenType::NUMBER, "", num);
+ }
+ else if(isStateError())
+ {
+ return produceToken(TokenType::INVALID);
+ }
+
+ // string literals
+ std::string lex = parseString();
+ if(isStateSuccess())
+ {
+ return produceToken(TokenType::STRING, lex);
+ }
+ else if(isStateError())
+ {
+ return produceToken(TokenType::INVALID);
+ }
+
+ // keywords
+ Token tkn = parseKeyword();
+ if(isStateSuccess())
+ {
+ return tkn;
+ }
+
+ // identifiers
+ std::string identifier = parseIdentifier();
+ if(isStateSuccess())
+ {
+ return produceToken(TokenType::IDENTIFIER, identifier);
+ }
+
+ return produceToken(TokenType::INVALID);
+}
+
diff --git a/homework/81625/cpp2html/src/Lexer.h b/homework/81625/cpp2html/src/Lexer.h
new file mode 100644
index 0000000..92c2f53
--- /dev/null
+++ b/homework/81625/cpp2html/src/Lexer.h
@@ -0,0 +1,223 @@
+#ifndef LEXER_H
+#define LEXER_H
+
+#include <vector>
+#include <map>
+#include <string>
+
+enum TokenType
+{
+// Single character tokens
+ LEFT_PAREN = 1, // (
+ RIGHT_PAREN, // )
+ LEFT_BRACKET, // [
+ RIGHT_BRACKET, // ]
+ LEFT_CUR_BRAC, // {
+ RIGHT_CUR_BRAC, // }
+ PLUS, // +
+ MINUS, // -
+ MULTIPLICATION, // *
+ DIVIDE, // /
+ MODULO, // %
+ LESSER, // <
+ GREATER, // >
+ ASSIGN, // =
+ SEMI_COLON, // ;
+ QUESTION_MARK, // ?
+ EXCLAMATION_MARK, // !
+ COLON, // :
+ BITWISE_AND, // &
+ BITWISE_OR, // |
+ BITWISE_XOR, // ^
+ BITWISE_NOT, // ~
+ DOT, // .
+
+// Double character tokens
+ SCOPE, // ::
+ PLUS_PLUS, // ++
+ MINUS_MINUS, // --
+ PTR_ARROW, // ->
+ LEFT_BITWISE_SHIFT, // <<
+ RIGHT_BITWISE_SHIFT,// >>
+ EQUAL, // ==
+ NOT_EQUAL, // !=
+ LESS_EQUAL, // <=
+ GREATER_EQUAL, // >=
+ LOGIC_AND, // &&
+ LOGIC_OR, // ||
+ MOD_EQUAL, // %=
+ MULT_EQUAL, // *=
+ DIV_EQUAL, // /=
+ PLUS_EQUAL, // +=
+ MINUS_EQUAL, // -=
+ BIT_AND_EQUAL, // &=
+ BIT_OR_EQUAL, // |=
+ BIT_XOR_EQUAL, // ^=
+
+// Three character tokens
+ LEFT_SHIFT_EQUAL, // <<=
+ RIGHT_SHIFT_EQUAL, // >>=
+
+// Keyword Tokens
+ ALIGNAS,
+ ALIGNOF,
+ AND,
+ AND_EQ,
+ ASM,
+ AUTO,
+ BITAND,
+ BITOR,
+ BOOL,
+ BREAK,
+ CASE,
+ CATCH,
+ CHAR,
+ CHAR16_T,
+ CHAR32_T,
+ CLASS,
+ COMPL,
+ CONST,
+ CONSTEXPR,
+ CONST_CAST,
+ CONTINUE,
+ DECLTYPE,
+ DEFAULT,
+ DELETE,
+ DO,
+ DOUBLE,
+ DYNAMIC_CAST,
+ ELSE,
+ ENUM,
+ EXPLICIT,
+ EXPORT,
+ EXTERN,
+ FALSE,
+ FLOAT,
+ FOR,
+ FRIEND,
+ GOTO,
+ IF,
+ INLINE,
+ INT,
+ LONG,
+ MUTABLE,
+ NAMESPACE,
+ NEW,
+ NOEXCEPT,
+ NOT,
+ NOT_EQ,
+ NULLPTR,
+ OPERATOR,
+ OR,
+ OR_EQ,
+ PRIVATE,
+ PROTECTED,
+ PUBLIC,
+ REGISTER,
+ REINTERPRET_CAST,
+ RETURN,
+ SHORT,
+ SIGNED,
+ SIZEOF,
+ STATIC,
+ STATIC_ASSERT,
+ STATIC_CAST,
+ STRUCT,
+ SWITCH,
+ TEMPLATE,
+ THIS,
+ THREAD_LOCAL,
+ THROW,
+ TRUE,
+ TRY,
+ TYPEDEF,
+ TYPEID,
+ TYPENAME,
+ UNION,
+ UNSIGNED,
+ USING,
+ VIRTUAL,
+ VOID,
+ VOLATILE,
+ WCHAR_T,
+ WHILE,
+ XOR,
+ XOR_EQ,
+
+ // preprocessors
+ PRE_DEFINE,
+ PRE_UNDEF,
+ PRE_INCLUDE,
+ PRE_IF,
+ PRE_IFDEF,
+ PRE_IFNDEF,
+ PRE_ELSE,
+ PRE_ELIF,
+ PRE_ENDIF,
+ PRE_LINE,
+ PRE_ERROR,
+ PRE_PRAGMA,
+
+ NUMBER,
+ IDENTIFIER,
+ STRING,
+ COMMENT,
+ Eof,
+ INVALID
+};
+
+enum State
+{
+ FAIL,
+ SUCCESS,
+ ERROR
+};
+
+struct Token
+{
+ TokenType type;
+ unsigned line;
+ std::string lexeme;
+ double value;
+};
+
+class Tokenizer
+{
+private:
+ const char* code;
+ unsigned line;
+ unsigned column;
+ unsigned codeIndex;
+ State state;
+ std::map<std::string, TokenType> keywords;
+ std::map<std::string, TokenType> preprocessors;
+
+public:
+ Tokenizer(const char* code);
+ Token nextToken();
+ Token produceToken(TokenType type, std::string lexeme, double val = 0.0);
+ Token produceToken(TokenType type);
+
+ bool isAtEOF() const;
+ bool match(char c) const;
+ bool isStateError() const;
+ bool isStateSuccess() const;
+ bool tokenize(std::vector<Token> &tokens);
+
+ double parseNumber();
+ std::string parseComment();
+ std::string parseString();
+ Token parseKeyword();
+ Token parsePreprocessor();
+ std::string parseIdentifier();
+
+ void skipWhiteSpaces();
+ void nextSymbol();
+ void prevSymbol();
+
+};
+
+//#include "Lexer.cpp"
+
+#endif
+
diff --git a/homework/81625/cpp2html/src/main.cpp b/homework/81625/cpp2html/src/main.cpp
new file mode 100644
index 0000000..92f4d30
--- /dev/null
+++ b/homework/81625/cpp2html/src/main.cpp
@@ -0,0 +1,107 @@
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include "Lexer.h"
+
+void printTokens(std::vector<Token> &tokens)
+{
+ for(int i = 0;i<tokens.size();i++)
+ {
+ std::cout<<tokens[i].type<<" "<<tokens[i].lexeme <<" on line " << tokens[i].line <<std::endl;
+ }
+}
+
+void cpp2html(std::vector<Token> &tokens, const char* code)
+{
+ std::ofstream out("../cpp2.html");
+ std::string header = "<!DOCTYPE html>\n"
+ "<html lang=\"en\">\n"
+ "<head>\n"
+ " <style>\n"
+ " body {\n"
+ " font-size: 20px;\n"
+ " }\n\n"
+ " .number {\n"
+ " color: pink;\n"
+ " }\n\n"
+ " .string {\n"
+ " color: blue;\n"
+ " }\n\n"
+ " .keyword {\n"
+ " color: purple;\n"
+ " font-weight: bold;\n"
+ " }\n\n"
+ " .operator {\n"
+ " color: red;\n"
+ " }\n\n"
+ " .comment {\n"
+ " color: gray;\n"
+ " font-style: italic;\n"
+ " }\n\n"
+ " .preprocessor {\n"
+ " color: green;\n"
+ " font-weight: bold;\n"
+ " }\n\n"
+ " </style>\n"
+ "</head>\n"
+ "<body>\n";
+ out << header;
+ unsigned codeInd = 0;
+ for(int i = 0;i < tokens.size();i++)
+ {
+ while(code[codeInd] == ' ' || code[codeInd] == '\t' || code[codeInd] == '\n')
+ {
+ if(code[codeInd] == '\n') out << "<br>";
+ else out << "&nbsp";
+ //else out <<
+ ++codeInd;
+ }
+ if(tokens[i].type == TokenType::NUMBER)
+ {
+ out << "<span class=\"number\">" << tokens[i].value <<"</span>";
+ }
+ else if(tokens[i].type == TokenType::STRING)
+ {
+ out << "<span class=\"string\">" << tokens[i].lexeme <<"</span>";
+ }
+ else if(tokens[i].type == TokenType::COMMENT)
+ {
+ out << "<span class=\"comment\">" << tokens[i].lexeme <<"</span>";
+ }
+ else if(tokens[i].type <= TokenType::RIGHT_SHIFT_EQUAL)
+ {
+ out << "<span class=\"operator\">" << tokens[i].lexeme <<"</span>";
+ }
+ else if(tokens[i].type <= TokenType::XOR_EQ)
+ {
+ out << "<span class=\"keyword\">" << tokens[i].lexeme <<"</span>";
+ }
+ else if(tokens[i].type <= TokenType::PRE_PRAGMA)
+ {
+ out << "<span class=\"preprocessor\">" << tokens[i].lexeme <<"</span>";
+ }
+ else
+ {
+ out << tokens[i].lexeme;
+ }
+ codeInd += tokens[i].lexeme.length();
+ }
+ out << "\n</body>\n</html>";
+ out.close();
+}
+
+int main()
+{
+ char code[] = "#include<iostream>\nbool isCapitalCase(char c)\n{\n return c >= 'A' && c <= 'Z';\n}\nm_KeyWordsTable[\"break\"] = TokenType::Break;\n// this is a comment test\n"
+ "/* another one */";
+ Tokenizer tokenizer(code);
+ std::vector<Token> tokens;
+
+ if(tokenizer.tokenize(tokens))
+ {
+ cpp2html(tokens, code);
+ }
+ //printTokens(tokens);
+ return 0;
+}
+