关于大模拟
#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,真是淦