Advertisement
onilink_

Prefix expression parser and evaluator

Nov 21st, 2014
315
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.82 KB | None | 0 0
  1. #include <iostream>
  2. #include <cstdio>
  3.  
  4. struct Token
  5. {
  6.     enum Kind { Value, Plus, Minus, Mult, Div, Eof };
  7.     int value;
  8.     Kind kind;
  9.    
  10.     Token():kind(Eof){}
  11.     Token(Kind kind):kind(kind){}
  12.     Token(int value):value(value), kind(Value){}
  13.    
  14.     bool isOperator() const { return kind != Value; }
  15.    
  16.     bool operator==(Kind kind) const { return this->kind == kind; }
  17.     bool operator!=(Kind kind) const { return this->kind != kind; }
  18.    
  19.     std::string toString() {
  20.         switch(kind) {
  21.             case Plus: return "+";
  22.             case Minus: return "-";
  23.             case Mult: return "*";
  24.             case Div: return "/";
  25.             case Eof: return "\0";
  26.             default: break;
  27.         }
  28.         char buff[30];
  29.         sprintf(buff, "%d", value);
  30.         return buff;
  31.     }
  32. };
  33.  
  34. class Lexer
  35. {
  36.     std::string str;
  37.     size_t cursor;
  38.     char last_char;
  39.     Token last_token;
  40.    
  41.     char getchar() {
  42.         if(cursor >= str.length())
  43.             return '\0';
  44.         return str[cursor++];
  45.     }
  46.    
  47.     Token getToken()
  48.     {
  49.         while(last_char == ' ')
  50.             last_char = getchar();
  51.        
  52.         if(std::isdigit(last_char))
  53.         {
  54.             int val = last_char - '0';
  55.             while(std::isdigit(last_char = getchar()))
  56.             {
  57.                 val = val * 10 + last_char - '0';
  58.             }
  59.             return Token(val);
  60.         }
  61.        
  62.         Token ret;
  63.         if(last_char == '+')
  64.             ret = Token(Token::Plus);
  65.         else if(last_char == '-')
  66.             ret = Token(Token::Minus);
  67.         else if(last_char == '*')
  68.             ret = Token(Token::Mult);
  69.         else if(last_char == '/')
  70.             ret = Token(Token::Div);
  71.        
  72.         last_char = getchar();
  73.        
  74.         return ret;
  75.     }
  76.    
  77. public:
  78.     Lexer(const std::string & str):str(str),cursor(0),last_char(' '){}
  79.    
  80.     Token get() { return last_token = getToken(); }
  81.     Token last() const { return last_token; }
  82. };
  83.  
  84.  
  85. struct Ast
  86. {
  87.     virtual float eval() const = 0;
  88.     virtual std::string infix() const = 0;
  89. };
  90.  
  91. struct BinaryOpAst : public Ast
  92. {
  93.     Ast * left;
  94.     Ast * right;
  95.    
  96.     BinaryOpAst(Ast * left, Ast * right):left(left),right(right){}
  97. };
  98.  
  99. struct OpAddAst : public BinaryOpAst
  100. {
  101.     OpAddAst(Ast * left, Ast * right):BinaryOpAst(left, right) {}
  102.     float eval() const { return left->eval() + right->eval(); }
  103.     std::string infix() const { return "(" + left->infix() + " + " + right->infix() + ")"; }
  104. };
  105.  
  106. struct OpSubAst : public BinaryOpAst
  107. {
  108.     OpSubAst(Ast * left, Ast * right):BinaryOpAst(left, right) {}
  109.     float eval() const { return left->eval() - right->eval(); }
  110.     std::string infix() const { return "(" + left->infix() + " - " + right->infix() + ")"; }
  111. };
  112.  
  113. struct OpMultAst : public BinaryOpAst
  114. {
  115.     OpMultAst(Ast * left, Ast * right):BinaryOpAst(left, right) {}
  116.     float eval() const { return left->eval() * right->eval(); }
  117.     std::string infix() const { return "(" + left->infix() + " * " + right->infix() + ")"; }
  118. };
  119.  
  120. struct OpDivAst : public BinaryOpAst
  121. {
  122.     OpDivAst(Ast * left, Ast * right):BinaryOpAst(left, right) {}
  123.     float eval() const { return left->eval() / right->eval(); }
  124.     std::string infix() const { return "(" + left->infix() + " / " + right->infix() + ")"; }
  125. };
  126.  
  127.  
  128. struct ValueAst : public Ast
  129. {
  130.     float value;
  131.    
  132.     ValueAst(float value):value(value){}
  133.    
  134.     float eval() const { return value; }
  135.    
  136.     std::string infix() const {
  137.         char buff[30];
  138.         sprintf(buff, "%d", (int)value);
  139.         return buff;
  140.     }
  141. };
  142.  
  143. class Parser
  144. {
  145.     Ast * parseBinaryOperation(Lexer & lex);
  146.     Ast * parseValue(Lexer & lex);
  147.     Ast * parse(Lexer & lex);
  148.    
  149. public:
  150.     static Ast * parseString(const std::string & str);
  151. };
  152.  
  153. Ast * Parser::parseString(const std::string & str)
  154. {
  155.     Lexer lex(str);
  156.     Parser parser;
  157.     return parser.parse(lex);
  158. }
  159.  
  160. Ast * Parser::parseBinaryOperation(Lexer & lex)
  161. {
  162.     switch(lex.last().kind)
  163.     {
  164.         case Token::Plus: return new OpAddAst(parse(lex), parse(lex));
  165.         case Token::Minus: return new OpSubAst(parse(lex), parse(lex));
  166.         case Token::Mult: return new OpMultAst(parse(lex), parse(lex));
  167.         case Token::Div: return new OpDivAst(parse(lex), parse(lex));
  168.         default: return 0; // nullptr
  169.     }
  170. }
  171.  
  172. Ast * Parser::parseValue(Lexer & lex)
  173. {
  174.     return new ValueAst(lex.last().value);
  175. }
  176.  
  177. Ast * Parser::parse(Lexer & lex)
  178. {
  179.     if(lex.get().isOperator())
  180.         return parseBinaryOperation(lex);
  181.     else
  182.         return parseValue(lex);
  183. }
  184.  
  185. int main()
  186. {
  187.     std::string str = "+ 5 - - 4 2 + 3 1";
  188.    
  189.     Ast * ast = Parser::parseString(str);
  190.    
  191.     std::cout << ast->infix() << std::endl
  192.         << "= " << ast->eval() << std::endl;
  193.    
  194.     return 0;
  195. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement