POJ-2314(简单C语言虚拟机)

来源:互联网 发布:cacti 监控linux流量 编辑:程序博客网 时间:2024/05/16 02:10

题目:http://poj.org/problem?id=2314

是道很好的题目,牵扯到设计模式、状态机、名称空间、函数重载等,debug时还可以用到拦截器的思想,用心做的话可以学习或练习到很多东西:

(1)命令模式:设计一个公共基类Expression作为接口,则几种Expression便对应了各个实体command,分别实现自己的语法和语义,用户类Program则只需要包含基类Expression的句柄(指针),即可run

(2)状态机:载入程序时,边载入边进行语义分析,递归(DFS)调用载入程序

(3)拦截器:由于所有变量都是global的,可以利用STL map类似数组的用法结合C++操作符重载的特性,在变量access时,可以打印access前(后)global scope的状态


#include <cstdio>#include <cctype>#include <string>#include <map>#include <vector>#include <functional>#include <algorithm>using namespace std;bool isNumber(const string& s){//if s is an integer    if(s.empty()) return false;    for(int i = 0; i < s.size(); ++i){        if(!isdigit(s[i])) return false;    }    return true;}int toNumber(const string& s){//parse s as an integer    int n;    sscanf(s.c_str(), "%d", &n);    return n;}struct Expression{    virtual ~Expression(){}    virtual void execute(){};};class Scope{private:    map<string,int> nameValueMap;    map<string,int>::const_iterator iter;    void intercept(const string& name){        printf("before access \"%s\"\n", name.c_str());        for(iter = nameValueMap.begin(); iter != nameValueMap.end(); ++iter){            printf("%s = %d\n", iter->first.c_str(), iter->second);        }    }public:    int& operator [] (const string& name){//        intercept(name);        return nameValueMap[name];    }} global;bool Terminate = false;struct Special : public Expression{    string variable;    Special(const string& s) : variable(s){}    virtual void execute(){        ::Terminate = true;        printf("%d\n", global[variable]);    }};struct Assignment : public Expression{    string A, B, OP, C; //A = B or A = B OP C    Assignment(const string& s){//        printf("new Assignment: %s\n", s.c_str());        string::size_type equalSign = s.find('=');        A = s.substr(0, equalSign);        string::size_type op = s.find_first_of("+-*", equalSign+1);        if(op == string::npos) B = s.substr(equalSign+1);        else{            B = s.substr(equalSign+1, op-equalSign-1);            OP.push_back(s[op]);            C = s.substr(op+1);        }        if(isNumber(B)) global[B] = toNumber(B);        if(isNumber(C)) global[C] = toNumber(C);    }    virtual void execute(){//        printf("execute %s=%s%s%s\n", A.c_str(), B.c_str(), OP.c_str(), C.c_str());        if(OP.empty()) global[A] = global[B];        else if(OP == "+") global[A] = global[B] + global[C];        else if(OP == "-") global[A] = global[B] - global[C];        else global[A] = global[B] * global[C];    }};struct Judgement : public Expression{    string A, OP, B;    bool result;    Judgement(const string& s){//        printf("new Judgement: %s\n", s.c_str());        string::size_type pos = s.find_first_of("<=");        if(s[pos+1] == '='){//<= or ==            A = s.substr(0, pos);            OP = s.substr(pos, 2);            B = s.substr(pos+2);        }        else{//<            A = s.substr(0, pos);            OP.push_back(s[pos]);            B = s.substr(pos+1);        }        if(isNumber(A)) global[A] = toNumber(A);        if(isNumber(B)) global[B] = toNumber(B);    }    virtual void execute(){//        printf("execute %s%s%s\n", A.c_str(), OP.c_str(), B.c_str());        if(OP == "<") result = global[A] < global[B];        else if(OP == "==") result = global[A] == global[B];        else result = global[A] <= global[B];    }    bool judge(){        execute();        return result;    }};struct IfSuite : public Expression{    Judgement condition;    vector<Expression*> clause;    IfSuite(const string& s) : condition(s){}    ~IfSuite(){        for(int i = 0; i < clause.size(); ++i) delete clause[i];    }    void addClause(Expression* exp){        clause.push_back(exp);    }    virtual void execute(){        if(!::Terminate && condition.judge()){//            for(int i = 0; i < clause.size(); ++i) clause[i]->execute();            for_each(clause.begin(), clause.end(), mem_fun(&Expression::execute));        }    }};struct WhileSuite : public Expression{    Judgement condition;    vector<Expression*> clause;    WhileSuite(const string& s) : condition(s){}    ~WhileSuite(){        for(int i = 0; i < clause.size(); ++i) delete clause[i];    }    void addClause(Expression* exp){        clause.push_back(exp);    }    virtual void execute(){        while(!::Terminate && condition.judge()){//            for(int i = 0; i < clause.size(); ++i) clause[i]->execute();            for_each(clause.begin(), clause.end(), mem_fun(&Expression::execute));        }    }};class Program{private:    vector<Expression*> clause;private:    Expression* loadSpecial(){        char c;        string name;        while((c = getchar()) != ';'){            if(!isspace(c)) name.push_back(c);        }        return new Special(name);    }    Expression* loadIf(){        char c;        string condition;        while((c = getchar()) != ')'){            if(!isspace(c)) condition.push_back(c);        }        IfSuite* suite = new IfSuite(condition);        while(getchar() != '{') ;        load(suite->clause, '}');        return suite;    }    Expression* loadWhile(){        char c;        string condition;        while((c = getchar()) != ')'){            if(!isspace(c)) condition.push_back(c);        }        WhileSuite* suite = new WhileSuite(condition);        while(getchar() != '{') ;        load(suite->clause, '}');        return suite;    }    void load(vector<Expression*>& v, int endTag = -1){        int c;        string s;        while((c = getchar()) != endTag){//read till end            if(isspace(c)) continue;            if(c == '('){//suite begins                if(s == "if") v.push_back(loadIf());                else v.push_back(loadWhile());                s.clear();            }            else if(c == '#'){//special begins                v.push_back(loadSpecial());                s.clear();            }            else if(c == ';'){//assignment ends                if(!s.empty()){                    v.push_back(new Assignment(s));                    s.clear();                }            }            else s.push_back(c);//part of expression        }    }public:    ~Program(){        for(int i = 0; i < clause.size(); ++i) delete clause[i];    }    void load(){        load(clause);    }    void run(){//        printf("\nabout to execute %u clause:\n\n", clause.size());        for_each(clause.begin(), clause.end(), mem_fun(&Expression::execute));    }};int main(){    Program tiny;    tiny.load();    tiny.run();    return 0;}

0 0
原创粉丝点击