Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // LEXER_HPP
- #pragma once
- #include <stack>
- #include <string>
- #include <variant>
- namespace
- {
- enum class TokenTypes
- {
- NUMBER,
- END,
- MULTIPLY = '*',
- DIVIDE = '/',
- ADD = '+',
- SUBTRACT = '-',
- LEFT_PARANTHESIS = '(',
- RIGHT_PARANTHESIS = ')',
- EXPONENT = '^'
- };
- enum class Precedence
- {
- END,
- NUMBER = END,
- PARANTHESIS,
- ADDSUB,
- MULDIV,
- EXPONENT
- };
- }
- struct Token
- {
- Token() : type(TokenTypes::END), contents(-1), order(Precedence::END)
- {
- }
- Token(TokenTypes Type, std::variant<int, char> Contents) : type(Type), contents(Contents), order(Precedence::END)
- {
- switch (type)
- {
- case TokenTypes::END:
- order = Precedence::END;
- break;
- case TokenTypes::NUMBER:
- order = Precedence::NUMBER;
- break;
- case TokenTypes::LEFT_PARANTHESIS:
- case TokenTypes::RIGHT_PARANTHESIS:
- order = Precedence::PARANTHESIS;
- break;
- case TokenTypes::ADD:
- case TokenTypes::SUBTRACT:
- order = Precedence::ADDSUB;
- break;
- case TokenTypes::MULTIPLY:
- case TokenTypes::DIVIDE:
- order = Precedence::MULDIV;
- break;
- case TokenTypes::EXPONENT:
- order = Precedence::EXPONENT;
- break;
- }
- }
- std::string toString()
- {
- if (contents.index() == 0)
- return std::to_string(std::get<int>(contents));
- return std::string{ std::get<char>(contents) };
- }
- bool isLeftAssociative()
- {
- switch (type)
- {
- case TokenTypes::SUBTRACT: case TokenTypes::DIVIDE: case TokenTypes::ADD: case TokenTypes::MULTIPLY:
- return true;
- default:
- return false;
- }
- }
- auto operator<=>(const Token& other) const
- {
- return order <=> other.order;
- }
- auto operator==(const Token& other) const
- {
- return order == other.order;
- }
- auto operator!=(const Token& other) const
- {
- return order != other.order;
- }
- auto operator==(const TokenTypes& other) const
- {
- return type == other;
- }
- auto operator!=(const TokenTypes& other) const
- {
- return type != other;
- }
- TokenTypes type;
- Precedence order;
- std::variant<int, char> contents;
- };
- class Lexer
- {
- public:
- std::string read(std::string input);
- private:
- std::stack<Token> outputStack;
- std::stack<Token> operatorStack;
- };
- // LEXER_CPP
- #include "Lexer.h"
- #include <sstream>
- #include <iostream>
- std::string Lexer::read(std::string input)
- {
- std::stringstream inputStream(input);
- char token;
- Token lastOperator;
- while (!inputStream.eof())
- {
- token = inputStream.get();
- Token inOperator = Token{ TokenTypes{token}, token };
- switch (token)
- {
- case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
- if (!outputStack.empty())
- {
- if (lastOperator == TokenTypes::NUMBER)
- {
- inOperator = Token{ TokenTypes::NUMBER, std::stoi(inOperator.toString() + lastOperator.toString()) };
- outputStack.pop();
- outputStack.push(inOperator);
- break;
- }
- }
- inOperator = Token{ TokenTypes::NUMBER, (int)(token - '0') };
- outputStack.push(inOperator);
- break;
- case '+': case '-': case '*': case '/': case '^':
- while (!operatorStack.empty() && (operatorStack.top() > inOperator || (operatorStack.top() == inOperator && inOperator.isLeftAssociative())) && operatorStack.top() != TokenTypes{ '(' })
- {
- outputStack.push(operatorStack.top());
- operatorStack.pop();
- }
- operatorStack.push(inOperator);
- break;
- case '(':
- operatorStack.push(inOperator);
- break;
- case ')':
- while (operatorStack.top() != TokenTypes{ '(' })
- {
- outputStack.push(operatorStack.top());
- operatorStack.pop();
- }
- if (operatorStack.top() == TokenTypes{ '(' })
- operatorStack.pop();
- break;
- }
- lastOperator = inOperator;
- }
- while (!operatorStack.empty())
- {
- outputStack.push(operatorStack.top());
- operatorStack.pop();
- }
- std::string outputString;
- size_t stackSize = outputStack.size();
- for (size_t i = 0; i < stackSize; i++)
- {
- outputString += outputStack.top().toString() + ' ';
- outputStack.pop();
- }
- outputString = std::string{ outputString.rbegin(), outputString.rend() };
- return outputString;
- }
- // MAIN_CPP
- #include <iostream>
- #include "Lexer.h"
- int main()
- {
- Lexer lexer;
- std::cout << lexer.read("134 + 4 * 2 / (1 - 5) ^ 2 ^ 3");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement