zoukankan      html  css  js  c++  java
  • bzoj4020: 未来程序·改

    只需写一个解释器

    第一次预处理将输入进行分词,分割出 关键字,运算符,变量/函数名,整数常量,并对变量/函数名离散化以便处理

    第二次预处理建语法树,每个节点存节点类型,变量定义表等信息

    运行时在语法树上递归处理,维护一个栈存运行中用到的变量

    #include<cstdio>
    #include<map>
    #include<string>
    #include<vector>
    #include<cstring>
    using namespace std;
    int mem[10000007],*mp=mem;
    char buf[10007],*ptr=buf;
    char stk[10007];
    int stp=0;
    map<string,int>ops,kws,vars;
    int vid=0;
    int rk[28]={100,100,101,101,2,2,3,3,3,4,4,4,5,5,6,6,6,6,7,7,8,9,10,11,12,12,13,14};
    int rka[28];
    struct token{
        int tp;//operator:0 integer:1 var_name:2 keyword:3
        int v;
        void init2(){
            tp=2;
            string a(stk);
            if(kws.find(a)!=kws.end()){
                tp=3;
                v=kws[a];
            }else if(vars.find(a)!=vars.end()){
                v=vars[a];
            }else{
                v=vars[a]=++vid;
            }
        }
        void init1(int x){
            tp=1;
            v=x;
        }
        void init0(){
            tp=0;
            v=ops[string(stk)];
            if((v==7||v==8)&&(this[-1].tp==1||this[-1].tp==2||this[-1].eq(0,1)||this[-1].eq(0,3)))v+=5;
        }
        bool eq(int a,int b){
            return tp==a&&v==b;
        }
    }ts[7007];
    int tp=0,tptr=0;
    bool isname(char x){
        return isalpha(x)||isdigit(x)||x=='_'||x=='$';
    }
    int _n,__in[10007],_inp=0;
    int _ri(){
        int x=0,f=1;
        while(!isdigit(*ptr))*ptr++=='-'?f=-1:0;
        while(isdigit(*ptr))x=x*10+*ptr++-48;
        return x*f;
    }
    void pre(){
        _n=_ri();
        for(int i=0;i<_n;++i)__in[i]=_ri();
        for(;*ptr!=';';++ptr);++ptr;
        while(1){
            for(;*ptr!=-1&&*ptr<33;++ptr);
            if(*ptr==-1)break;
            stp=0;
            if(isalpha(*ptr)){
                for(;isname(*ptr);stk[stp++]=*ptr++);stk[stp]=0;
                ts[tp++].init2();
            }else if(isdigit(*ptr)){
                ts[tp++].init1(_ri());
            }else{
                stk[stp++]=*ptr++;
                stk[1]=*ptr;
                stk[2]=0;
                if(ops.find(string(stk))!=ops.end())++ptr;
                else stk[1]=0;
                ts[tp].init0();++tp;
            }
        }
    }
    #define ptr __
    struct var{
        int id,*dat,sz;
        vector<int>dsz;
        var(){sz=1,id=0;}
        void newdim(int x){
            dsz.push_back(x);
            sz*=x;
        }
    };
    vector<var>var_now[7007];
    struct varlist{
        std::vector<var>vs;
        void def(bool init=1){
            for(int i=0;i<vs.size();++i){
                var&w=vs[i];
                if(init)memset(mp,0,sizeof(int)*w.sz);
                w.dat=mp,mp+=w.sz;
                var_now[w.id].push_back(w);
            }
        }
        void defs(){
            int mx=*--mp;
            for(int i=0;i<vs.size();++i){
                var&w=vs[i];
                memset(mp,0,sizeof(int)*w.sz);
                w.dat=mp,mp+=w.sz;
                var_now[w.id].push_back(w);
            }
            *mp++=mx+vs.size();
        }
        void undef(){
            for(int i=0;i<vs.size();++i){
                var_now[vs[i].id].pop_back();
                mp-=vs[i].sz;
            }
        }
        void undefs(){
            int mx=*--mp;
            for(int i=0;i<mx;++i){
                var_now[vs[i].id].pop_back();
                mp-=vs[i].sz;
            }
        }
        void ins(int id){
            var w;
            w.id=id;
            vs.push_back(w);
        }
        void R(){
            var w;
            w.id=ts[tptr++].v;
            for(;ts[tptr].eq(0,2);tptr+=3)w.newdim(ts[tptr+1].v);
            vs.push_back(w);
        }
        void Rs(){
            for(++tptr;;){
                R();
                if(ts[tptr++].v==27)break;
            }
        }
    }glob_var;
    struct node{
        int tp,v;
        varlist vs;
        vector<node>rs;
        node&rspb(){
            rs.push_back(node());
            return rs.back();
        }
        void Rvar(){tp=7,v=ts[tptr++].v;}
        void Rint(){tp=8,v=ts[tptr++].v;}
        void setop(int w){tp=10,v=w;}
        void Rcall(){
            tp=9;
            v=ts[tptr].v;
            tptr+=2;
            while(!ts[tptr-1].eq(0,1))rspb().Rexpr();
        }
        void setvdim(int L,int R,varlist&w){
            tp=13;
            for(int i=L;i<R;++i)vs.vs.push_back(w.vs[i]);
        }
        void Rexpr(){
            tp=2;
            vector<int>ops;
            ops.push_back(0);
            while(1){
                if(ts[tptr].tp==0){//oper
                    if(ts[tptr].v>=26){
                        while(ops.back()){
                            rspb().setop(ops.back());
                            ops.pop_back();
                        }
                        break;
                    }
                    int v=ts[tptr].v;
                    if(v==0||v==2)ops.push_back(v);
                    else if(v==1){
                        while(ops.back()){
                            rspb().setop(ops.back());
                            ops.pop_back();
                        }
                        ops.pop_back();
                        if(ops.empty())break;
                    }else if(v==3){
                        int c;
                        do{
                            c=ops.back();
                            rspb().setop(c);
                            ops.pop_back();
                        }while(c!=2);
                    }else{
                        while(ops.back()[rk]+v[rka]<=v[rk]){
                            rspb().setop(ops.back());
                            ops.pop_back();
                        }
                        ops.push_back(v);
                    }
                    ++tptr;
                }else if(ts[tptr].tp==1)rspb().Rint();//int
                else if(ts[tptr+1].eq(0,0))rspb().Rcall();//call func
                else rspb().Rvar();//var
            }
            ++tptr;
        }
        void Rkw(){
            if(ts[tptr].v==0){//if
                tp=3;
                tptr+=2;
                rspb().Rexpr();
                rspb().Rblock();
                if(ts[tptr].eq(3,1)){//else
                    ++tptr;
                    rspb().Rblock();
                }
            }else if(ts[tptr].v==2){//while
                tp=4;
                tptr+=2;
                rspb().Rexpr();
                rspb().Rblock();
            }else if(ts[tptr].v==3){//for
                tp=5;
                tptr+=2;
                rspb();
                if(ts[tptr].eq(3,4))vs.Rs(),rs.back().tp=12;
                else rs.back().Rexpr();
                rspb().Rexpr();
                rspb().Rexpr();
                rspb().Rblock();
            }else{//return
                tp=6;
                ++tptr;
                rspb().Rexpr();
            }
        }
        void Rblock(){
            if(!ts[tptr].eq(0,4)){
                if(ts[tptr].tp==3)Rkw();
                else Rexpr();
                return;
            }
            tp=1;
            ++tptr;
            while(!ts[tptr].eq(0,5)){
                if(ts[tptr].tp==3){
                    if(ts[tptr].v==4){
                        int L=vs.vs.size();
                        vs.Rs();
                        int R=vs.vs.size();
                        rspb().setvdim(L,R,vs);
                    }else rspb().Rkw();
                }else rspb().Rblock();
            }
            ++tptr;
        }
        void Rfunc(){
            tp=0;
            tptr+=3;
            if(ts[tptr].eq(0,1))++tptr;
            else do{
                ++tptr;
                vs.R();
            }while(!ts[tptr++].eq(0,1));
            rspb().Rblock();
        }
    }funcs[7007];
    #define run(x) _runs[x.tp](x)
    int (*_runs[30])(node&);
    void (*_ops[30])();
    bool ret_flag=0;
    int _func(node&w){
        w.vs.def(0);
        int r=run(w.rs[0]);
        w.vs.undef();
        ret_flag=0;
        void push(int);
        push(r);
        return r;
    }
    int _block(node&w){
        *mp++=0;
        int r=0;
        for(int i=0;i<w.rs.size()&&!ret_flag;++i)r=run(w.rs[i]);
        w.vs.undefs();
        return r;
    }
    int _expr(node&w){
        if(w.rs.empty())return 1;
        for(int i=0;i<w.rs.size();++i)run(w.rs[i]);
        int&pop();
        return pop();
    }
    int _if(node&w){
        int r=0;
        if(run(w.rs[0]))r=run(w.rs[1]);
        else if(w.rs.size()==3)r=run(w.rs[2]);
        return r;
    }
    int _while(node&w){
        int r=0;
        while(!ret_flag&&run(w.rs[0]))r=run(w.rs[1]);
        return r;
    }
    int _for(node&w){
        int r=0;
        w.vs.def();
        for(run(w.rs[0]);!ret_flag&&run(w.rs[1]);run(w.rs[2]))r=run(w.rs[3]);
        w.vs.undef();
        return r;
    }
    int _ret(node&w){
        int r=run(w.rs[0]);
        ret_flag=1;
        return r;
    }
    int _var(node&w){
        mp[0]=w.v;
        mp[1]=0;
        mp[2]=0;
        mp+=3;
    }
    void push(int x){
        mp[0]=-1;
        mp[1]=x;
        mp[2]=0;
        mp+=3;
    }
    int _int(node&w){
        push(w.v);
    }
    int _nod(node&w){}
    int _call(node&w){
        for(int i=0;i<w.rs.size();++i){
            int r=run(w.rs[i]);
            *mp++=r;
        }
        mp-=w.rs.size();
        return run(funcs[w.v]);
    }
    int&pop(){
        mp-=3;
        return *mp<0?mp[1]:var_now[*mp].back().dat[mp[2]];
    }
    void _arr(){
        int x=pop();
        mp[-1]*=var_now[mp[-3]].back().dsz[mp[-2]++];
        mp[-1]+=x;
    }
    void _not(){push(!pop());}
    void _pos(){push(pop());}
    void _neg(){push(-pop());}
    #define dop(x,y) void x(){int b=pop(),a=pop();push(y);}
    dop(_mul,a*b)
    dop(_div,a/b)
    dop(_mod,a%b)
    dop(_add,a+b)
    dop(_sub,a-b)
    dop(_leq,a<=b)
    dop(_meq,a>=b)
    dop(_lss,a<b)
    dop(_mre,a>b)
    dop(_eq,a==b)
    dop(_neq,a!=b)
    dop(_xor,!a+!b==1)
    dop(_and,a&&b)
    dop(_or,a||b)
    void _set(){
        int b=pop();
        pop()=b;
        push(b);
    }
    void _in(){
        pop()=__in[_inp++];
    }
    void _out(){
        int x=pop();
        if(mp[0]==3)puts("");
        else printf("%d",x);
    }
    int _op(node&w){
        _ops[w.v]();
    }
    int _vdim(node&w){
        w.vs.defs();
    }
    int _pc(node&w){
        int c=*mp;
        putchar(c);
        push(c);
        return c;
    }
    void pre2(){
        while(tptr<tp){
            if(ts[tptr+2].tp==0&&ts[tptr+2].v==0)funcs[ts[tptr+1].v].Rfunc();
            else glob_var.Rs();
        }
    }
    int main(){
        _runs[0]=_func;
        _runs[1]=_block;
        _runs[2]=_expr;
        _runs[3]=_if;
        _runs[4]=_while;
        _runs[5]=_for;
        _runs[6]=_ret;
        _runs[7]=_var;
        _runs[8]=_int;
        _runs[9]=_call;
        _runs[10]=_op;
        _runs[11]=_pc;
        _runs[12]=_nod;
        _runs[13]=_vdim;
        _ops[2]=_arr;
        _ops[6]=_not;_ops[7]=_pos;_ops[8]=_neg;
        _ops[9]=_mul;_ops[10]=_div;_ops[11]=_mod;
        _ops[12]=_add;_ops[13]=_sub;
        _ops[14]=_leq;_ops[15]=_meq;_ops[16]=_lss;_ops[17]=_mre;
        _ops[18]=_eq;_ops[19]=_neq;
        _ops[20]=_xor;
        _ops[21]=_and;
        _ops[22]=_or;
        _ops[23]=_set;
        _ops[24]=_out;
        _ops[25]=_in;
        rka[6]=rka[7]=rka[8]=rka[23]=1;
        ops["("]=0;ops[")"]=1;
        ops["["]=2;ops["]"]=3;
        ops["{"]=4;ops["}"]=5;
        ops["!"]=6;ops["+"]=7;ops["-"]=8;
        ops["*"]=9;ops["/"]=10;ops["%"]=11;
        ops["<="]=14;ops[">="]=15;ops["<"]=16;ops[">"]=17;
        ops["=="]=18;ops["!="]=19;
        ops["^"]=20;
        ops["&&"]=21;
        ops["||"]=22;
        ops["="]=23;
        ops["<<"]=24;ops[">>"]=25;
        ops[","]=26;
        ops[";"]=27;
        kws["if"]=0;
        kws["else"]=1;
        kws["while"]=2;
        kws["for"]=3;
        kws["int"]=4;
        kws["return"]=5;
        vars["cin"]=++vid;
        vars["cout"]=++vid;
        vars["endl"]=++vid;
        funcs[vars["putchar"]=++vid].tp=11;
        fread(buf,1,sizeof(buf),stdin)[buf]=-1;
        pre();
        pre2();
        glob_var.ins(1);
        glob_var.ins(2);
        glob_var.ins(3);
        glob_var.def();
        run(funcs[vars["main"]]);
        return 0;
    }
    View Code
  • 相关阅读:
    HDU 1754线段树基本操作,建树,更新,查询
    用第三方下载工具下载官方XCode独立安装包的方法
    解决Windows平台通过cURL上传APP到蒲公英pgyer平台时无法使用中文升级描述的问题
    Cygwin 版本的 Curl 安装,提取,使用笔记
    Android Gradle 引用本地 AAR 的几种方式
    VM虚拟机快照还原效果实现方式
    插入中文错误ERROR 1406 (22001): Data too long for column 'name' at row 1
    mysql初始化默认为空的密码修改
    性能测试学习计划(转)
    context-param和init-param区别
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7296226.html
Copyright © 2011-2022 走看看