只需写一个解释器

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

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

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

#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: 未来程序·改的更多相关文章

  1. 如何A掉未来程序改

    话说有这样一道神题:[集训队互测2015]未来程序·改. 大意是要求写一个简单的C++解释器!这里去掉了C++的许多特性,连简单的break和continue都没有了! 话说NOI被屠了之后,一时心血 ...

  2. uoj98未来程序改 纯暴力不要想了

    暴力模拟A了,数据还是良(shui)心(shui)的 90分的地方卡了半天最后发现一个局部变量被我手抖写到全局去了,,, 心碎*∞ 没什么好解释的,其实只要写完表达式求值(带函数和变量的),然后处理一 ...

  3. 问题-某个程序改了ICO图标后编译后还是显示老图标?

    问题现象:某个程序改了ICO图标后编译后还是显示老图标? 问题原原:可能是因为系统的缓存问题. 问题处理:把程序的EXE放在别的路径下打开就可以了. 问题相关人员:QQ253120114(朋友)  Q ...

  4. uoj#73 【WC2015】未来程序

    在 2047 年,第 64 届全国青少年信息学奥林匹克冬令营前夕,B君找到了 2015 年,第 32 届冬令营的题目来练习. 他打开了第三题 “未来程序” 这道题目: 本题是一道提交答案题,一共 10 ...

  5. Uoj 73 未来程序

    Uoj 73 未来程序 神仙提答. Subtask 1 仔细阅读,发现是要计算 \(a*b\ \%\ c\).用龟速乘或者 \(python\) 直接算. Subtask 2 仔细阅读并手算一下,发现 ...

  6. VS2013中,将Qt的GUI程序改为控制台程序

    在Visual studio 中创建QT GUI程序是不带Console的,但是调试时候常常需要查看打印信息,可以通过如下设置显示控制台 方法一.在vs中直接创建控制台程序方法二.当你通过设置你的应用 ...

  7. 昨晚值班将发dla的程序改好后放入正式环境

    可是在修改的topic的发送文件中出现有节点没有对应,整个过程陆续调至有20分钟最后11电把新程序换掉.

  8. 四则运算程序扩展:将程序改为java语言,并允许用户输入,对输入结果进行验证

    题目 每个同学选一个方向,把程序扩展一下:1.让程序能接受用户输入答案,并判定对错.最后给出总共对/错 的数量.2.把程序变成一个网页程序,用户通过设定参数,就可以得到各种题目.3.把程序变成一个Wi ...

  9. 小程序--改变子级别页面导航栏信息 / navigationBarTitleText

    微信小程序在公共文件app.json中设置了导航栏相关样式如下: 其中  navigationBarTitleText 为设置导航栏名称,若是想子级页面和父页面的header页面不同,则在子级文件中新 ...

随机推荐

  1. JAVA中native方法调用

    在Java中native是关键字.它一般在本地声明,异地用C和C++来实现.它的声明有几点要注意:1)native与访问控制符前后的关系不受限制.2)必须在返回类型之前.3)它一般为非抽象类方法.4) ...

  2. C++学习(八)(C语言部分)之 图形库

    有关图形库的学习笔记 1.安装 ww.easys.cn 2.创建win32控制台应用程序 .cpp文件(图形库必须创建cpp文件) *重点 3.安装好后 重启一下vs 图形库 是一些函数的集合 作用是 ...

  3. 实验吧—安全杂项——WP之 女神

    点击链接下载压缩文件解压后得到 打开TXT文档: 能看出是base64,这么长,那就是转成图片喽~ 地址:http://www.vgot.net/test/image2base64.php? 然后就是 ...

  4. 如何对oracle数据库进行监控检查

    sqlplus '/as sysdba' 手动生成一个oracle数据库的快照 execute dbbms_workload_repository.create_snapshot(); 执行自动工作负 ...

  5. mysqldump命令之常用模板

    ##=====================================================## ## 在Master上导出所有数据库 /export/servers/mysql/b ...

  6. scala学习笔记-面向对象编程之Trait

    将trait作为接口使用 1 // Scala中的Triat是一种特殊的概念 2 // 首先我们可以将Trait作为接口来使用,此时的Triat就与Java中的接口非常类似 3 // 在triat中可 ...

  7. WebSocket概念

    WebSocket 是什么? WebSocket 是一种网络通信协议.RFC6455 定义了它的通信标准. WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议 ...

  8. ZeroTier One

    ZeroTier – 无配置,零基础「内网穿透」随时随地连回家/学校/办公室 [跨平台] https://www.appinn.com/zerotier-one/ Virtual NetworkZer ...

  9. git 常见命令 和 git 原理图

    git 工作原理图:git 有4 个仓库 这是 git和 svn 一个巨大的区别,所以git 没网也能提交代码和查看记录. svn 只有2 个仓库 ,一个远程一个本地. 1 创建git 仓库(  参数 ...

  10. NET设计模式 第二部分 结构性模式(10):组合模式(Composite Pattern)

    组合模式(Composite Pattern) ——.NET设计模式系列之十一 Terrylee,2006年3月 概述 组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复 ...