90 pts 求条
查看原帖
90 pts 求条
1095979
HSC307楼主2024/12/5 17:40

rt

评测记录

已经处理了行末\r,思路是以行为单位执行,预处理每个IFEND IF的位置,在每个IF内单独处理,对于IFELSE里都定义变量或RETURN的情况就向上传回去

代码如下

#include<bits/stdc++.h>
#define Flandre std
using namespace Flandre;
typedef long long ll;
bitset<26> WARNING1[55];
bitset<55> WARNING2;

inline vector<string> split(const string &org){
    vector<string> res;
    string tmp = "";
    for(int i=0;i<org.length();++i){
        if(org[i]==' '||org[i]=='\r'){
            if(!tmp.empty())res.push_back(tmp);
            tmp = "";
        }else tmp+=org[i];
    }if(!tmp.empty())res.push_back(tmp);
    return res;
}

inline bool startWith(const string &org,const string &pre){
    if(org.length()<pre.length())
        return 0;
    for(int i=0;i<pre.length();++i){
        if(pre[i]==org[i])continue;
        if(pre[i]==org[i]-'a'+'A')continue;
        if(pre[i]==org[i]-'A'+'a')continue;
        return 0;
    }return 1;
}

inline bool isNum(const string &org){
    for(auto chr:org)
        if((!('0'<=chr&&chr<='9'))&&(chr!='-'))return 0;
    return 1;
}
inline bool isOper(const string &org){
    for(auto chr:org){
        if(chr=='=')continue;
        if(chr=='>')continue;
        if(chr=='<')continue;
        if(chr=='+')continue;
        if(chr=='-')continue;
        if(chr=='*')continue;
        if(chr=='/')continue;
        return 0;
    }return 1;
}
inline bool isEmpty(const string &org){
    for(auto chr:org){
        if(chr==' ')continue;
        if(chr=='\r')continue;
        if(chr=='\n')continue;
        return 0;
    }return 1;
}

int N;
vector<string> codes[55];
inline void initVari(bitset<26> &varis,const int &line){
    for(int i=1;i<codes[line].size();i++){
        if(isOper(codes[line][i]))continue;
        if(isNum(codes[line][i]))continue;
        if(isEmpty(codes[line][i]))continue;
        if('A'<=codes[line][i][0]&&codes[line][i][0]<='Z')
            if(!varis[codes[line][i][0]-'A'])
                WARNING1[line].set(codes[line][i][0]-'A');
    }
    if(codes[line][0].size()==1)
        if('A'<=codes[line][0][0]&&codes[line][0][0]<='Z')
            varis.set(codes[line][0][0]-'A');
}

unordered_map<int,int> ENDIF;
int stacIF[495],top=-1;
bitset<26> globalVari;
inline void preIF(){
    for(int LINE=2;LINE<=N;LINE++){
        if(startWith(codes[LINE][0],"IF"))
            stacIF[++top]=LINE;
        if(startWith(codes[LINE][0],"END"))
            if(top>-1)
                ENDIF[stacIF[top]]=LINE,top--;
    }
}

