关于大模拟

#include<bits/stdc++.h>
#warning Tab and SPace !!!
using namespace std;
const int N = 500+10, V = 50 + 5, L = 1000 + 10;
enum{C_root, C_prevar, C_set, C_print, C_if, C_for, C_while, C_innerprevar};
enum{V_arr, V_var};
enum{L_lt, L_gt, L_le, L_ge, L_eq, L_neq};
enum{E_lo, E_nu};
using Tp = int;
struct Error_s{
	void throwit(string x){
		cerr<< x << endl;
		abort();
	}
}Error;
string trim(const string& str){
	int p1 = str.find_first_not_of(' ');
	int p2 = str.find_last_not_of(' ');
	return str.substr(p1, p2 - p1 + 1);
}
vector<string> split(string str, char ch = ' '){
	vector<string> ret;
	int lst = 0;
	while(lst <= str.length()){
		int nxt = str.find_first_of(ch, lst);
		if(nxt == -1) break;
		ret.push_back(str.substr(lst, nxt - lst));
		lst = nxt + 1;
	}
	if(lst != str.length()) ret.push_back(str.substr(lst));
	return ret;
}
template<typename Tp>
vector<string> split(string str, Tp chk){
	vector<string> ret;
	int lst = 0;
	for(int i = 0; i < str.length(); ++i){
		if(!chk(str[i])){
			if(lst != i)ret.push_back(str.substr(lst, i - lst));
			ret.push_back(str.substr(i, 1));
			lst = i + 1;
		}
	}
	if(lst != str.length()) ret.push_back(str.substr(lst));
	return ret;
}
struct VaribleBase{
	typedef pair<int, int> pii;
	struct ArrBase{
		Tp data[V];
		int l, r;
		void init(int l_, int r_){
			l = l_, r = r_;
		}
		Tp& Val(int x){
			if(x < l){
				Error.throwit("VariableBase :: ArrBase :: Val() : Invaild Array Place.");
			}
			return data[x - l];
		}
	}ArrBasePool[V];
	struct VarBase{
		Tp val;
		void init(){
			;
		}
		Tp& Val(){
			return val;
		}
	}VarBasePool[V];
	int arrcnt, varcnt;
	unordered_map<string, pii> mp;
	void init(int opt, string x, int l = -1, int r = -1){
		if(opt == V_arr) {
			++arrcnt;
			mp[x] = {opt, arrcnt};
			ArrBasePool[arrcnt].init(l, r);
		}else if(opt == V_var){
			++varcnt;
			mp[x] = {opt, varcnt};
			VarBasePool[varcnt].init();
		}
	}
	Tp& Val(string s, int x = -1){
		if(mp[s].second ==0){
			Error.throwit("VaribleBase::Val() : Variable is not defined.");
		}	
		if(mp[s].first == V_arr){
			return ArrBasePool[mp[s].second].Val(x);
		}else if(mp[s].first == V_var){
			return VarBasePool[mp[s].second].Val();
		}
		abort();
	}
}VariablePool;
bool GeneralLegalCheck(char ch){
	return islower(ch) || isupper(ch) ||isdigit(ch) ||  ch == '[' || ch == ']';
}
bool isNumber(string s){
	for(auto ch : s){
		if(!isdigit(ch)) return false;
	}
	return true;
}
bool isLegal(string s){
	for(auto ch : s){
		if(!GeneralLegalCheck(ch)) return false;
	}
	return true;
}
template<typename T>
bool isLegal(string s, T check){
	for(auto ch : s){
		if(!check(ch)) return false;
	}
	return true;
}
struct ExpressionBase{
	static Tp& ValRef(string s){
		int p1 = s.find_first_of('[');
		int p2 = s.find_first_of(']');		
		if(p1 == -1) return VariablePool.Val(s);
		return VariablePool.Val(s.substr(0, p1), Val(s.substr(p1 + 1, p2 - p1 - 1)));
	}
	static Tp Val(string s){
		if(!isLegal(s)) {
			Error.throwit(string("Expression :: Val(string) : Variable is not legal"));
		}
		if(isNumber(s)) return stoi(s);
		return ValRef(s);
	}
	static int Numeric(string arg){
		auto ret = split(arg, GeneralLegalCheck);
		int op = 1;
		int rval = 0;
		for(string x : ret){
			if(!isLegal(x)){
				if(x[0] == '+') op = 1;
				else if(x[0] == '-') op = -1;
			}else {
				rval += op * Val(x);
			}
		}
		return rval;
	}
	static int LogicalTrans(string comp){
		if(comp == "neq"){
			return L_neq;
		}else if(comp == "eq"){
			return L_eq;
		}else if(comp == "gt"){
			return L_gt;
		}else if(comp == "lt"){
			return L_lt;
		}else if(comp == "ge"){
			return L_ge;
		}else if(comp == "le"){
			return L_le;
		}else{
			Error.throwit(string("ExpressionBase :: LogicalTrans(string) : Invaild Logical Operator."));
		}
		abort();
	}
	static bool Compare(string arg1, string arg2, string comp){
		int opt = LogicalTrans(comp);
		int v1 = Numeric(arg1), v2 = Numeric(arg2);
		switch(opt){
			case L_neq: return v1 != v2;
			case L_eq : return v1 == v2;
			case L_gt : return v1 > v2;
			case L_lt : return v1 < v2;
			case L_ge : return v1 >= v2;
			case L_le : return v1 <= v2;
		}
		Error.throwit(string("Invaild Compare"));
		abort();
	}
	static bool Logical(string arg){
		auto chk = [&](char ch){return GeneralLegalCheck(ch) || ch == '+' || ch == '-' || ch == ' ';};
		auto ret = split(arg, chk);
		string args[5];
		int cnt = 0;
		for(auto x : ret){
			assert(cnt <= 3);
			if(isLegal(x, chk)){
				args[++cnt] = trim(x);
			}
		}
		return Compare(args[2], args[3], args[1]);
	}
	static int GetExpressionType(string s){
		if(s.find(',') != -1) return E_lo;
		else return E_nu;
	}
	static int Calc(string arg){
		if(GetExpressionType(arg) == E_nu) return Numeric(arg);
		return Logical(arg);
	}
};
struct Command{
	int opt;
	string arg;
	void Run(){
		if(opt == C_print){
			cout << ExpressionBase::Calc(arg) << " ";
		}else if(opt == C_set){
			auto chk = [&](char ch){return GeneralLegalCheck(ch) || ch == '+' || ch == '-' || ch == ' ';};
			auto ret = split(arg, chk);
			int cnt = 0;
			string args[5];
			for(string x : ret){
				if(isLegal(x, chk)){
					++cnt;
					args[cnt] = trim(x);
				}
			}
			ExpressionBase::ValRef(args[1]) = ExpressionBase::Calc(args[2]);
		}
	}
};
void putspc(int x){
	for(int i = 1; i <= x; ++i) cerr<<"*";
}
struct CommandBlock{
	int opt;
	string exp;
	vector<CommandBlock> coms;
	string arg;
	string argext;
	void init(){
		if(opt == C_for){
			auto ret = split(arg, ',');
			assert(ret.size() == 3);
			for(int i = 0; i < 3; ++i) ret[i] = trim(ret[i]);
			exp = "le, " + ret[0] + ", " + ret[2];
			arg = ret[0] + ", " + ret[1];
			argext = ret[0] + "," + ret[0] + "+1";
		}
	}
	static string opt_to_string(int opt){
		if(opt == C_for){
			return "for";
		}else if(opt == C_if){
			return "if";
		}else if(opt == C_while){
			return "while";
		}else if(opt == C_root){
			return "root";
		}else if(opt == C_set){
			return "set";
		}else if(opt == C_print){
			return "print";
		}else if(opt ==C_innerprevar){
			return "innnerprevar";
		}else if(opt == C_prevar){
			return "prevar";
		}
		return "Unknown Function";
	}
	void debug(int x){
		putspc(x); cerr<<  opt_to_string(opt) << " : "<<exp <<" : " <<arg << endl;
		for(auto y : coms){
			y.debug(x + 1);
		}
	}
	void Run(){
		if(opt == C_root){
			for(auto x : coms){
				x.Run();
			}
		}else if(opt == C_prevar){
			for(auto x : coms){
				x.Run();
			}
		}else if(opt == C_print){
			Command tmp = {C_print, arg};
			tmp.Run();
		}else if(opt == C_innerprevar){
			int p = arg.find("array");
			if(p == -1){
				p = arg.find(":");
				VariablePool.init(V_var, arg.substr(0, p - 1 - 0 + 1));
			}else{
				p = arg.find("..");
				int k = arg.find(",");
				auto lstr = arg.substr(k + 1, p - 1 - (k + 1) + 1), rstr = arg.substr(p + 2, arg.length() - 1 - (p + 2));
				lstr = trim(lstr), rstr = trim(rstr);
				int l =	ExpressionBase::Val(lstr);
				int r = ExpressionBase::Val(rstr);
				p = arg.find(":");
				VariablePool.init(V_arr, arg.substr(0, p - 1 - 0 + 1), l, r);
			}
		}else if(opt == C_set){
			Command tmp = {C_set, arg};
			tmp.Run();
		}else if(opt == C_if){
			if(ExpressionBase::Calc(exp)){
				for(auto x : coms){
					x.Run();
				}
			}
		}else if(opt == C_while){
			while(ExpressionBase::Calc(exp)){
				for(auto x : coms){
					x.Run();
				}
			}
		}else if(opt == C_for){
			Command tmp = {C_set, arg};
			tmp.Run();
			while(ExpressionBase::Calc(exp)){
				for(auto x : coms){
					x.Run();
				}
				tmp = {C_set, argext};
				tmp.Run();
			}
		}else{
			Error.throwit("CommandBlock:: Run() : Invaild Command type.");
		}
	}
}root;
string inp[N];
int n;
void input(){
	while(!cin.eof()) ++n, getline(cin, inp[n]);
}
pair<CommandBlock,int> analyze(int p, bool ignore){
	CommandBlock cur;
	for(int i = p; i <= n; ++i){
		if(inp[i].find('{') != -1){
			if(ignore) {
				if(inp[i].find("while") != -1){
					int p = inp[i].find("while");
					cur.opt = C_while;
					cur.exp = inp[i].substr(p + 5);
					cur.init();
				}
				else if(inp[i].find("vars") != -1) cur.opt = C_prevar;
				else if(inp[i].find("hor") != -1){
					int p = inp[i].find("hor");
					cur.opt = C_for;
					cur.arg = inp[i].substr(p + 3);
					cur.init();
				}else if(inp[i].find("ihu") != -1){
					int p = inp[i].find("ihu");
					cur.opt = C_if;
					cur.exp = inp[i].substr(p + 3);
				}
				ignore = false;
			}
			else{
				auto ret = analyze(i, true);
				cur.coms.push_back(ret.first);
				i = ret.second;
			}
		}else if(inp[i].find("set") != -1){
			int p = inp[i].find("set");
			CommandBlock tmp;
			tmp.opt = C_set;
			tmp.arg = trim(inp[i].substr(p + 3));
			cur.coms.push_back(tmp);
		}else if(inp[i].find("yosoro") != -1){
			int p = inp[i].find("yosoro");
			CommandBlock tmp;
			tmp.opt = C_print;
			tmp.arg = trim(inp[i].substr(p + 6));
			cur.coms.push_back(tmp);
		}
		else if(inp[i].find('}') != -1) return {cur, i};
		else if(inp[i].find("int") != -1){
			CommandBlock tmp;
			tmp.opt = C_innerprevar;
			tmp.arg = trim(inp[i]);
			cur.coms.push_back(tmp);
		}
	}
	return {cur, n};
}
int main(){
	input();
	CommandBlock root = analyze(1, false).first;
	root.opt = C_root;
	root.Run();
	return 0;
}

调试的时候有一个莫名奇妙的错误:我习惯性用TAB缩进,这个语言用空格,导致我处理空格的时候没有去掉TAB,所有变量名前面都挂着个空格,一调用就会
VaribleBase::Val() : Variable is not defined.
因为这个调了20min,真是淦

posted @ 2022-10-03 20:00  CDsidi  阅读(36)  评论(6编辑  收藏  举报