Advertisement
Guest User

Backwards recursive parsing

a guest
Jan 12th, 2015
325
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.46 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <sstream>
  4. #include <vector>
  5.  
  6. //FROM MY UTILITY HEADER
  7. template <typename T>
  8. T interpret_as(std::istream& in)
  9. {
  10.     auto out = T{};
  11.     in >> out;
  12.     return out;
  13. }
  14.  
  15. template <typename T>
  16. T interpret_as(const std::string& in)
  17. {
  18.     auto stream = std::istringstream{ in };
  19.     return interpret_as<T>(stream);
  20. }
  21.  
  22. template <>
  23. std::string interpret_as<std::string>(const std::string& in)
  24. {
  25.     return in;
  26. }
  27.  
  28. template <typename T>
  29. T interpret_line_as(std::istream& in)
  30. {
  31.     auto str = string{};
  32.     getline(in, str);
  33.     return interpret_as<T>(str);
  34. }
  35.  
  36. enum BracketType
  37. {
  38.     NOT_BRACKET = 0,
  39.     OPEN_BRACKET = 1,
  40.     CLOSE_BRACKET = 2
  41. };
  42.  
  43. BracketType isbracket(char ch)
  44. {
  45.     const auto brackets = std::string{ "()[]{}" };
  46.     const auto result = brackets.find(ch);
  47.     if (result == brackets.npos)
  48.     {
  49.         return NOT_BRACKET;
  50.     }
  51.     return static_cast<BracketType>(1 + (result % 2));
  52. }
  53.  
  54. // END FUNCTIONS FROM UTILITY
  55.  
  56. using namespace std; // Toy projects only
  57.  
  58. enum class Direction : char
  59. {
  60.     left,
  61.     right
  62. };
  63.  
  64. typedef pair<char, Direction> Operator;
  65.  
  66. template <>
  67. Direction interpret_as<Direction>(const string& in)
  68. {
  69.     return (in == "left" ? Direction::left : Direction::right);
  70. }
  71.  
  72. template <>
  73. Operator interpret_as<Operator>(const string& in)
  74. {
  75.     return Operator{ in.at(0), interpret_as<Direction>(in.substr(2)) };
  76. }
  77.  
  78. int distanceToCloseBracket(const string& expression)
  79. {
  80.     for (auto it = begin(expression)+1; it != end(expression); ++it)
  81.     {
  82.         switch (isbracket(*it))
  83.         {
  84.         default:
  85.         case NOT_BRACKET:
  86.             break;
  87.         case CLOSE_BRACKET:
  88.             return distance(begin(expression),it);
  89.             break;
  90.         case OPEN_BRACKET:
  91.             it += distanceToCloseBracket(string{ it, end(expression) });
  92.             break;
  93.         }
  94.     }
  95.     return 0;
  96. }
  97.  
  98. int findCharLtoR(const string& expression, char ch)
  99. {
  100.     // Search, ignoring anywhere inside brackets.
  101.     auto openBrackets = 0;
  102.     for (auto it = begin(expression); it != end(expression); ++it)
  103.     {
  104.         if (isbracket(*it))
  105.         {
  106.             // Skip to the end of the brackets.
  107.             it += distanceToCloseBracket(string{ it, end(expression) });
  108.         }
  109.         if (*it == ch)
  110.         {
  111.             return distance(begin(expression),it);
  112.         }
  113.     }
  114.     return -1;
  115. }
  116.  
  117. int findCharRtoL(const string& expression, char ch)
  118. {
  119.     auto reversedExpression = string{rbegin(expression), rend(expression)};
  120.  
  121.     // Reverse the brackets.
  122.     for (auto& ch : reversedExpression)
  123.     {
  124.         if (isbracket(ch) == OPEN_BRACKET)
  125.         {
  126.             ch = ')';
  127.         }
  128.         if (isbracket(ch) == CLOSE_BRACKET)
  129.         {
  130.             ch = '(';
  131.         }
  132.     }
  133.  
  134.     // Hook into the LtoR finder.
  135.     const auto result = findCharLtoR(reversedExpression, ch);
  136.  
  137.     // Convert the result.
  138.     if (result == -1)
  139.     {
  140.         return result;
  141.     }
  142.     else
  143.     {
  144.         return static_cast<int>(expression.size()) - 1 - result;
  145.     }
  146. }
  147.  
  148. int findOperator(const string& expression, const Operator& op)
  149. {
  150.     return (op.second == Direction::right ? findCharLtoR(expression, op.first) : findCharRtoL(expression, op.first));
  151. }
  152.  
  153. string parseExpression(const string& expression, const vector<Operator>& operators)
  154. {
  155.    
  156.     // Search the operators backwards, so we start from the lowest precedence.
  157.     for (auto it = rbegin(operators); it != rend(operators); ++it)
  158.     {
  159.         // If an operator is found, split around that operator, and parse the two sides separately.
  160.         const auto pos = findOperator(expression, *it);
  161.         if (pos != -1)
  162.         {
  163.             const auto leftSide = expression.substr(0, pos);
  164.             const auto rightSide = expression.substr(pos + 1);
  165.             auto output = ostringstream{};
  166.             output << '(' << parseExpression(leftSide, operators)
  167.                 << it->first
  168.                 << parseExpression(rightSide, operators) << ')';
  169.             return output.str();
  170.         }
  171.     }
  172.  
  173.     // If no operator, seek out brackets and parse into the brackets.
  174.     auto output = ostringstream{};
  175.     for (auto it = begin(expression); it != end(expression); ++it)
  176.     {
  177.         output << *it;
  178.         if (isbracket(*it) == OPEN_BRACKET)
  179.         {
  180.             auto startPoint = it + 1;
  181.             it += distanceToCloseBracket(string{ it, end(expression) });
  182.             auto endPoint = it;
  183.             output << parseExpression(string{ startPoint, endPoint }, operators);
  184.         }
  185.     }
  186.     return output.str();
  187. }
  188.  
  189. int main()
  190. {
  191.     const auto n_operators = interpret_line_as<int>(cin);
  192.  
  193.     auto operators = vector<Operator>{};
  194.     operators.reserve(n_operators);
  195.  
  196.     for (auto i = 0; i < n_operators; ++i)
  197.     {
  198.         operators.push_back(interpret_line_as<Operator>(cin));
  199.     }
  200.  
  201.     const auto expression = interpret_line_as<string>(cin);
  202.  
  203.     cout << parseExpression(expression, operators) << '\n';
  204.     cin.get();
  205.     return 0;
  206. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement