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 ;
}
bzoj4020: 未来程序·改的更多相关文章
- 如何A掉未来程序改
话说有这样一道神题:[集训队互测2015]未来程序·改. 大意是要求写一个简单的C++解释器!这里去掉了C++的许多特性,连简单的break和continue都没有了! 话说NOI被屠了之后,一时心血 ...
- uoj98未来程序改 纯暴力不要想了
暴力模拟A了,数据还是良(shui)心(shui)的 90分的地方卡了半天最后发现一个局部变量被我手抖写到全局去了,,, 心碎*∞ 没什么好解释的,其实只要写完表达式求值(带函数和变量的),然后处理一 ...
- 问题-某个程序改了ICO图标后编译后还是显示老图标?
问题现象:某个程序改了ICO图标后编译后还是显示老图标? 问题原原:可能是因为系统的缓存问题. 问题处理:把程序的EXE放在别的路径下打开就可以了. 问题相关人员:QQ253120114(朋友) Q ...
- uoj#73 【WC2015】未来程序
在 2047 年,第 64 届全国青少年信息学奥林匹克冬令营前夕,B君找到了 2015 年,第 32 届冬令营的题目来练习. 他打开了第三题 “未来程序” 这道题目: 本题是一道提交答案题,一共 10 ...
- Uoj 73 未来程序
Uoj 73 未来程序 神仙提答. Subtask 1 仔细阅读,发现是要计算 \(a*b\ \%\ c\).用龟速乘或者 \(python\) 直接算. Subtask 2 仔细阅读并手算一下,发现 ...
- VS2013中,将Qt的GUI程序改为控制台程序
在Visual studio 中创建QT GUI程序是不带Console的,但是调试时候常常需要查看打印信息,可以通过如下设置显示控制台 方法一.在vs中直接创建控制台程序方法二.当你通过设置你的应用 ...
- 昨晚值班将发dla的程序改好后放入正式环境
可是在修改的topic的发送文件中出现有节点没有对应,整个过程陆续调至有20分钟最后11电把新程序换掉.
- 四则运算程序扩展:将程序改为java语言,并允许用户输入,对输入结果进行验证
题目 每个同学选一个方向,把程序扩展一下:1.让程序能接受用户输入答案,并判定对错.最后给出总共对/错 的数量.2.把程序变成一个网页程序,用户通过设定参数,就可以得到各种题目.3.把程序变成一个Wi ...
- 小程序--改变子级别页面导航栏信息 / navigationBarTitleText
微信小程序在公共文件app.json中设置了导航栏相关样式如下: 其中 navigationBarTitleText 为设置导航栏名称,若是想子级页面和父页面的header页面不同,则在子级文件中新 ...
随机推荐
- 配置apache-maven-3.6.0时所遇到的坑(一)
在命令行窗口中输入:mvn -v 或 直接 mvn 时报错:“错误: 找不到或无法加载主类 org.codehaus.plexus.classworlds.launcher.Lau ...
- 数据类型int、float、str、list、dict、set定义及常用方法汇总
数据类型int:记录整数事物状态 可变不可变:值不可变类型,改变变量值实则是改变了变量的指向 int():功能:1.工厂函数, i = 5 <==> i = int(5) 2.强制类型转换 ...
- border重叠的问题
可以在css中添加border:0:去掉其中的一条border
- opencv掩模操作
//设置变量,读图 Mat image, mask; Mat img1, img2, img3, img4; image = imread("data/img/1.jpg"); / ...
- 深入浅出理解 COOKIE MAPPING
转载自:http://www.myttnn.com/digital-marketing/cookie-mapping-introduction/ 在RTB(实时竞价广告,Real-Time-Biddi ...
- shell基础入门(一)
//获取输入内容 #!/bin/bash echo "What is your name?" read PERSON read -p "who are you name: ...
- MySQL Cursor Demo
-- 使用cursor的demo -- ==============================## -- 删除存储过程 DROP PROCEDURE USP_TestCursor; DELIMI ...
- What's New In Zeebe: Scaling Zeebe, New Client APIs, Faster Requests, Timestamps, NodeJS Client, and Default Topic is Back!
Written by Daniel Meyer on May 16 2018 in the What's New In Zeebe category. Welcome to the first-eve ...
- 使用prometheus+ grafana+nginx-module-vts 模块监控openresty
nginx-module-vts 是一个很不错的nginx 模块,我们可以用来,方便的分析系统的请求状态 同时支持基于prometheus 的监控, 我参考openresty 的docker镜像已 ...
- 【HI3520DV200】sample
1.vdec不支持1280x720,支持640x480及以下