【集训队互测2015】未来程序·改

模拟,暴力

题目大意:

要求实现一个简易 C++ 解释器,支持部分功能。给定输入以及源代码,求输出结果。

题解:

由于给定的源代码并不长,所以可以用比较暴力的方式模拟。

程序分为以下几个部分:

  1. 初始化输入流。
  2. 分析代码。
  3. 划分语段。
  4. 运行代码。

主要需要实现的内容:

  1. 表达式求值。
  2. 代码运行部分。

分析代码的时候,运算符的匹配采用贪心的原则。右结合的 +- 操作可以记为 $+$- 以进行区分。

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;
}