Advertisement
Guest User

Код менеджера

a guest
Dec 16th, 2013
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.51 KB | None | 0 0
  1. #include <string>
  2. #include <cassert>
  3. #include <memory>
  4. #include <stdexcept>
  5. #include <vector>
  6. #include <iostream>
  7. #include <cstdio>
  8.  
  9. using namespace std;
  10.  
  11. struct Token {
  12.         enum Type { value, operation, opening_bracket, closing_bracket};
  13.         Type type;
  14.         string text;
  15. };
  16.  
  17. struct Tokenizer {
  18.         //I am too lazy to write real tokenizer, it is very simple. I hope formula generator for fake tokenizer will be ok.
  19. public:
  20.         Tokenizer() { content=generate(); pos=content.begin(); } ;
  21.         const Token* peek() { return pos!=content.end() ?&*pos:0; } ;
  22.         const Token* get() { if (pos!=content.end()) { cout << pos->text << " "; } return pos!=content.end()?&*pos++:0; } ;
  23. private:
  24.     vector<Token> generate(int level=0);
  25.    
  26. private:
  27.         vector<Token>::iterator pos;
  28.         vector<Token> content;
  29. };
  30.  
  31. //To be honest using classes for expression parsing is a bit overkill, old style could save some code.
  32. class Expression;
  33. typedef struct auto_ptr<Expression> ExpressionPtr;
  34.  
  35. //Represents abstract expression
  36. class Expression {
  37. public:
  38.         Expression() {}
  39.         virtual ~Expression() {}
  40.         //actually this static parse functions should be constructor in most classes. I.e. this is violation of principle 'Resource Acquisition Is Initialization'.
  41.         //but some functions return different classes depending on context, i.e. this is some kind of 'virtual constructor' (see Operation::parse for example)
  42.         //so I made decision to make static construction function in all classes, just for uniformity
  43.         static ExpressionPtr parse(Tokenizer& tokens);
  44.         virtual float calc()=0;
  45.         virtual void debug(string prefix)=0;
  46. };
  47.  
  48.  
  49. //Represents single value: for example 3.1415
  50. class Value: public Expression {
  51. public:
  52.         Value() {}
  53.         virtual ~Value() {}
  54.         static bool isItYou(Tokenizer& tokens);
  55.         static ExpressionPtr parse(Tokenizer& tokens);
  56.         virtual float calc() { return _value; }
  57.         virtual void debug(string prefix) { cout << prefix << "Value(" <<  calc() <<"): " << _value << endl; }
  58. protected:
  59.         float _value;
  60. };
  61.  
  62. //Represents operation: + or -
  63. class Operation: public Expression {
  64. public:
  65.         Operation() {};
  66.         virtual ~Operation() {}
  67.         static ExpressionPtr parse(Tokenizer& tokens, ExpressionPtr& l);
  68.         virtual float calc();
  69.         virtual void debug(string prefix) { cout << prefix << "Operation(" <<  calc() <<"): " << _operation << endl; if ( _left.get() ) _left->debug(prefix + "\t"); if ( _right.get() ) _right->debug(prefix + "\t"); }
  70. protected:
  71.         std::auto_ptr<Expression> _left;
  72.         std::auto_ptr<Expression> _right;
  73.         string _operation;
  74. };
  75.  
  76. //Represents operation: * or /
  77. class PriorityOperation: public Operation {
  78. public:
  79.         PriorityOperation() {};
  80.         virtual ~PriorityOperation() {}
  81.         static ExpressionPtr parse(Tokenizer& tokens, ExpressionPtr& left);
  82.         //virtual float calc(); inherit it
  83.         virtual void debug(string prefix) { cout << prefix << "PriorityOperation(" <<  calc() <<"): " << _operation << endl; if ( _left.get() ) _left->debug(prefix + "\t"); if ( _right.get() ) _right->debug(prefix + "\t"); }
  84. };
  85.  
  86.  
  87. //Represents bracketed expression: (expr)
  88. class BracketExpression: public Expression {
  89. public:
  90.         static bool isItYou(Tokenizer& tokens);
  91.         static ExpressionPtr parse(Tokenizer& tokens);
  92.         virtual float calc() { return _internal->calc(); } ;
  93.         virtual void debug(string prefix) { cout << prefix << "Brackets(" <<  calc() <<"): "  << endl; _internal->debug(prefix + "\t"); }
  94. protected:
  95.         std::auto_ptr<Expression> _internal;
  96. };
  97.  
  98.  
  99. ExpressionPtr Expression::parse(Tokenizer& tokens)
  100. {
  101.     //cout << "Expression::parse" << endl;
  102.    
  103.         if (!tokens.peek()) return ExpressionPtr();
  104.  
  105.         if ( BracketExpression::isItYou(tokens) )
  106.         {
  107.                 return BracketExpression::parse(tokens);
  108.         }
  109.         else
  110.         if ( Value::isItYou(tokens) )
  111.         {        
  112.                 return Value::parse(tokens);
  113.         }
  114.         else
  115.         {
  116.                 throw logic_error("(Expression) Wtf is that: " + tokens.peek()->text );
  117.         }
  118. }
  119.  
  120. bool Value::isItYou(Tokenizer& tokens)
  121. {
  122.         const Token* t = tokens.peek();
  123.         if ( !t || t->type != Token::value ) return false;
  124.  
  125.         char* endptr;
  126.         strtod( t->text.c_str(), &endptr);
  127.         return *endptr == 0;
  128. }
  129.  
  130. ExpressionPtr Value::parse(Tokenizer& tokens)
  131. {
  132.     //cout << "Value::parse" << endl;
  133.    
  134.         std::auto_ptr<Value> foo( new Value );
  135.  
  136.         const Token* t=tokens.get();
  137.         assert( t && t->type == Token::value );
  138.  
  139.         char* endptr;
  140.         foo->_value = strtod( t->text.c_str(), &endptr);
  141.         return ExpressionPtr(foo.release()); //lack of heterosexual auto_ptr conversions is killing me
  142. }
  143.  
  144. bool BracketExpression::isItYou(Tokenizer& tokens)
  145. {
  146.         return tokens.peek() && tokens.peek()->type == Token::opening_bracket;
  147. }
  148.  
  149.  
  150. ExpressionPtr BracketExpression::parse(Tokenizer& tokens)
  151. {
  152.     //cout << "BracketExpression::parse" << endl;
  153.         const Token* t=tokens.get();
  154.         assert ( t->type == Token::opening_bracket );
  155.  
  156.         auto_ptr<BracketExpression> result ( new BracketExpression );
  157.         ExpressionPtr null;
  158.         result->_internal = Operation::parse(tokens, null);
  159.  
  160.         t = tokens.get();
  161.         if ( t ==0 || t->type != Token::closing_bracket )
  162.         {
  163.                 throw logic_error("(BracketExpression) mismatched brackets ");
  164.         }
  165.  
  166.         return ExpressionPtr(result.release());
  167. }
  168.  
  169.  
  170. ExpressionPtr Operation::parse(Tokenizer& tokens, ExpressionPtr& l)
  171. {
  172.     //cout << "Operation::parse:" << l.get() << endl;
  173.         ExpressionPtr left;
  174.  
  175.         if (l.get())
  176.         {
  177.                 left=l;
  178.                 // left is assigned for us.
  179.         }
  180.         else
  181.         {
  182.                 left=Expression::parse(tokens);
  183.         }        
  184.  
  185.         const Token *t=tokens.peek();
  186.         if (!t || t->type == Token::closing_bracket  ) return left; //just return Value, sorry no operation guys
  187.  
  188.         if (t->type == Token::operation && (t->text=="*" || t->text=="/") )
  189.         {
  190.                 ExpressionPtr result = PriorityOperation::parse(tokens, left);                
  191.                 //we got exit after priority operations will end, parse position will be on + or - or at end
  192.                 left = result;        
  193.  
  194.                 t=tokens.peek();
  195.                 if (!t || t->type == Token::closing_bracket  ) return left; //just return Value, sorry no operation guys
  196.         }
  197.  
  198.     //cout << "Operation::parse again" << endl;
  199.         if (t->type == Token::operation && (t->text=="+" || t->text=="-") )
  200.         {
  201.                 tokens.get(); //just commit previous peek
  202.  
  203.                 auto_ptr<Operation> result ( new Operation );
  204.                 result->_operation = t->text;
  205.                 result->_left=left; //smart ptr giveup ownership
  206.        
  207.         //cout << "Operation::parse before token" << endl;
  208.         ExpressionPtr foo=Expression::parse(tokens);
  209.         //cout << "Operation::parse after expression" << endl;
  210.        
  211.         const Token *t=tokens.peek();
  212.        
  213.         if (t != 0 && (t->text=="*" || t->text=="/"))
  214.         {
  215.             //cout << "Operation::parse to priority" << endl;
  216.             foo = PriorityOperation::parse(tokens,foo);
  217.         }
  218.        
  219.         result->_right=foo;
  220.        
  221.         ExpressionPtr bar(result.release());
  222.         return Operation::parse(tokens, bar);
  223.                
  224.         }
  225.         else
  226.         {
  227.                 throw logic_error("(Operation) Wtf is that: " + tokens.peek()->text);
  228.         }
  229. }
  230.  
  231. ExpressionPtr PriorityOperation::parse(Tokenizer& tokens, ExpressionPtr& left)
  232. {
  233.     //cout << "PriorityOperation::parse" << endl;
  234.    
  235.     // left is already assigned for priority operation
  236.         const Token *t=tokens.peek();
  237.         if (!t || t->type == Token::closing_bracket  ) return left; //just return Value, sorry no operation guys
  238.  
  239.         if (t->type == Token::operation && (t->text=="*" || t->text=="/") )
  240.         {
  241.                 tokens.get(); //commit previuos peek
  242.  
  243.                 auto_ptr<PriorityOperation> result ( new PriorityOperation );
  244.                 result->_operation = t->text;
  245.                 result->_left=left;
  246.                 result->_right=Expression::parse(tokens);
  247.                 ExpressionPtr rs(result.release());
  248.  
  249.                 return PriorityOperation::parse(tokens, rs);
  250.  
  251.         }
  252.         else if (t->type == Token::operation && (t->text=="+" || t->text=="-") )
  253.         {
  254.                 return left;
  255.         }
  256.         else
  257.         {
  258.                 throw logic_error("(PriorityOperation) Wtf is that: " + tokens.peek()->text );
  259.         }
  260. }
  261.  
  262.  
  263. float Operation::calc()
  264. {
  265.         if (_operation == "+")
  266.         {
  267.                 float l=_left.get()?_left->calc():0.0f;
  268.                 float r=_right.get()?_right->calc():0.0f;
  269.                 return l+r;
  270.         }
  271.         else
  272.         if (_operation == "-")
  273.         {
  274.                 float l=_left.get()?_left->calc():0.0f;
  275.                 float r=_right.get()?_right->calc():0.0f;
  276.                 return l-r;
  277.         }        
  278.         else
  279.         if (_operation == "*")
  280.         {
  281.                 float l=_left.get()?_left->calc():1.0f;
  282.                 float r=_right.get()?_right->calc():1.0f;
  283.                 return  l*r;
  284.         }        
  285.         else
  286.         if (_operation == "/")
  287.         {
  288.                 float l = _left.get()?_left->calc():1.0f;
  289.                 float r = _right.get()?_right->calc():1.0f;
  290.                 return l/r;
  291.         }
  292.         else
  293.         {
  294.                 throw logic_error("Wft: operation udefined");
  295.         }                
  296. }
  297.  
  298. //returning vector by value, will be slow( O(n*n) actually ), but it is just testing code.
  299. vector<Token> Tokenizer::generate(int level)
  300. {
  301.     //be careful with this value - formula size is approx 2^level
  302.     if (level > 6)
  303.     {
  304.         Token t;
  305.         char f[100];
  306.         snprintf(f,100,"%d",int(rand() % 100));
  307.         t.text=f;
  308.         t.type=Token::value;
  309.         return vector<Token>(&t,&t+1);
  310.     }
  311.  
  312.     if (rand() % 10 == 0)
  313.     {
  314.             vector<Token> result;
  315.             Token t1,t2;
  316.             t1.type=Token::opening_bracket;
  317.             t1.text="(";
  318.             t2.type=Token::closing_bracket;
  319.             t2.text=")";
  320.             result.push_back(t1);
  321.             vector<Token> r=generate(level+1);
  322.             result.insert(result.end(),r.begin(),r.end());
  323.             result.push_back(t2);
  324.  
  325.             return result;
  326.     }        
  327.  
  328.     char op = "+-*/"[rand()%4];
  329.     Token t;
  330.     t.type=Token::operation;
  331.     t.text=op;
  332.  
  333.     vector<Token> result=generate(level+1);
  334.     result.push_back(t);
  335.     vector<Token> r2=generate(level+1);
  336.     result.insert(result.end(),r2.begin(),r2.end());
  337.  
  338.     return result;
  339. }
  340.  
  341. int main()
  342. {        
  343.         try
  344.         {
  345.                 //create fake tokenizer
  346.                 Tokenizer tk;
  347.  
  348.                 //parse it
  349.                 ExpressionPtr null;
  350.                 ExpressionPtr foo = Operation::parse(tk,null);
  351.                 cout << endl;
  352.                 foo->debug("");
  353.                 float result = foo->calc();        
  354.                 cout << "result = " << result << endl;
  355.         }
  356.         catch(exception& e)
  357.         {
  358.                 cout << e.what() << endl;
  359.                 return 1;                  
  360.         }
  361.  
  362.         return 0;
  363. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement