【集训队互测2015】未来程序·改
模拟,暴力
题目大意:
要求实现一个简易 C++ 解释器,支持部分功能。给定输入以及源代码,求输出结果。
题解:
由于给定的源代码并不长,所以可以用比较暴力的方式模拟。
程序分为以下几个部分:
- 初始化输入流。
- 分析代码。
- 划分语段。
- 运行代码。
主要需要实现的内容:
- 表达式求值。
- 代码运行部分。
分析代码的时候,运算符的匹配采用贪心的原则。右结合的 +
,-
操作可以记为 $+
,$-
以进行区分。
if else
的匹配采用就近原则,贪心匹配。
对表达式求值的复杂度要求不高,可以暴力处理。具体就是按照优先级从大到小展开(最高的是括号,括号部分递归计算,然后再匹配函数参数以及数组下标。匹配时左结合计算,否则会在一些 UB 的时候得到非预期答案。之后是剩余字符)。注意将变量、常数、运算符、函数分开记录。
putchar
可以记为特殊的函数。
cin/cout/endl
可以记为特殊的变量(单独开一类),也可以考虑记为关键字。注意 for
的第一、三个部分可以 cin/cout
,所以采用记为变量的方式会比较方便。
有毒瘤数据,要写内存池防止内存泄露。
{}
里面一定有语句,但是会出现 {...;{...;}...;}
即无征兆地出现花括号的情况。
还有一些其他小细节,不一一列举。
代码加注释共 $22.7\texttt{KB}$,其中有不少复制粘贴的,所以感觉也没很难写。
Code:
/*
未来程序·改
By mrsrz
2020-10-07 ~ 2020-10-08
*/
// Pascal is too hard.
#include<bits/stdc++.h>
using namespace std;
inline void ErrorThrow(string s){
cerr<<s<<endl;
exit(1);
}
string code;
map<string,int>IndexOperator;
inline void _set(string s,int x){IndexOperator[s]=x;}
struct Block{
struct __commands{
int tp;
/*
tp:
1. Variables define
2. Common expression
3. For
4. While
5. If
6. Return
7. New block
*/
int id;
};
vector<__commands>cmd;
void set(int,int);
int run(bool&);
};
Block B[50005];
struct Istream{
int n,a[100005],it;
void Init(){
cin>>n,it=0;
for(int i=1;i<=n;++i)cin>>a[i];
}
inline int nextInt(){return a[++it];}
}InputBuffer; // input stream
struct _word_{
string s[10005];
int n,type[10005];
/*
type:
1: keywords
2: variable or function
3: constant
4: operator
5: bracket
*/
void push(string t,int tp){
s[++n]=t,type[n]=tp;
}
}words;
struct variable{ // variable
vector<int>A;
vector<int>MEM;
string name;
int size;
inline void MEMset(){
size=1;
for(int i=0;i<(int)A.size();++i)size*=A[i];
MEM.clear();MEM.resize(size);
}
inline int get_address(vector<int>&v){
if(v.size()!=A.size())ErrorThrow("Compile Error! Exit code=4");
int ad=0;
for(int i=0;i<(int)v.size();++i){
if(v[i]>=A[i])ErrorThrow("Runtime Error! Segment Fault!");
ad=ad*A[i]+v[i];
}
return ad;
}
inline int&get(int address){
if(address>size||address<0)ErrorThrow("Runtime Error! Segment Fault!");
return MEM[address];
}
inline int&get(vector<int>&v){return get(get_address(v));}
}__v[20005];
vector<int>memory_id;
map<string,vector<int> >IndexVar;
int new_var(vector<int>A,string name){
int id=memory_id.back();
memory_id.pop_back();
__v[id].A=A,__v[id].name=name;
__v[id].MEMset();
IndexVar[name].push_back(id);
return id;
}
void dispose_id(int id){
if(IndexVar[__v[id].name].back()!=id)ErrorThrow("Memory Error!");
IndexVar[__v[id].name].pop_back();
__v[id].name="",__v[id].A.clear(),__v[id].MEM.clear();
memory_id.push_back(id);
}
void assignment(string name,vector<int>address,int val){
__v[IndexVar[name].back()].get(address)=val;
}
map<string,int>IndexFunc;
struct Func{
string name; // function name
vector<string>para_name; // parameter
int _main_id; // commands
int run(vector<int>VAR){
if(VAR.size()!=para_name.size())
ErrorThrow("Compile Error! Exit code=3");
for(int i=0;i<(int)VAR.size();++i){
new_var(vector<int>(),para_name[i]);
assignment(para_name[i],vector<int>(),VAR[i]);
}
bool isreturn=0;
int res=B[_main_id].run(isreturn);
for(int i=0;i<(int)VAR.size();++i){
dispose_id(IndexVar[para_name[i]].back());
}
return res;
}
}__func[2005];
int __func_tot;
// -----------------------------------------------------------------------------------------------
int _returntot,_iftot,_whiletot,_fortot,_definetot,EXPtot,Blocktot,_cintot,_couttot;
struct calc_member{
int type; // 1: variable 2: constant 3: operator 4: function 5: iostream
int id_val;// type=1: variable_id type=2: value type=3: operator_id type=4:parameter type=5:cin=1/cout=2/endl=3
int address;// type=1: address_of_array type=2,3,4: undefined
};
inline int turn_to_value(const calc_member&c){
if(c.type==2)return c.id_val;
if(c.type==1)return __v[c.id_val].get(c.address);
ErrorThrow("Runtime Error!");
return 1;
}
int get_nextpara(vector<calc_member>&v,int&pos){
if(v[pos].type==2||(v[pos].type==1&&v[pos].address!=-1))
return turn_to_value(v[pos++]);
int it=pos+1,rem=pos;
vector<int>lst;
if(v[pos].type==1){
for(int j=0;j<(int)__v[v[pos].id_val].A.size();++j)
lst.push_back(get_nextpara(v,it));
pos=it;
return __v[v[rem].id_val].get(lst);
}else{
for(int j=0;j<(int)__func[v[pos].id_val].para_name.size();++j)
lst.push_back(get_nextpara(v,it));
pos=it;
if(v[rem].id_val==1){
// putchar
cout.put(lst[0]);
return lst[0];
}else return __func[v[rem].id_val].run(lst);
}
}
struct EXPR{
// The most important part of the program.
int L,R;
void set(int l,int r){L=l,R=r;}
calc_member _CALC_(vector<calc_member>v,int level=1){
vector<calc_member>m,tmp;
switch(level){
case 1:{
for(int i=0;i<(int)v.size();++i){
if(v[i].type==3&&(v[i].id_val==2||v[i].id_val==4)){
while(m.size()&&(m.back().type!=3||(m.back().id_val!=1&&m.back().id_val!=3)))
tmp.push_back(m.back()),m.pop_back();
m.pop_back();
if(tmp.size())
reverse(tmp.begin(),tmp.end()),m.push_back((calc_member){2,turn_to_value(_CALC_(tmp,0))});
tmp.clear();
}else m.push_back(v[i]);
}
v=m,m.clear();
}
case 0:{
vector<int>lst;
for(int i=0;i<(int)v.size();){
if(v[i].type!=1&&v[i].type!=4)m.push_back(v[i++]);
else if(v[i].type==4){
int t=i+1;
for(int j=0;j<(int)__func[v[i].id_val].para_name.size();++j)
lst.push_back(get_nextpara(v,t));
if(v[i].id_val==1){
// putchar
m.push_back((calc_member){2,lst[0]});
cout.put(lst[0]);
}else m.push_back((calc_member){2,__func[v[i].id_val].run(lst)});
lst.clear();
i=t;
}else{
int t=i+1;
for(int j=0;j<(int)__v[v[i].id_val].A.size();++j)
lst.push_back(get_nextpara(v,t));
m.push_back((calc_member){1,v[i].id_val,__v[v[i].id_val].get_address(lst)});
lst.clear();
i=t;
}
}
v=m,m.clear();
}
case 2:{
for(int i=(int)v.size()-1;~i;--i){
if(v[i].type!=3)m.push_back(v[i]);
else{
switch(v[i].id_val){
case 5:{
int value=turn_to_value(m.back());
m.pop_back();
m.push_back((calc_member){2,!value});
break;
}
case 6:{
int value=turn_to_value(m.back());
m.pop_back();
m.push_back((calc_member){2,+value});
break;
}
case 7:{
int value=turn_to_value(m.back());
m.pop_back();
m.push_back((calc_member){2,-value});
break;
}
default:m.push_back(v[i]);
}
}
}
v=m,m.clear();
reverse(v.begin(),v.end());
}
case 3:{
for(int i=0;i<(int)v.size();++i){
if(v[i].type==3){
switch(v[i].id_val){
case 8:{
calc_member L=m.back();
m.pop_back();
++i;
m.push_back((calc_member){2,turn_to_value(L)*turn_to_value(v[i])});
break;
}
case 9:{
calc_member L=m.back();
m.pop_back();
++i;
m.push_back((calc_member){2,turn_to_value(L)/turn_to_value(v[i])});
break;
}
case 10:{
calc_member L=m.back();
m.pop_back();
++i;
m.push_back((calc_member){2,turn_to_value(L)%turn_to_value(v[i])});
break;
}
default:m.push_back(v[i]);
}
}else m.push_back(v[i]);
}
v=m,m.clear();
}
case 4:{
for(int i=0;i<(int)v.size();++i){
if(v[i].type==3){
switch(v[i].id_val){
case 11:{
calc_member L=m.back();
m.pop_back();
++i;
m.push_back((calc_member){2,turn_to_value(L)+turn_to_value(v[i])});
break;
}
case 12:{
calc_member L=m.back();
m.pop_back();
++i;
m.push_back((calc_member){2,turn_to_value(L)-turn_to_value(v[i])});
break;
}
default:m.push_back(v[i]);
}
}else m.push_back(v[i]);
}
v=m,m.clear();
}
case 5:{
for(int i=0;i<(int)v.size();++i){
if(v[i].type==3){
switch(v[i].id_val){
case 13:{
calc_member L=m.back();
m.pop_back();
++i;
m.push_back((calc_member){2,turn_to_value(L)<=turn_to_value(v[i])});
break;
}
case 14:{
calc_member L=m.back();
m.pop_back();
++i;
m.push_back((calc_member){2,turn_to_value(L)>=turn_to_value(v[i])});
break;
}
case 15:{
calc_member L=m.back();
m.pop_back();
++i;
m.push_back((calc_member){2,turn_to_value(L)<turn_to_value(v[i])});
break;
}
case 16:{
calc_member L=m.back();
m.pop_back();
++i;
m.push_back((calc_member){2,turn_to_value(L)>turn_to_value(v[i])});
break;
}
default:m.push_back(v[i]);
}
}else m.push_back(v[i]);
}
v=m,m.clear();
}
case 6:{
for(int i=0;i<(int)v.size();++i){
if(v[i].type==3){
switch(v[i].id_val){
case 17:{
calc_member L=m.back();
m.pop_back();
++i;
m.push_back((calc_member){2,turn_to_value(L)==turn_to_value(v[i])});
break;
}
case 18:{
calc_member L=m.back();
m.pop_back();
++i;
m.push_back((calc_member){2,turn_to_value(L)!=turn_to_value(v[i])});
break;
}
default:m.push_back(v[i]);
}
}else m.push_back(v[i]);
}
v=m,m.clear();
}
case 7:{
for(int i=0;i<(int)v.size();++i)
if(v[i].type==3&&v[i].id_val==19){
calc_member L=m.back();
m.pop_back();
++i;
int result=(turn_to_value(L)==0)+(turn_to_value(v[i])==0);
if(result==2)result=0;
m.push_back((calc_member){2,result});
}else m.push_back(v[i]);
v=m,m.clear();
}
case 8:{
for(int i=0;i<(int)v.size();++i)
if(v[i].type==3&&v[i].id_val==20){
calc_member L=m.back();
m.pop_back();
++i;
m.push_back((calc_member){2,turn_to_value(L)&&turn_to_value(v[i])});
}else m.push_back(v[i]);
v=m,m.clear();
}
case 9:{
for(int i=0;i<(int)v.size();++i)
if(v[i].type==3&&v[i].id_val==21){
calc_member L=m.back();
m.pop_back();
++i;
m.push_back((calc_member){2,turn_to_value(L)||turn_to_value(v[i])});
}else m.push_back(v[i]);
v=m,m.clear();
}
case 10:{
for(int i=(int)v.size()-1;~i;--i)
if(v[i].type==3&&v[i].id_val==22){
--i;
calc_member R=m.back();
m.pop_back();
if(v[i].type!=1)ErrorThrow("Expression Error!");
__v[v[i].id_val].get(v[i].address)=turn_to_value(R);
m.push_back(v[i]);
}else m.push_back(v[i]);
v=m,m.clear();
reverse(v.begin(),v.end());
}
case 11:{
if(v.size()&&v[0].type==5){
if(v[0].id_val==0){
// cin
for(int i=1;i<(int)v.size();++i)
if(v[i].type==1)
__v[v[i].id_val].get(v[i].address)=InputBuffer.nextInt();
}else if(v[0].id_val==1){
// cout
for(int i=1;i<(int)v.size();++i)
if(v[i].type==5){
// endl
cout<<'\n';
}else if(v[i].type!=3)cout<<turn_to_value(v[i]);
}else ErrorThrow("Expression Error!");
v.resize(1);
}
}
case 12:return v[0];
}
ErrorThrow("Unknown Error!");
return(calc_member){0};
}
calc_member calc(){
if(L>R)return(calc_member){2,1};
vector<calc_member>vc;
for(int pos=L;pos<=R;++pos){
if(words.s[pos]=="cin"){
vc.push_back((calc_member){5,0});
}else if(words.s[pos]=="cout"){
vc.push_back((calc_member){5,1});
}else if(words.s[pos]=="endl"){
vc.push_back((calc_member){5,2});
}else if(words.type[pos]==4||words.type[pos]==5){
if(words.s[pos]==","){
vc.push_back((calc_member){3,IndexOperator[")"]});
vc.push_back((calc_member){3,IndexOperator["("]});
}else
vc.push_back((calc_member){3,IndexOperator[words.s[pos]]});
}else if(words.type[pos]==3){
vc.push_back((calc_member){2,atoi(words.s[pos].c_str())});
}else{
if(IndexFunc.count(words.s[pos])){
// function
vc.push_back((calc_member){4,IndexFunc[words.s[pos]]});
}else{
// variable
vc.push_back((calc_member){1,IndexVar[words.s[pos]].back(),-1});
}
}
}
return _CALC_(vc);
}
}EXPRESSION[50005];
struct VarDefine{
vector<string>name;
vector<vector<int> >W;
}_define[5005];
struct For{
int tp0,id0; // first statement
int _; // second statement
int id1; // third statement
int _block_id;
}_for[5005];
struct While{
int _;
int _block_id;
}_while[5005];
struct If{
int _;
int _then_id,_else_id;
}_if[5005];
struct Return{
int _;
}_return[5005];
// -----------------------------------------------------------------------------------------------
int FindNextsentense(int pos){
if(words.s[pos]=="{"){
int _=0;
for(int it=pos;it<=words.n;++it)
if(words.s[it]=="{")++_;
else if(words.s[it]=="}"){
if(!--_)return it;
}
ErrorThrow("Compile Error!");
}
if(words.s[pos]=="while"||words.s[pos]=="for"){
int _=0,it=pos;
for(;it<=words.n;++it){
if(words.s[it]=="(")++_;else
if(words.s[it]==")"){if(!--_)break;}
}
if(it>words.n)ErrorThrow("Compile Error!");
return FindNextsentense(it+1);
}
if(words.s[pos]=="if"){
int _=0,it=pos;
for(;it<=words.n;++it){
if(words.s[it]=="(")++_;else
if(words.s[it]==")"){if(!--_)break;}
}
if(it>words.n)ErrorThrow("Compile Error!");
int npos=FindNextsentense(it+1);
if(npos<words.n&&words.s[npos+1]=="else")
return FindNextsentense(npos+2);
return npos;
}
for(int it=pos;it<=words.n;++it)
if(words.s[it]==";")return it;
ErrorThrow("Compile Error!");
return 0;
}
void Block::set(int l,int r){
if(words.s[l]=="{"&&words.s[r]=="}")++l,--r;
for(int pos=l;pos<=r;){
if(words.s[pos]==";"){++pos;continue;}
else if(words.s[pos]=="{"){
int it=pos,_=0;
while(1){
if(words.s[it]=="{")++_;else
if(words.s[it]=="}"){if(!--_)break;}
++it;
}
cmd.push_back((__commands){7,++Blocktot});
B[Blocktot].set(pos,it);
pos=it+1;
}else if(words.type[pos]!=1){
// expression
cmd.push_back((__commands){2,++EXPtot});
int it=pos;
while(words.s[it]!=";")++it;
EXPRESSION[EXPtot].set(pos,it-1);
pos=it+1;
}else if(words.s[pos]=="int"){
// new variable define
cmd.push_back((__commands){1,++_definetot});
string name="";
vector<int>W;
++pos;
while(1){
if(words.type[pos]==2)name=words.s[pos];
else if(words.type[pos]==3)W.push_back(atoi(words.s[pos].c_str()));
else if(words.s[pos]==","||words.s[pos]==";"){
_define[_definetot].name.push_back(name);
_define[_definetot].W.push_back(W);
name="",W.clear();
}
if(words.s[pos]==";")break;
++pos;
}
}else if(words.s[pos]=="for"){
// for
cmd.push_back((__commands){3,++_fortot});
int _f=_fortot;
pos+=2;int it=pos;
while(words.s[it]!=";")++it;
if(words.s[pos]=="int"){
_for[_f].tp0=2;
_for[_f].id0=++_definetot;
string name="";
vector<int>W;
++pos;
while(1){
if(words.type[pos]==2)name=words.type[pos];
else if(words.type[pos]==3)W.push_back(atoi(words.s[pos].c_str()));
else if(words.s[pos]==","||words.s[pos]==";"){
_define[_definetot].name.push_back(name);
_define[_definetot].W.push_back(W);
name="",W.clear();
}
if(words.s[pos]==";")break;
}
}else{
_for[_f].tp0=1;
_for[_f].id0=++EXPtot;
EXPRESSION[EXPtot].set(pos,it-1);
}
pos=it+1;
for(it=pos;words.s[it]!=";";++it);
_for[_f]._=++EXPtot;
EXPRESSION[EXPtot].set(pos,it-1);
pos=it+1;
int _=1;
while(1){
if(words.s[it]=="(")++_;else
if(words.s[it]==")"){if(!--_)break;}
++it;
}
_for[_f].id1=++EXPtot;
EXPRESSION[EXPtot].set(pos,it-1);
pos=it+1;
_for[_f]._block_id=++Blocktot;
int endpos=FindNextsentense(pos);
B[_for[_f]._block_id].set(pos,endpos);
pos=endpos+1;
}else if(words.s[pos]=="while"){
// while
cmd.push_back((__commands){4,++_whiletot});
int _w=_whiletot;
while(words.s[pos]!="(")++pos;
int it=pos,_=0;
while(1){
if(words.s[it]=="(")++_;else
if(words.s[it]==")"){if(!--_)break;}
++it;
}
_while[_w]._=++EXPtot;
EXPRESSION[EXPtot].set(pos+1,it-1);
pos=it+1;
_while[_w]._block_id=++Blocktot;
int endpos=FindNextsentense(pos);
B[_while[_w]._block_id].set(pos,endpos);
pos=endpos+1;
}else if(words.s[pos]=="if"){
// if
cmd.push_back((__commands){5,++_iftot});
int _i=_iftot;
while(words.s[pos]!="(")++pos;
int it=pos,_=0;
while(1){
if(words.s[it]=="(")++_;else
if(words.s[it]==")"){if(!--_)break;}
++it;
}
_if[_i]._=++EXPtot;
EXPRESSION[EXPtot].set(pos+1,it-1);
pos=it+1;
_if[_i]._then_id=++Blocktot;
int endpos=FindNextsentense(pos);
B[_if[_i]._then_id].set(pos,endpos);
pos=endpos+1;
if(words.s[pos]=="else"){
_if[_i]._else_id=++Blocktot;
endpos=FindNextsentense(++pos);
B[_if[_i]._else_id].set(pos,endpos);
pos=endpos+1;
}else _if[_i]._else_id=0;
}else if(words.s[pos]=="return"){
// return
cmd.push_back((__commands){6,++_returntot});
int it=pos;
while(words.s[it]!=";"&&it<=r)++it;
_return[_returntot]._=++EXPtot;
EXPRESSION[EXPtot].set(pos+1,it-1);
pos=it+1;
}else ErrorThrow("Compile Error! Exit code=2");
}
}
int Block::run(bool&isreturn){
int res=0;
vector<int>var_id;
for(int i=0;i<(int)cmd.size();++i){
if(isreturn)break;
switch(cmd[i].tp){
case 1:{
// define
VarDefine&d=_define[cmd[i].id];
for(int j=0;j<(int)d.name.size();++j)
var_id.push_back(new_var(d.W[j],d.name[j]));
break;
}
case 2:{
// expression
EXPRESSION[cmd[i].id].calc();
break;
}
case 3:{
// for
For&F=_for[cmd[i].id];
vector<int>for_var_id;
if(F.tp0==1)EXPRESSION[F.id0].calc();
else{
VarDefine&d=_define[F.id0];
for(int j=0;j<(int)d.name.size();++j)
for_var_id.push_back(new_var(d.W[j],d.name[j]));
}
while(turn_to_value(EXPRESSION[F._].calc())){
res=B[F._block_id].run(isreturn);
if(isreturn)break;
EXPRESSION[F.id1].calc();
}
if(F.tp0==2){
for(int j=(int)for_var_id.size()-1;~j;--j)
dispose_id(for_var_id[j]);
}
break;
}
case 4:{
// while
While&w=_while[cmd[i].id];
while(turn_to_value(EXPRESSION[w._].calc())){
res=B[w._block_id].run(isreturn);
if(isreturn)break;
}
break;
}
case 5:{
// if
If&f=_if[cmd[i].id];
if(turn_to_value(EXPRESSION[f._].calc()))
res=B[f._then_id].run(isreturn);
else if(f._else_id!=0)
res=B[f._else_id].run(isreturn);
break;
}
case 6:{
// return
isreturn=1;
res=turn_to_value(EXPRESSION[_return[cmd[i].id]._].calc());
break;
}
case 7:{
Block&_B=B[cmd[i].id];
res=_B.run(isreturn);
break;
}
}
}
for(int i=(int)var_id.size()-1;~i;--i)
dispose_id(var_id[i]);
return res;
}
// -----------------------------------------------------------------------------------------------
inline bool isword(char ch){
return(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||ch=='_';
}
inline int GetOperatorPriority(string s){
//if(s=="["||s=="]"||s=="("||s==")")return 1;
if(s=="!"||s=="$+"||s=="$-")return 2;
if(s=="*"||s=="/"||s=="%")return 3;
if(s=="+"||s=="-")return 4;
if(s=="<="||s==">="||s=="<"||s==">")return 5;
if(s=="=="||s=="!=")return 6;
if(s=="^")return 7;
if(s=="&&")return 8;
if(s=="||")return 9;
if(s=="=")return 10;
if(s=="<<"||s==">>")return 11;
return 0;
}
inline int matchKeyword(string s){
if(s=="int")return 1;
if(s=="for")return 2;
if(s=="while")return 3;
if(s=="if")return 4;
if(s=="else")return 5;
if(s=="return")return 6;
return 0;
}
void readCode(){
string tmp;
getline(cin,tmp),getline(cin,tmp),getline(cin,tmp),getline(cin,tmp);
while(getline(cin,tmp))code+=' '+tmp;
}
void CodeDivide(string code){
string wd="";
for(int pos=0;pos<(int)code.length();){
if(code[pos]==' '||code[pos]=='\n'){++pos;continue;}
wd+=code[pos++];
if((wd=="<"||wd==">")&&(code[pos]=='='||wd[0]==code[pos])){
// match "<=", ">=", "<<", ">>"
wd+=code[pos++];
}else if((wd=="+"||wd=="-")&&(words.type[words.n]!=2&&words.type[words.n]!=3&&words.s[words.n]!=")"&&words.s[words.n]!="]")){
wd="$"+wd;
}else if((wd=="="||wd=="!")&&code[pos]=='='){
// match "==", "!="
wd+=code[pos++];
}else if((wd=="&"||wd=="|")&&code[pos]==wd[0]){
// match "&&", "||"
wd+=code[pos++];
}
if(!isword(wd[0])&&!isdigit(wd[0])){
// not constant or variable
if(GetOperatorPriority(wd))
words.push(wd,4);
else
words.push(wd,5);
wd="";
}
else if(isword(wd[0])&&!isword(code[pos])&&!isdigit(code[pos])){
// variable, function or keyword
if(matchKeyword(wd))
words.push(wd,1);
else
words.push(wd,2);
wd="";
}else if(isdigit(wd[0])&&!isdigit(code[pos])){
words.push(wd,3);
wd="";
}
}
}
void splitFunction(int l,int r){
++__func_tot;
Func&F=__func[__func_tot];
F.name=words.s[l];
IndexFunc[words.s[l]]=__func_tot;
int pos=l+1;
for(;words.s[pos]!=")";++pos)if(words.type[pos]==2)
F.para_name.push_back(words.s[pos]);
F._main_id=++Blocktot;
B[Blocktot].set(pos+1,r);
}
void splitVar(int l,int r){
string name;
vector<int>WD;
for(int i=l;i<=r;++i)
if(words.type[i]==2)name=words.s[i];
else if(words.type[i]==3)WD.push_back(atoi(words.s[i].c_str()));
else if(words.s[i]==","||words.s[i]==";"){
new_var(WD,name);
WD.clear(),name="";
}
}
void CodeBlock(){
for(int pos=1;pos<=words.n;){
if(words.s[pos]=="int"){
bool flag=0;
int _=0,i=pos+1;
while(1){
if(words.s[i]==";"&&!flag)break;
else if(words.s[i]=="{")flag=1,++_;
else if(words.s[i]=="}"){
if(!--_)break;
}
++i;
if(i>words.n)ErrorThrow("CodeBlock Error1");
}
if(flag){
// Function
splitFunction(pos+1,i);
}else{
// Variable
splitVar(pos+1,i);
}
pos=i+1;
}else ErrorThrow("CodeBlock Error2");
}
}
void CodeAnalysis(){
CodeDivide(code);
// for(int i=1;i<=words.n;++i)
// cerr<<i<<" : "<<words.s[i]<<" "<<words.type[i]<<endl;
CodeBlock();
}
void programInit(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
for(int i=0;i<20000;++i)memory_id.push_back(i);
_set("[",1),_set("]",2),_set("(",3),_set(")",4);
_set("!",5),_set("$+",6),_set("$-",7);
_set("*",8),_set("/",9),_set("%",10);
_set("+",11),_set("-",12);
_set("<=",13),_set(">=",14),_set("<",15),_set(">",16);
_set("==",17),_set("!=",18);
_set("^",19);
_set("&&",20);
_set("||",21);
_set("=",22);
_set(">>",23);
_set("<<",24);
__func[++__func_tot].name="putchar";
IndexFunc["putchar"]=__func_tot;
__func[__func_tot].para_name.push_back("c");
IndexVar["cin"]=IndexVar["cout"]=IndexVar["endl"]=vector<int>();
}
int main(){
programInit();
InputBuffer.Init();
readCode();
CodeAnalysis();
__func[IndexFunc["main"]].run(vector<int>());
return 0;
}