Advertisement
Guest User

stack_machine.cpp

a guest
Oct 20th, 2019
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.41 KB | None | 0 0
  1. ////////////////////////////////////////////////////////////////////////////////
  2. // Module Name:  stack_machine.h/cpp
  3. // Authors:      Sergey Shershakov
  4. // Version:      0.2.0
  5. // Date:         23.01.2017
  6. //
  7. // This is a part of the course "Algorithms and Data Structures"
  8. // provided by  the School of Software Engineering of the Faculty
  9. // of Computer Science at the Higher School of Economics.
  10. ////////////////////////////////////////////////////////////////////////////////
  11.  
  12. #include "stack_machine.h"
  13.  
  14. #include <vector>
  15. #include <sstream>
  16. #include <vector>
  17. #include <string>
  18. #include <iostream>
  19. #include <stdlib.h>
  20.  
  21. namespace xi {
  22.  
  23.     //==============================================================================
  24.     // Free functions -- helpers
  25.     //==============================================================================
  26.  
  27.     bool isNumb(const std::string& s)
  28.     {
  29.         size_t offset = 0;
  30.         if (s[offset] == '-' || (s[offset] == '+' && s.length() != 1))
  31.             ++offset;
  32.         return s.find_first_not_of("0123456789", offset) == std::string::npos;
  33.     }
  34.  
  35.     //==============================================================================
  36.     // class PlusOp
  37.     //==============================================================================
  38.  
  39.  
  40.     int PlusOp::operation(char op, int a, int b, int /*c*/) // < just commented unused argument. This does not affect the code anyhow.
  41.     {
  42.         if (op != '+')
  43.             throw std::logic_error("Operation other than Plus (+) are not supported");
  44.  
  45.         // here we just ignore unused operands
  46.         return a + b;
  47.     }
  48.  
  49.     IOperation::Arity PlusOp::getArity() const
  50.     {
  51.         return arDue;
  52.     }
  53.  
  54.     int ChoiceOp::operation(char op, int a, int b, int c)
  55.     {
  56.         if (op != '?')
  57.             throw std::logic_error("Operation other than Choise (?) are not supported");
  58.         if (a != 0)
  59.             return b;
  60.         return c;
  61.     }
  62.  
  63.     IOperation::Arity ChoiceOp::getArity() const
  64.     {
  65.         return arTre;
  66.     }
  67.  
  68.     int SigChangeOp::operation(char op, int a, int /*b*/, int /*c*/)
  69.     {
  70.         if (op != '!')
  71.             throw std::logic_error("Operation other than SigChange (!) are not supported");
  72.         return -a;
  73.     }
  74.  
  75.     IOperation::Arity SigChangeOp::getArity() const
  76.     {
  77.         return arUno;
  78.     }
  79.  
  80.     int AndOp::operation(char op, int a, int b, int /*c*/)
  81.     {
  82.         if (op != '&')
  83.             throw std::logic_error("Operation other than And (&) are not supported");
  84.         return a & b;
  85.     }
  86.  
  87.     IOperation::Arity AndOp::getArity() const
  88.     {
  89.         return arDue;
  90.     }
  91.  
  92.     //==============================================================================
  93.     // class StackMachine
  94.     //==============================================================================
  95.  
  96.      // types
  97.     typedef std::map<char, IOperation*> SymbolToOperMap;
  98.     typedef SymbolToOperMap::const_iterator SymbolToOperMapConstIter;
  99.  
  100.     // TODO: put StackMachine methods implementation here
  101.  
  102.     /** Register an operation object for a given symbol.
  103.      *
  104.      *  If the symbol is already registered, throws an exception.
  105.      *
  106.      *  !The method implementation should be shred with students!
  107.      */
  108.     void StackMachine::registerOperation(char symb, IOperation* oper)
  109.     {
  110.         SymbolToOperMapConstIter it = _opers.find(symb);
  111.         if (it != _opers.end())
  112.             throw std::logic_error("An operation already registered.");
  113.         _opers[symb] = oper;
  114.     }
  115.  
  116.     /** For a given symb returns an operation object.
  117.      *
  118.      *  If the given symbol is not mapped to any operation, a nullptr is returned.
  119.      */
  120.     IOperation* StackMachine::getOperation(char symb) {
  121.         SymbolToOperMapConstIter it = _opers.find(symb);
  122.         if (it != _opers.end())
  123.             return it->second;
  124.         else
  125.             return nullptr;
  126.     }
  127.  
  128.     /** Calculates given expression using the shared stack and returns the value on its top.
  129.     *
  130.     *  \param clearStack determines if a stack should be clear before parsing the expression.
  131.     *  If one prefer not to clear stack before parsing, the results of previous calculations
  132.     *  can be used further.
  133.     *
  134.     *  \param expr contains a string-based expression contains interger operands and one-symbol operators
  135.     *  If an unrecognized symbol (or substring) is found, throws an exception.
  136.     *  If given expression is not valid (e.g., in the case of lack of operands or similar),
  137.     *  an exception is thrown.
  138.     */
  139.     int StackMachine::calculate(const std::string& expr, bool clearStack)
  140.     {
  141.         if (clearStack)
  142.             _s.clear();
  143.         std::string word = "";
  144.         IOperation* operation;
  145.         int a, b, c;
  146.         IOperation::Arity arity;
  147.         for (int i = 0; i < expr.length(); i++)
  148.         {
  149.             if (expr[i] != ' ')
  150.                 word += expr[i];
  151.             if ((expr[i] == ' ' || expr[i + 1] == '\0') && word.length() != 0)
  152.             {
  153.                 if (isNumb(word))
  154.                 {
  155.                     _s.push(stoi(word));
  156.                     word = "";
  157.                 }
  158.                 else if (word.length() == 1)
  159.                 {
  160.                     char symb = word[0];
  161.                     operation = getOperation(symb);
  162.                     if (operation == nullptr)
  163.                         throw std::logic_error("nullptr");
  164.                     arity = operation->getArity();
  165.                     switch (arity)
  166.                     {
  167.                     case 0:
  168.                         a = _s.pop();
  169.                         _s.push(operation->operation(symb, a));
  170.                         break;
  171.                     case 1:
  172.                         b = _s.pop();
  173.                         a = _s.pop();
  174.                         _s.push(operation->operation(symb, a, b));
  175.                         break;
  176.                     case 2:
  177.                         c = _s.pop();
  178.                         b = _s.pop();
  179.                         a = _s.pop();
  180.                         _s.push(operation->operation(symb, a, b, c));
  181.                         break;
  182.                     }
  183.                     word = "";
  184.                 }
  185.                 else if ((expr[i] == ' ' || expr[i + 1] == '\0') && word.length() == 0)
  186.                     continue;
  187.                 else
  188.                     throw std::logic_error("It is not number or operation.");
  189.             }
  190.         }
  191.         return _s.top();
  192.     }
  193. } // namespace xi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement