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

题目: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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值