rt
已经处理了行末\r,思路是以行为单位执行,预处理每个IF与END IF的位置,在每个IF内单独处理,对于IF与ELSE里都定义变量或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
*/