bool globalUnreachable = 0;
inline void runIF(const int &IF,const int &END,bitset<26> &upVari,bool &upUnreachable){
    if(upUnreachable)return;
    bitset<26> ifVari = upVari;
    bitset<26> elseVari = upVari;
    bitset<26> *localVari = &ifVari;
    for(int i=0;i<codes[IF].size();i++){
        if(startWith(codes[IF][i],"THEN"))break;
        if(startWith(codes[IF][i],"IF"))continue;
        if(isOper(codes[IF][i]))continue;
        if(isNum(codes[IF][i]))continue;
        if(isEmpty(codes[IF][i]))continue;
        if('A'<=codes[IF][i][0]&&codes[IF][i][0]<='Z')
            if(codes[IF][i].size()==1)
                if(!upVari[codes[IF][i][0]-'A'])
                    WARNING1[IF].set(codes[IF][i][0]-'A');
    }
    bool unreachable = 0;
    bool retInElse = 0;
    bool retInIf = 0;
    bool inElse = 0;
    for(int LINE=IF+1;LINE<END;LINE++){
        if(startWith(codes[LINE][0],"END"))
            continue;
        if(startWith(codes[LINE][0],"ELSE")){
            unreachable = 0;
            inElse = 1;
            localVari = &elseVari;
            continue;
        }
        if(unreachable){
            WARNING2.set(LINE);
            continue;
        }
        if(startWith(codes[LINE][0],"IF")){
            if(!unreachable){
                runIF(LINE,ENDIF[LINE],*localVari,unreachable);
                if(unreachable&&(!inElse))
                    retInIf = 1;
                if(unreachable&&inElse)
                    retInElse = 1;  
                LINE = ENDIF[LINE];
                continue;
            }
        } 
        if(startWith(codes[LINE][0],"RETURN")){
            for(int j=1;j<codes[LINE].size();j++){
            if(codes[LINE][j].size()==1)
                if('A'<=codes[LINE][j][0]&&codes[LINE][j][0]<='Z')
                    if(!(*localVari)[codes[LINE][j][0]-'A'])
                        WARNING1[LINE].set(codes[LINE][j][0]-'A');
            }
            unreachable = 1;
            if(inElse)
                retInElse = 1;
            else 
                retInIf = 1;
            continue;
        }
        initVari((*localVari),LINE);
    }
    if(retInIf&&retInElse)upUnreachable = 1;
    for(int i=0;i<26;i++)
        if((ifVari[i]||retInIf)&&(elseVari[i]||retInElse))
            upVari.set(i);
}


inline void param(vector<string> &code){
    for(int i=0;i<code.size();i++)
        if(code[i].size()==1)
            if('A'<=code[i][0]&&code[i][0]<='Z')
                globalVari.set(code[i][0]-'A');
}



inline void compile(){
    param(codes[1]);
    preIF();
    for(int LINE=2;LINE<=N;LINE++){
        if(startWith(codes[LINE][0],"END"))
            continue;
        if(startWith(codes[LINE][0],"ELSE"))
            continue;
        if(globalUnreachable){
            WARNING2.set(LINE);
            continue;
        }
        if(startWith(codes[LINE][0],"IF")){
            // exit(9961);
            if(!globalUnreachable){
                runIF(LINE,ENDIF[LINE],globalVari,globalUnreachable);
                LINE = ENDIF[LINE];
                continue;
            }  
        }
        if(startWith(codes[LINE][0],"RETURN")){
            for(int j=1;j<codes[LINE].size();j++){
                if('A'<=codes[LINE][j][0]&&codes[LINE][j][0]<='Z')
                    if(!globalVari[codes[LINE][j][0]-'A'])
                        WARNING1[LINE].set(codes[LINE][j][0]-'A');
            }
            globalUnreachable = 1;
            continue;
        }
        initVari(globalVari,LINE);
    }
}
inline void warning(){
    for(int LINE=1;LINE<=N;LINE++){
        if(startWith(codes[LINE][0],"PARAM"))
            continue;
        if(startWith(codes[LINE][0],"END"))
            continue;
        if(startWith(codes[LINE][0],"ELSE"))
            continue;
        if(WARNING2[LINE]){
            cout<<"Line "<<LINE<<": unreachable code\n";
            continue;
        }
        for(int i=0;i<26;i++)
            if(WARNING1[LINE][i])
                cout<<"Line "<<LINE<<": variable "<<(char)(i+'A')<<" might not have been initialized\n";
    }
}

string input;
int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    while(getline(cin,input))codes[++N] = split(input);
    compile();
    warning();
    return 0;
}
/*
2024/11/29 19:48
2024/11/30 6:52
PARAM A
IF A = 3 THEN
RETURN 3
ELSE
RETURN 4
END IF
RETURN C

output:
    Line 7: unreachable code

PARAM A B
IF A > 5 THEN
IF C > 9 THEN
C = A + B
END IF
C = B * A
END IF
D = B - C
Z = Y + X
E = T
F = E + E
V = G + G
RETURN F
*/
2024/12/5 17:40
加载中...