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
原文地址:https://www.cnblogs.com/ccz181078/p/7296226.html