bzoj4020: 未来程序·改

时间:2023-03-10 07:03:40
bzoj4020: 未来程序·改

只需写一个解释器

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

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

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

#include<cstdio>
#include<map>
#include<string>
#include<vector>
#include<cstring>
using namespace std;
int mem[],*mp=mem;
char buf[],*ptr=buf;
char stk[];
int stp=;
map<string,int>ops,kws,vars;
int vid=;
int rk[]={,,,,,,,,,,,,,,,,,,,,,,,,,,,};
int rka[];
struct token{
int tp;//operator:0 integer:1 var_name:2 keyword:3
int v;
void init2(){
tp=;
string a(stk);
if(kws.find(a)!=kws.end()){
tp=;
v=kws[a];
}else if(vars.find(a)!=vars.end()){
v=vars[a];
}else{
v=vars[a]=++vid;
}
}
void init1(int x){
tp=;
v=x;
}
void init0(){
tp=;
v=ops[string(stk)];
if((v==||v==)&&(this[-].tp==||this[-].tp==||this[-].eq(,)||this[-].eq(,)))v+=;
}
bool eq(int a,int b){
return tp==a&&v==b;
}
}ts[];
int tp=,tptr=;
bool isname(char x){
return isalpha(x)||isdigit(x)||x=='_'||x=='$';
}
int _n,__in[],_inp=;
int _ri(){
int x=,f=;
while(!isdigit(*ptr))*ptr++=='-'?f=-:;
while(isdigit(*ptr))x=x*+*ptr++-;
return x*f;
}
void pre(){
_n=_ri();
for(int i=;i<_n;++i)__in[i]=_ri();
for(;*ptr!=';';++ptr);++ptr;
while(){
for(;*ptr!=-&&*ptr<;++ptr);
if(*ptr==-)break;
stp=;
if(isalpha(*ptr)){
for(;isname(*ptr);stk[stp++]=*ptr++);stk[stp]=;
ts[tp++].init2();
}else if(isdigit(*ptr)){
ts[tp++].init1(_ri());
}else{
stk[stp++]=*ptr++;
stk[]=*ptr;
stk[]=;
if(ops.find(string(stk))!=ops.end())++ptr;
else stk[]=;
ts[tp].init0();++tp;
}
}
}
#define ptr __
struct var{
int id,*dat,sz;
vector<int>dsz;
var(){sz=,id=;}
void newdim(int x){
dsz.push_back(x);
sz*=x;
}
};
vector<var>var_now[];
struct varlist{
std::vector<var>vs;
void def(bool init=){
for(int i=;i<vs.size();++i){
var&w=vs[i];
if(init)memset(mp,,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=;i<vs.size();++i){
var&w=vs[i];
memset(mp,,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=;i<vs.size();++i){
var_now[vs[i].id].pop_back();
mp-=vs[i].sz;
}
}
void undefs(){
int mx=*--mp;
for(int i=;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(,);tptr+=)w.newdim(ts[tptr+].v);
vs.push_back(w);
}
void Rs(){
for(++tptr;;){
R();
if(ts[tptr++].v==)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=,v=ts[tptr++].v;}
void Rint(){tp=,v=ts[tptr++].v;}
void setop(int w){tp=,v=w;}
void Rcall(){
tp=;
v=ts[tptr].v;
tptr+=;
while(!ts[tptr-].eq(,))rspb().Rexpr();
}
void setvdim(int L,int R,varlist&w){
tp=;
for(int i=L;i<R;++i)vs.vs.push_back(w.vs[i]);
}
void Rexpr(){
tp=;
vector<int>ops;
ops.push_back();
while(){
if(ts[tptr].tp==){//oper
if(ts[tptr].v>=){
while(ops.back()){
rspb().setop(ops.back());
ops.pop_back();
}
break;
}
int v=ts[tptr].v;
if(v==||v==)ops.push_back(v);
else if(v==){
while(ops.back()){
rspb().setop(ops.back());
ops.pop_back();
}
ops.pop_back();
if(ops.empty())break;
}else if(v==){
int c;
do{
c=ops.back();
rspb().setop(c);
ops.pop_back();
}while(c!=);
}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==)rspb().Rint();//int
else if(ts[tptr+].eq(,))rspb().Rcall();//call func
else rspb().Rvar();//var
}
++tptr;
}
void Rkw(){
if(ts[tptr].v==){//if
tp=;
tptr+=;
rspb().Rexpr();
rspb().Rblock();
if(ts[tptr].eq(,)){//else
++tptr;
rspb().Rblock();
}
}else if(ts[tptr].v==){//while
tp=;
tptr+=;
rspb().Rexpr();
rspb().Rblock();
}else if(ts[tptr].v==){//for
tp=;
tptr+=;
rspb();
if(ts[tptr].eq(,))vs.Rs(),rs.back().tp=;
else rs.back().Rexpr();
rspb().Rexpr();
rspb().Rexpr();
rspb().Rblock();
}else{//return
tp=;
++tptr;
rspb().Rexpr();
}
}
void Rblock(){
if(!ts[tptr].eq(,)){
if(ts[tptr].tp==)Rkw();
else Rexpr();
return;
}
tp=;
++tptr;
while(!ts[tptr].eq(,)){
if(ts[tptr].tp==){
if(ts[tptr].v==){
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=;
tptr+=;
if(ts[tptr].eq(,))++tptr;
else do{
++tptr;
vs.R();
}while(!ts[tptr++].eq(,));
rspb().Rblock();
}
}funcs[];
#define run(x) _runs[x.tp](x)
int (*_runs[])(node&);
void (*_ops[])();
bool ret_flag=;
int _func(node&w){
w.vs.def();
int r=run(w.rs[]);
w.vs.undef();
ret_flag=;
void push(int);
push(r);
return r;
}
int _block(node&w){
*mp++=;
int r=;
for(int i=;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 ;
for(int i=;i<w.rs.size();++i)run(w.rs[i]);
int&pop();
return pop();
}
int _if(node&w){
int r=;
if(run(w.rs[]))r=run(w.rs[]);
else if(w.rs.size()==)r=run(w.rs[]);
return r;
}
int _while(node&w){
int r=;
while(!ret_flag&&run(w.rs[]))r=run(w.rs[]);
return r;
}
int _for(node&w){
int r=;
w.vs.def();
for(run(w.rs[]);!ret_flag&&run(w.rs[]);run(w.rs[]))r=run(w.rs[]);
w.vs.undef();
return r;
}
int _ret(node&w){
int r=run(w.rs[]);
ret_flag=;
return r;
}
int _var(node&w){
mp[]=w.v;
mp[]=;
mp[]=;
mp+=;
}
void push(int x){
mp[]=-;
mp[]=x;
mp[]=;
mp+=;
}
int _int(node&w){
push(w.v);
}
int _nod(node&w){}
int _call(node&w){
for(int i=;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-=;
return *mp<?mp[]:var_now[*mp].back().dat[mp[]];
}
void _arr(){
int x=pop();
mp[-]*=var_now[mp[-]].back().dsz[mp[-]++];
mp[-]+=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==)
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[]==)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+].tp==&&ts[tptr+].v==)funcs[ts[tptr+].v].Rfunc();
else glob_var.Rs();
}
}
int main(){
_runs[]=_func;
_runs[]=_block;
_runs[]=_expr;
_runs[]=_if;
_runs[]=_while;
_runs[]=_for;
_runs[]=_ret;
_runs[]=_var;
_runs[]=_int;
_runs[]=_call;
_runs[]=_op;
_runs[]=_pc;
_runs[]=_nod;
_runs[]=_vdim;
_ops[]=_arr;
_ops[]=_not;_ops[]=_pos;_ops[]=_neg;
_ops[]=_mul;_ops[]=_div;_ops[]=_mod;
_ops[]=_add;_ops[]=_sub;
_ops[]=_leq;_ops[]=_meq;_ops[]=_lss;_ops[]=_mre;
_ops[]=_eq;_ops[]=_neq;
_ops[]=_xor;
_ops[]=_and;
_ops[]=_or;
_ops[]=_set;
_ops[]=_out;
_ops[]=_in;
rka[]=rka[]=rka[]=rka[]=;
ops["("]=;ops[")"]=;
ops["["]=;ops["]"]=;
ops["{"]=;ops["}"]=;
ops["!"]=;ops["+"]=;ops["-"]=;
ops["*"]=;ops["/"]=;ops["%"]=;
ops["<="]=;ops[">="]=;ops["<"]=;ops[">"]=;
ops["=="]=;ops["!="]=;
ops["^"]=;
ops["&&"]=;
ops["||"]=;
ops["="]=;
ops["<<"]=;ops[">>"]=;
ops[","]=;
ops[";"]=;
kws["if"]=;
kws["else"]=;
kws["while"]=;
kws["for"]=;
kws["int"]=;
kws["return"]=;
vars["cin"]=++vid;
vars["cout"]=++vid;
vars["endl"]=++vid;
funcs[vars["putchar"]=++vid].tp=;
fread(buf,,sizeof(buf),stdin)[buf]=-;
pre();
pre2();
glob_var.ins();
glob_var.ins();
glob_var.ins();
glob_var.def();
run(funcs[vars["main"]]);
return ;
}