Advertisement
Guest User

Untitled

a guest
Feb 24th, 2020
192
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.79 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <utility>
  4. #include <variant>
  5. #include <sstream>
  6. #include <algorithm>
  7. #include <vector>
  8. #include <unordered_set>
  9. #include "StreamTable.h"
  10.  
  11. struct LexicalError : public std::runtime_error {
  12.     explicit LexicalError(const std::string& what) : std::runtime_error(what) {
  13.     }
  14. };
  15.  
  16. struct SymbolToken {
  17.     SymbolToken(const std::string& str) {
  18.         name = str;
  19.     }
  20.     SymbolToken(char c) {
  21.         name += c;
  22.     }
  23.     std::string name;
  24.     bool operator==(const SymbolToken& rhs) const {
  25.         return name == rhs.name;
  26.     }
  27. };
  28.  
  29. struct QuoteToken {
  30.     bool operator==(const QuoteToken& rhs) const {
  31.         return true;
  32.     }
  33. };
  34.  
  35. struct DotToken {
  36.     bool operator==(const DotToken& rhs) const {
  37.         return true;
  38.     }
  39. };
  40.  
  41. enum class BracketToken { OPEN, CLOSE };
  42.  
  43. enum class BooleanToken { TRUE, FALSE };
  44.  
  45. struct ConstantToken {
  46.     int value;
  47.     bool operator==(const ConstantToken& rhs) const {
  48.         return value == rhs.value;
  49.     }
  50. };
  51.  
  52. typedef std::variant<ConstantToken, BracketToken, BooleanToken, QuoteToken, DotToken, SymbolToken>
  53.     Token;
  54.  
  55. class Tokenizer {
  56.     std::vector<Token> tokens_;
  57.     bool is_end_ = false;
  58.     bool is_new_variable = false;
  59.     bool is_method_declaration = false;
  60.     std::istream* in_;
  61.     std::unordered_set<std::string> variables;
  62.     std::unordered_set<std::string> operators{
  63.         "+",
  64.         "if",
  65.         "boolean?",
  66.         "quote",
  67.         "not",
  68.         "and",
  69.         ">",
  70.         "<",
  71.         "=",
  72.         "define",
  73.         "set!",
  74.         "or",
  75.         "number?",
  76.         ">=",
  77.         "<=",
  78.         "*",
  79.         "-",
  80.         "/",
  81.         "max",
  82.         "min",
  83.         "abs",
  84.         "symbol?",
  85.         "pair?",
  86.         "null?",
  87.         "list?",
  88.         "cons",
  89.         "car",
  90.         "cdr",
  91.         "set-car!",
  92.         "set-cdr!",
  93.         "list",
  94.         "list-ref",
  95.         "list-tail",
  96.         "lambda",
  97.         "eval"};
  98. public:
  99.     Tokenizer(std::istream* in) {
  100.         in_ = in;
  101.         Next();
  102.     }
  103.     bool IsEnd() {
  104.         return is_end_;
  105.     }
  106.  
  107.     void Next(bool lexicalCheck = false) {
  108.         char c, fc;
  109.         bool is_successfull_token = false;
  110.         while (!is_successfull_token) {
  111.             if (!in_->get(c)) {
  112.                 is_end_ = true;
  113.                 break;
  114.             }
  115.             fc = c;
  116.             is_successfull_token = true;
  117.             std::vector<char> except_chars = {'+', '-', '*', '>', '<', '=', '/'};
  118.             switch (fc) {
  119.                 case ')':
  120.                     tokens_.emplace_back(BracketToken::CLOSE);
  121.                     break;
  122.                 case '(':
  123.                     tokens_.emplace_back(BracketToken::OPEN);
  124.                     break;
  125.                 case '\'':
  126.                     tokens_.emplace_back(QuoteToken());
  127.                     break;
  128.                 case '.':
  129.                     tokens_.emplace_back(DotToken());
  130.                     break;
  131.                 case '#':
  132.                     if (in_->peek() != EOF && (in_->peek() == 't' || in_->peek() == 'f')) {
  133.                         in_->get(fc);
  134.                         tokens_.emplace_back(fc == 't' ? BooleanToken::TRUE : BooleanToken::FALSE);
  135.                         break;
  136.                     }
  137.                 default:
  138.                     if (std::isdigit(fc) || ((fc == '-' || fc == '+') && in_->peek() != EOF &&
  139.                                              std::isdigit(in_->peek()))) {
  140.                         int value;
  141.                         if (fc == '-' || fc == '+') {
  142.                             value = 0;
  143.                         } else {
  144.                             value = fc - '0';
  145.                         }
  146.                         while (in_->peek() != EOF && std::isdigit(in_->peek())) {
  147.                             in_->get(c);
  148.                             value *= 10;
  149.                             value += c - '0';
  150.                         }
  151.                         if (fc == '-') {
  152.                             value *= -1;
  153.                         }
  154.                         if (lexicalCheck) {
  155.                             std::string next_chars;
  156.                             while (in_->peek() != EOF && std::isgraph(in_->peek())) {
  157.                                 in_->get(c);
  158.                                 if (c == ')')
  159.                                     break;
  160.                                 next_chars += c;
  161.                             }
  162.                             if (next_chars.length() > 0) {
  163.                                 tokens_.emplace_back(SymbolToken(std::to_string(value) + next_chars));
  164.                                 throw LexicalError("Invalid lexeme name:");
  165.                             }
  166.                         }
  167.                         tokens_.emplace_back(ConstantToken{value});
  168.                     } else if (std::isalpha(fc)) {
  169.                         std::vector<char> possible_signs = {'+', '-', '*', '?', '!'};
  170.                         std::string cur_token;
  171.                         cur_token += fc;
  172.                         while (in_->peek() != EOF &&
  173.                                (std::isdigit(in_->peek()) || std::isalpha(in_->peek()) ||
  174.                                 std::find(possible_signs.begin(), possible_signs.end(),
  175.                                           in_->peek()) != possible_signs.end())) {
  176.                             in_->get(c);
  177.                             cur_token += c;
  178.                         }
  179.                         tokens_.emplace_back(SymbolToken{cur_token});
  180.                     } else if (std::find(except_chars.begin(), except_chars.end(), fc) !=
  181.                                except_chars.end()) {
  182.                         if (in_->peek() != EOF && (in_->peek() == '=')) {
  183.                             std::string s = "ab";
  184.                             s[0] = fc;
  185.                             in_->get(s[1]);
  186.                             tokens_.emplace_back(s);
  187.                         } else {
  188.                             tokens_.emplace_back(SymbolToken(fc));
  189.                         }
  190.                     } else {
  191.                         is_successfull_token = false;
  192.                     }
  193.             }
  194.         }
  195.         if (lexicalCheck) {
  196.             if (auto pval = std::get_if<SymbolToken>(&tokens_.back())) {
  197.                 if (is_new_variable || is_method_declaration) {
  198.                     if (is_new_variable && variables.find(pval->name) != variables.end())
  199.                         throw LexicalError("Repeated declaration: ");
  200.                     else if (operators.find(pval->name) != operators.end())
  201.                         throw LexicalError("Invalid use of operator: ");
  202.                     else
  203.                         variables.insert(pval->name);
  204.                     is_new_variable = false;
  205.                 } else {
  206.                     if (operators.find(pval->name) == operators.end() && variables.find(pval->name) == variables.end())
  207.                         throw LexicalError("Unknown lexeme: ");
  208.                     if (pval->name == "define" || pval->name == "lambda")
  209.                         is_new_variable = true;
  210.                 }
  211.             } else if (is_new_variable || is_method_declaration) {
  212.                 if (fc != '(' &&  fc != ')')
  213.                     throw LexicalError("Illegal variable name: ");
  214.                 else
  215.                     is_method_declaration ^= true;
  216.             }
  217.         }
  218.     }
  219.  
  220.     Token GetToken() {
  221.         if (!tokens_.empty()) {
  222.             return tokens_.back();
  223.         }
  224.     }
  225.  
  226.     std::vector<Token> GetTokens() {
  227.         return tokens_;
  228.     }
  229.  
  230.     std::string ClassifyTokens() {
  231.         try {
  232.             while (!IsEnd()) {
  233.                 Next(true);
  234.             }
  235.             auto tokens = GetTokens();
  236.             std::stringstream table;
  237.             StreamTable st(table);
  238.             st.AddCol(5);
  239.             st.AddCol(15);
  240.             st.AddCol(20);
  241.             st.MakeBorderExt(true);
  242.             st.SetDelimRow(true, '-');
  243.             st.SetDelimCol(true, '|');
  244.             st << "Number" << "Name" << "Type";
  245.             for (int i = 0; i < tokens.size(); ++i) {
  246.                 st << i + 1 << GetTokenName(tokens[i]) << GetTokenType(tokens[i]);
  247.             }
  248.             return table.str();
  249.         } catch (LexicalError &err) {
  250.             return err.what() + GetTokenName(tokens_.back());
  251.         }
  252.     }
  253.  
  254.     std::string GetTokenType(const Token &token) {
  255.         if (auto pval = std::get_if<ConstantToken>(&token)) {
  256.             return "ConstantToken";
  257.         } else if (auto pval = std::get_if<SymbolToken>(&token)) {
  258.             return (operators.find(pval->name) == operators.end() ? "Variable" : "Operator");
  259.         } else if (auto pval = std::get_if<BooleanToken>(&token)) {
  260.             return "BooleanToken";
  261.         } else if (std::get_if<QuoteToken>(&token)) {
  262.             return "QuoteToken";
  263.         } else if (std::get_if<DotToken>(&token)) {
  264.             return "DotToken";
  265.         } else if (auto pval = std::get_if<BracketToken >(&token))
  266.             return "BracketToken";
  267.     }
  268.  
  269.     std::string GetTokenName(const Token &token) {
  270.         if (auto pval = std::get_if<ConstantToken>(&token)) {
  271.             return std::to_string(pval->value);
  272.         } else if (auto pval = std::get_if<SymbolToken>(&token)) {
  273.             return pval->name;
  274.         } else if (auto pval = std::get_if<BooleanToken>(&token)) {
  275.             return (*pval == BooleanToken::TRUE ? "#t" : "#f");
  276.         } else if (std::get_if<QuoteToken>(&token)) {
  277.             return "'";
  278.         } else if (std::get_if<DotToken>(&token)) {
  279.             return ".";
  280.         } else if (auto pval = std::get_if<BracketToken >(&token))
  281.             return (*pval == BracketToken::OPEN ? "(" : ")");
  282.     }
  283. };
  284.  
  285. std::vector<Token> Read(const std::string& string);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement