Guest User

Turing-complete RPN

a guest
Dec 4th, 2012
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.65 KB | None | 0 0
  1. #include <iostream>
  2. #include <sstream>
  3. #include <string>
  4. #include <vector>
  5. #include <cmath>
  6.  
  7. struct command{
  8.     bool is_push;
  9.     double x;
  10.     std::string name;
  11.     command(double x):is_push(1),x(x){}
  12.     command(const std::string &s):is_push(0),name(s){}
  13. };
  14.  
  15. class RPN{
  16.     std::vector<double> stack;
  17.     std::vector<command> code;
  18.     std::vector<size_t> code_stack;
  19.     int skip,
  20.         simulation;
  21.     size_t ip;
  22. public:
  23.     RPN():skip(0),ip(0),simulation(0){}
  24.     void push_back(double x){
  25.         if (this->skip){
  26.             this->skip--;
  27.             return;
  28.         }
  29.         if (this->code_stack.size() && this->simulation<=0)
  30.             this->code.push_back(x);
  31.         this->stack.push_back(x);
  32.         this->print_stack();
  33.     }
  34.     void eval(const std::string &s){
  35.         if (this->code_stack.size() && this->simulation<=0)
  36.             this->code.push_back(s);
  37.         if (this->skip){
  38.             this->skip--;
  39.             return;
  40.         }
  41.         if (s=="+"){
  42.             if (this->stack.size()<2)
  43.                 return;
  44.             double b=this->stack.back();
  45.             this->stack.pop_back();
  46.             double a=this->stack.back();
  47.             this->stack.pop_back();
  48.             this->stack.push_back(a+b);
  49.         }else if (s=="-"){
  50.             if (this->stack.size()<2)
  51.                 return;
  52.             double b=this->stack.back();
  53.             this->stack.pop_back();
  54.             double a=this->stack.back();
  55.             this->stack.pop_back();
  56.             this->stack.push_back(a-b);
  57.         }else if (s=="neg"){
  58.             if (this->stack.size()<1)
  59.                 return;
  60.             double a=this->stack.back();
  61.             this->stack.pop_back();
  62.             this->stack.push_back(-a);
  63.         }else if (s=="bneg"){
  64.             if (this->stack.size()<1)
  65.                 return;
  66.             double a=this->stack.back();
  67.             this->stack.pop_back();
  68.             this->stack.push_back(a>=0?-1:1);
  69.         }else if (s=="*"){
  70.             if (this->stack.size()<2)
  71.                 return;
  72.             double b=this->stack.back();
  73.             this->stack.pop_back();
  74.             double a=this->stack.back();
  75.             this->stack.pop_back();
  76.             this->stack.push_back(a*b);
  77.         }else if (s=="/"){
  78.             if (this->stack.size()<2)
  79.                 return;
  80.             double b=this->stack.back();
  81.             this->stack.pop_back();
  82.             double a=this->stack.back();
  83.             this->stack.pop_back();
  84.             this->stack.push_back(a/b);
  85.         }else if (s=="^"){
  86.             if (this->stack.size()<2)
  87.                 return;
  88.             double b=this->stack.back();
  89.             this->stack.pop_back();
  90.             double a=this->stack.back();
  91.             this->stack.pop_back();
  92.             this->stack.push_back(pow(a,b));
  93.         }else if (s=="sqrt"){
  94.             if (this->stack.size()<1)
  95.                 return;
  96.             double a=this->stack.back();
  97.             this->stack.pop_back();
  98.             this->stack.push_back(sqrt(a));
  99.         }else if (s=="e"){
  100.             this->stack.push_back(2.7182818284590452353602874713527);
  101.         }else if (s=="pi"){
  102.             this->stack.push_back(3.1415926535897932384626433832795);
  103.         }else if (s=="exp"){
  104.             if (this->stack.size()<1)
  105.                 return;
  106.             double a=this->stack.back();
  107.             this->stack.pop_back();
  108.             this->stack.push_back(exp(a));
  109.         }else if (s=="log"){
  110.             if (this->stack.size()<1)
  111.                 return;
  112.             double a=this->stack.back();
  113.             this->stack.pop_back();
  114.             this->stack.push_back(log(a));
  115.         }else if (s=="sin"){
  116.             if (this->stack.size()<2)
  117.                 return;
  118.             double b=this->stack.back();
  119.             this->stack.pop_back();
  120.             double a=this->stack.back();
  121.             this->stack.pop_back();
  122.             this->stack.push_back(sin(a));
  123.         }else if (s=="cos"){
  124.             if (this->stack.size()<1)
  125.                 return;
  126.             double a=this->stack.back();
  127.             this->stack.pop_back();
  128.             this->stack.push_back(cos(a));
  129.         }else if (s=="tan"){
  130.             if (this->stack.size()<1)
  131.                 return;
  132.             double a=this->stack.back();
  133.             this->stack.pop_back();
  134.             this->stack.push_back(tan(a));
  135.         }else if (s=="asin"){
  136.             if (this->stack.size()<1)
  137.                 return;
  138.             double a=this->stack.back();
  139.             this->stack.pop_back();
  140.             this->stack.push_back(asin(a));
  141.         }else if (s=="acos"){
  142.             if (this->stack.size()<1)
  143.                 return;
  144.             double a=this->stack.back();
  145.             this->stack.pop_back();
  146.             this->stack.push_back(acos(a));
  147.         }else if (s=="atan"){
  148.             if (this->stack.size()<1)
  149.                 return;
  150.             double a=this->stack.back();
  151.             this->stack.pop_back();
  152.             this->stack.push_back(atan(a));
  153.         }else if (s=="atan2"){
  154.             if (this->stack.size()<2)
  155.                 return;
  156.             double b=this->stack.back();
  157.             this->stack.pop_back();
  158.             double a=this->stack.back();
  159.             this->stack.pop_back();
  160.             this->stack.push_back(atan2(a,b));
  161.         }else if (s=="pop"){
  162.             if (this->stack.size()<1)
  163.                 return;
  164.             this->stack.pop_back();
  165.         }else if (s=="dup"){
  166.             if (this->stack.size()<1)
  167.                 return;
  168.             this->stack.push_back(this->stack.back());
  169.         }else if (s=="swap"){
  170.             if (this->stack.size()<2)
  171.                 return;
  172.             double b=this->stack.back();
  173.             this->stack.pop_back();
  174.             double a=this->stack.back();
  175.             this->stack.pop_back();
  176.             this->stack.push_back(b);
  177.             this->stack.push_back(a);
  178.         }else if (s=="rot"){
  179.             if (this->stack.size()<1)
  180.                 return;
  181.             int n=(int)this->stack.back();
  182.             this->stack.pop_back();
  183.             if (this->stack.size()<n || n<2)
  184.                 return;
  185.             double *temp=new double[n];
  186.             for (int a=0;a<n;a++){
  187.                 temp[n-a-1]=this->stack.back();
  188.                 this->stack.pop_back();
  189.             }
  190.             for (int a=1;a<n;a++)
  191.                 this->stack.push_back(temp[a]);
  192.             this->stack.push_back(temp[0]);
  193.             delete[] temp;
  194.         }else if (s=="if"){
  195.             if (this->stack.size()<1)
  196.                 return;
  197.             int times=(int)this->stack.back();
  198.             this->stack.pop_back();
  199.             double condition=this->stack.back();
  200.             this->stack.pop_back();
  201.             if (condition<0)
  202.                 this->skip=times;
  203.         }else if (s=="begin"){
  204.             if (this->simulation<=0){
  205.                 this->code_stack.push_back(this->code.size());
  206.                 this->simulation--;
  207.             }else
  208.                 this->simulation++;
  209.         }else if (s=="leave"){
  210.             if (this->simulation<=0){
  211.                 this->simulation++;
  212.                 if (!this->simulation)
  213.                     this->exec();
  214.             }else
  215.                 this->simulation--;
  216.         }else if (s=="end"){
  217.             if (this->simulation>0){
  218.                 if (!this->code_stack.size())
  219.                     return;
  220.                 this->ip=this->code_stack[this->simulation-1];
  221.             }
  222.         }else if (s=="$"){
  223.             if (this->stack.size()<1)
  224.                 return;
  225.             std::cout <<this->stack.back()<<std::endl;
  226.         }
  227.         this->print_stack();
  228.     }
  229.     void exec(){
  230.         this->simulation=1;
  231.         this->ip=0;
  232.         while (this->simulation){
  233.             command &c=this->code[this->ip];
  234.             int ip=this->ip;
  235.             if (c.is_push)
  236.                 this->push_back(c.x);
  237.             else
  238.                 this->eval(c.name);
  239.             if (this->ip==ip)
  240.                 this->ip++;
  241.         }
  242.         this->code.clear();
  243.         this->code_stack.clear();
  244.     }
  245.     void print_stack(){
  246.         std::cout <<'[';
  247.         if (this->stack.size()){
  248.             for (int a=0;;){
  249.                 std::cout <<this->stack[a];
  250.                 a++;
  251.                 if (a==this->stack.size())
  252.                     break;
  253.                 std::cout <<',';
  254.             }
  255.         }
  256.         std::cout <<"]\n";
  257.     }
  258. };
  259.  
  260. int main(){
  261.     RPN rpn;
  262.     while (std::cin.good()){
  263.         std::string s;
  264.         double x;
  265.         std::cin >>s;
  266.         std::stringstream stream;
  267.         stream <<s;
  268.         if (stream >>x)
  269.             rpn.push_back(x);
  270.         else{
  271.             if (s=="exit")
  272.                 break;
  273.             rpn.eval(s);
  274.         }
  275.     }
  276.     return 0;
  277. }
Advertisement
Add Comment
Please, Sign In to add comment