Advertisement
Ardente

Lexer Demonstration

Aug 16th, 2020
198
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.30 KB | None | 0 0
  1. // LEXER_HPP
  2. #pragma once
  3.  
  4. #include <stack>
  5. #include <string>
  6. #include <variant>
  7.  
  8. namespace
  9. {
  10.     enum class TokenTypes
  11.     {
  12.         NUMBER,
  13.         END,
  14.         MULTIPLY = '*',
  15.         DIVIDE = '/',
  16.         ADD = '+',
  17.         SUBTRACT = '-',
  18.         LEFT_PARANTHESIS = '(',
  19.         RIGHT_PARANTHESIS = ')',
  20.         EXPONENT = '^'
  21.     };
  22.  
  23.     enum class Precedence
  24.     {
  25.         END,
  26.         NUMBER = END,
  27.         PARANTHESIS,
  28.         ADDSUB,
  29.         MULDIV,
  30.         EXPONENT
  31.     };
  32. }
  33.  
  34. struct Token
  35. {
  36.     Token() : type(TokenTypes::END), contents(-1), order(Precedence::END)
  37.     {
  38.  
  39.     }
  40.  
  41.     Token(TokenTypes Type, std::variant<int, char> Contents) : type(Type), contents(Contents), order(Precedence::END)
  42.     {
  43.         switch (type)
  44.         {
  45.         case TokenTypes::END:
  46.             order = Precedence::END;
  47.             break;
  48.  
  49.         case TokenTypes::NUMBER:
  50.             order = Precedence::NUMBER;
  51.             break;
  52.  
  53.         case TokenTypes::LEFT_PARANTHESIS:
  54.         case TokenTypes::RIGHT_PARANTHESIS:
  55.             order = Precedence::PARANTHESIS;
  56.             break;
  57.  
  58.         case TokenTypes::ADD:
  59.         case TokenTypes::SUBTRACT:
  60.             order = Precedence::ADDSUB;
  61.             break;
  62.  
  63.         case TokenTypes::MULTIPLY:
  64.         case TokenTypes::DIVIDE:
  65.             order = Precedence::MULDIV;
  66.             break;
  67.  
  68.         case TokenTypes::EXPONENT:
  69.             order = Precedence::EXPONENT;
  70.             break;
  71.         }
  72.     }
  73.  
  74.     std::string toString()
  75.     {
  76.         if (contents.index() == 0)
  77.             return std::to_string(std::get<int>(contents));
  78.  
  79.         return std::string{ std::get<char>(contents) };
  80.     }
  81.  
  82.     bool isLeftAssociative()
  83.     {
  84.         switch (type)
  85.         {
  86.         case TokenTypes::SUBTRACT: case TokenTypes::DIVIDE: case TokenTypes::ADD: case TokenTypes::MULTIPLY:
  87.             return true;
  88.  
  89.         default:
  90.             return false;
  91.         }
  92.     }
  93.  
  94.     auto operator<=>(const Token& other) const
  95.     {
  96.         return order <=> other.order;
  97.     }
  98.  
  99.     auto operator==(const Token& other) const
  100.     {
  101.         return order == other.order;
  102.     }
  103.  
  104.     auto operator!=(const Token& other) const
  105.     {
  106.         return order != other.order;
  107.     }
  108.  
  109.     auto operator==(const TokenTypes& other) const
  110.     {
  111.         return type == other;
  112.     }
  113.  
  114.     auto operator!=(const TokenTypes& other) const
  115.     {
  116.         return type != other;
  117.     }
  118.  
  119.     TokenTypes type;
  120.     Precedence order;
  121.  
  122.     std::variant<int, char> contents;
  123. };
  124.  
  125. class Lexer
  126. {
  127. public:
  128.  
  129.     std::string read(std::string input);
  130.  
  131. private:
  132.     std::stack<Token> outputStack;
  133.     std::stack<Token> operatorStack;
  134. };
  135.  
  136. // LEXER_CPP
  137. #include "Lexer.h"
  138.  
  139. #include <sstream>
  140. #include <iostream>
  141.  
  142. std::string Lexer::read(std::string input)
  143. {
  144.     std::stringstream inputStream(input);
  145.     char token;
  146.  
  147.     Token lastOperator;
  148.     while (!inputStream.eof())
  149.     {
  150.         token = inputStream.get();
  151.  
  152.         Token inOperator = Token{ TokenTypes{token}, token };
  153.  
  154.         switch (token)
  155.         {
  156.         case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
  157.             if (!outputStack.empty())
  158.             {
  159.                 if (lastOperator == TokenTypes::NUMBER)
  160.                 {
  161.                     inOperator = Token{ TokenTypes::NUMBER, std::stoi(inOperator.toString() + lastOperator.toString()) };
  162.                     outputStack.pop();
  163.                     outputStack.push(inOperator);
  164.                     break;
  165.                 }
  166.             }
  167.  
  168.             inOperator = Token{ TokenTypes::NUMBER, (int)(token - '0') };
  169.             outputStack.push(inOperator);
  170.             break;
  171.  
  172.         case '+': case '-': case '*': case '/': case '^':
  173.             while (!operatorStack.empty() && (operatorStack.top() > inOperator || (operatorStack.top() == inOperator && inOperator.isLeftAssociative())) && operatorStack.top() != TokenTypes{ '(' })
  174.             {
  175.                 outputStack.push(operatorStack.top());
  176.                 operatorStack.pop();
  177.             }
  178.  
  179.             operatorStack.push(inOperator);
  180.             break;
  181.  
  182.         case '(':
  183.             operatorStack.push(inOperator);
  184.             break;
  185.  
  186.         case ')':
  187.             while (operatorStack.top() != TokenTypes{ '(' })
  188.             {
  189.                 outputStack.push(operatorStack.top());
  190.                 operatorStack.pop();
  191.             }
  192.  
  193.             if (operatorStack.top() == TokenTypes{ '(' })
  194.                 operatorStack.pop();
  195.             break;
  196.         }
  197.  
  198.         lastOperator = inOperator;
  199.     }
  200.  
  201.     while (!operatorStack.empty())
  202.     {
  203.         outputStack.push(operatorStack.top());
  204.         operatorStack.pop();
  205.     }
  206.  
  207.     std::string outputString;
  208.  
  209.     size_t stackSize = outputStack.size();
  210.     for (size_t i = 0; i < stackSize; i++)
  211.     {
  212.         outputString += outputStack.top().toString() + ' ';
  213.         outputStack.pop();
  214.     }
  215.  
  216.     outputString = std::string{ outputString.rbegin(), outputString.rend() };
  217.  
  218.     return outputString;
  219. }
  220.  
  221. // MAIN_CPP
  222. #include <iostream>
  223.  
  224. #include "Lexer.h"
  225.  
  226. int main()
  227. {
  228.     Lexer lexer;
  229.     std::cout << lexer.read("134 + 4 * 2 / (1 - 5) ^ 2 ^ 3");
  230. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement