Advertisement
Guest User

Parser +-*/()

a guest
Feb 15th, 2014
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.31 KB | None | 0 0
  1. #include <vector>
  2. #include <iostream>
  3. #include <stdexcept>
  4. #include <cassert>
  5.  
  6. enum class Key{
  7.     Number,
  8.    
  9.     OpAdd,
  10.     OpSub,
  11.     OpMul,
  12.     OpDiv,
  13.     OpBracketL,
  14.     OpBracketR,
  15.        
  16.     Eof
  17. };
  18.  
  19. struct Token{
  20.     Key key;
  21.     std::string val;
  22.    
  23.     Token(Key key):key(key){}
  24.     Token(Key key, const std::string& val):key(key), val(val){}
  25.     Token(Key key, std::string&& val):key(key), val(std::move(val)){}
  26. };
  27.  
  28. std::vector<Token> scan(std::istream& in){
  29.     std::vector<Token> tokens;
  30.    
  31.     while(1){
  32.         int i = in.get();
  33.         DENGO:
  34.         switch(i){
  35.             case ' ':
  36.             case '\t':
  37.                 continue;
  38.             case '\n':
  39.                 tokens.emplace_back(Key::Eof);
  40.                 return tokens; 
  41.             case '+':
  42.                 tokens.emplace_back(Key::OpAdd);
  43.                 continue;
  44.             case '-':
  45.                 tokens.emplace_back(Key::OpSub);
  46.                 continue;
  47.             case '*':
  48.                 tokens.emplace_back(Key::OpMul);
  49.                 continue;
  50.             case '/':
  51.                 tokens.emplace_back(Key::OpDiv);
  52.                 continue;
  53.             case '(':
  54.                 tokens.emplace_back(Key::OpBracketL);
  55.                 continue;
  56.             case ')':
  57.                 tokens.emplace_back(Key::OpBracketR);
  58.                 continue;  
  59.                
  60.             case '0':case '1':case '2':case '3':case '4':
  61.             case '5':case '6':case '7':case '8':case '9':   {
  62.                 std::string str;
  63.                 str += (char)i;
  64.                
  65.                 while(1) switch((i = in.get())){
  66.                     case '0':case '1':case '2':case '3':case '4':
  67.                     case '5':case '6':case '7':case '8':case '9':
  68.                         str += (char)i;
  69.                         continue;
  70.                        
  71.                     case '\n':
  72.                         tokens.emplace_back(Key::Number, str);
  73.                         tokens.emplace_back(Key::Eof);
  74.                         return tokens;
  75.                        
  76.                     default:
  77.                         tokens.emplace_back(Key::Number, str);
  78.                         goto DENGO;
  79.                 };
  80.                
  81.                 continue;  
  82.             }      
  83.         }
  84.        
  85.         throw std::logic_error("Neznamy symbol");
  86.     }
  87.     assert(0);
  88. }
  89.  
  90. double parseValue(std::vector<Token>::const_iterator& tok);
  91. double parseAdd(std::vector<Token>::const_iterator& tok);
  92. double parseMul(std::vector<Token>::const_iterator& tok);
  93.  
  94. double parseValue(std::vector<Token>::const_iterator& tok){
  95.     switch(tok->key){
  96.         case Key::Number:{
  97.             double d = std::stod(tok->val);
  98.             ++tok;
  99.             return d;
  100.         }
  101.         case Key::OpBracketL:{
  102.             double d = parseAdd(++tok);
  103.             if(tok->key != Key::OpBracketR)throw std::logic_error("chyba znak ')'");
  104.             ++tok;
  105.             return d;
  106.         }
  107.        
  108.         default:
  109.             throw std::logic_error("Neznama hodnota");
  110.     }
  111.     assert(0);
  112. }
  113.  
  114. double parseMul(std::vector<Token>::const_iterator& tok){
  115.     double left = parseValue(tok);
  116.    
  117.     while(1) switch(tok->key){
  118.         case Key::OpMul:
  119.             left *= parseValue(++tok);
  120.             break;
  121.            
  122.         case Key::OpDiv:
  123.             left /= parseValue(++tok);
  124.             break;
  125.            
  126.         default:
  127.             return left;
  128.     }
  129.     assert(0);
  130. }
  131.  
  132. double parseAdd(std::vector<Token>::const_iterator& tok){
  133.     double left = parseMul(tok);
  134.    
  135.     while(1) switch(tok->key){
  136.         case Key::OpAdd:
  137.             left += parseMul(++tok);
  138.             break;
  139.            
  140.         case Key::OpSub:
  141.             left -= parseMul(++tok);
  142.             break;
  143.            
  144.         default:
  145.             return left;
  146.     }
  147.     assert(0);
  148. }
  149.  
  150. double parse(const std::vector<Token>& tokens){
  151.     //for(auto& tok : tokens)std::cout << "(" << (int)tok.key << "\t:\t" << tok.val << ")\n";
  152.     auto tok = tokens.begin();
  153.     double d = parseAdd(tok);
  154.     if(tok->key == Key::Eof)return d;
  155.     std::cout << (int)tok->key;
  156.     throw std::logic_error("PARSE ERROR");
  157. }
  158.  
  159. int main(){
  160.     using namespace std;
  161.     while(1){
  162.         std::cout << "= " << parse(scan(std::cin)) << ";\n\n";
  163.     }
  164.     return 0;
  165. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement