#include "StdAFX.h" #include "Script.h" #include "GMud32VW.h" #include "World.h" #define SCRIPT_START_STRING "<SCRIPT>" enum FUNC_IDS{F_NULL=0,F_IF,F_TESTEQUAL,F_SETEQUAL}; enum tokentypes{invalid=0,beginscope=1,endscope=2, function, uservariable}; struct token_struct{ LPCSTR szToken; int iTokenID; } g_Functions[]= { {"NULL",F_NULL}, {"if",F_IF}, {"==",F_TESTEQUAL}, {"=",F_SETEQUAL}, {"NULL",F_NULL}, }; void DescendScope(LPCSTR szScript,int &iCharIndex); CString GetNextStatement(LPCSTR szScript,int &iCharIndex); bool FindFunction(CString sStatement,CString &sFunction,CString &sArguments); CString GetNextToken(CString &sInput); tokentypes GetTokenType(CString sToken); void SkipScope(LPCSTR szScript,int &iCharIndex); bool DoIf(CString sStatement); int GetFuncID(CString sFunc); CString GetStringValue(CString sStatement); CMapStringToString *g_pUserVariables; CMudView *g_pView; CWorld *g_pWorld; void RunScript(CString sScript,CMudView &rView,CWorld &rWorld) { sScript.TrimLeft(); if(strnicmp(SCRIPT_START_STRING,sScript,lstrlen(SCRIPT_START_STRING))!=0) { rView.OnUserInput(0,(long)(LPCSTR)sScript); return; } try { g_pUserVariables = rWorld.GetUserVariables(); g_pView = &rView; g_pWorld = &rWorld; sScript=sScript.Mid(lstrlen(SCRIPT_START_STRING)); sScript.TrimLeft(); sScript.TrimRight(); int iIndex= 0; TRACE("\n%%%%%% Started Parsing...\n"); DescendScope(sScript,iIndex); TRACE("%%%%%% Completed Parsing.\n"); } catch(CString sError) { TRACE("%%%%%% Error parsing script, error follows\n"); TRACE("%s\n",(LPCSTR)sError); TRACE("%%%%%% End of Errors\n"); } return; } void DescendScope(LPCSTR szScript,int &iCharIndex) { TRACE("%%%%%% Descending\n"); do { CString sStatement=GetNextStatement(szScript,iCharIndex); TRACE("%%%%%% Parsing %s\n",(LPCSTR)sStatement); if(sStatement == '{') DescendScope(szScript,iCharIndex); else if(sStatement == '}') break; else { CString sToken=GetNextToken(sStatement); tokentypes type = GetTokenType(sToken); if(type == uservariable) // assignment { CString sOp = GetNextToken(sStatement); int iOpType = GetTokenType(sOp); if(iOpType!=function) throw "function expected! (assignment )"; int iOp = GetFuncID(sOp); if(iOp == F_SETEQUAL) { CString sValue = GetStringValue(sStatement); g_pUserVariables->SetAt(sToken,sValue); } else throw "assignment expected!"; } else if(type == function) { int function = GetFuncID(sToken); switch(function) { case F_IF: if(DoIf(sStatement)== false) { SkipScope(szScript,iCharIndex); } break; default: case F_NULL: CString s; s.Format("%%%%%% During script, error no function: %s\n",sToken); throw s; } } else { CString s; s.Format("%%%%%% During script, Dont know how to handle: %s\n",sToken); throw s; } } }while(szScript[iCharIndex]); TRACE("%%%%%% Ascending\n"); return; } CString GetNextToken(CString &sInput) { const char *token_delims=" <+>=(){},.[]|*&^%$#@!~"; for(int loop=0;loop<sInput.GetLength();loop++) { char ch=sInput[loop]; if(strchr(token_delims,ch)) { if(loop==0) loop++; CString sRet = sInput.Left(loop); sInput=sInput.Mid(loop); return sRet; } } return ""; } /* bool FindFunction(CString sStatement,CString &Function,CString &sArguments) { sStatement.TrimLeft(); for(int loop=0;loop<sStatement.GetLength();loop++) { if(sStatement[loop]=='(') return false; //[*] } return false; } */ const char *szStatementEnders=";{}"; CString GetNextStatement(LPCSTR szScript,int &iCharIndex) { while(isspace(szScript[iCharIndex])) iCharIndex++; int iStart = iCharIndex; CString sStatement; while( szScript[iCharIndex] && !strchr(szStatementEnders,szScript[iCharIndex])) { sStatement+=szScript[iCharIndex]; iCharIndex++; } if(!szScript[iCharIndex]) throw CString("Error: EOF Found, expected \';\'"); if(!sStatement.GetLength()) { sStatement=szScript[iCharIndex]; iCharIndex++; } else if(szScript[iCharIndex] != '{') iCharIndex++; sStatement.TrimRight(); return sStatement; } int GetFuncID(CString sFunc) { if(sFunc.IsEmpty()) return F_NULL; token_struct *pToken=NULL; int iIndex=1; while(1) { pToken=&g_Functions[iIndex]; if(pToken->iTokenID==F_NULL) break; if(sFunc.CompareNoCase(pToken->szToken)==0) return pToken->iTokenID; iIndex++; } return F_NULL; } tokentypes GetTokenType(CString sToken) { if(GetFuncID(sToken)!=F_NULL) return function; CString sDummy; if(g_pUserVariables->Lookup(sToken,sDummy)) return uservariable; return uservariable; } void SkipScope(LPCSTR szScript,int &iCharIndex) { int iBrackets=0; // skip leading space; while(szScript[iCharIndex] && isspace(szScript[iCharIndex])) iCharIndex++; if(szScript[iCharIndex]!='{') // single line if { while(szScript[iCharIndex] && szScript[iCharIndex]!=';') iCharIndex++; } else // bracketed if { for(iCharIndex;szScript[iCharIndex]!=NULL;iCharIndex++) { if(szScript[iCharIndex]=='{') iBrackets++; else if (szScript[iCharIndex] == '}') iBrackets--; } } } bool DoIf(CString sStatement) { TRACE("Entering DoIf with statemend of %s\n",(LPCSTR)sStatement); if(sStatement[0]!='(') throw "expected '('"; if(sStatement[sStatement.GetLength()-1]!=')') throw "expected ')'"; sStatement=sStatement.Mid(1,sStatement.GetLength()-2); sStatement.TrimLeft(); sStatement.TrimRight(); if(GetNextToken(sStatement)=="") // testing for existance of var. { CString sDummy; if(g_pUserVariables->Lookup(sStatement,sDummy)) return true; else return false; } return false; } CString GetStringValue(CString sStatement) { sStatement.TrimLeft(); CString sRet; bool bInQuote=false; for(int loop=0;loop<sStatement.GetLength();loop++) { if(sStatement[loop] == 34) //'/"') { if(bInQuote) break; else bInQuote=true; } else sRet+=sStatement[loop]; } return sRet; }