////////////////////////////////////////////////////////////////////////// private ScriptScope ParseEventHandler(ref List<ScriptToken>.Enumerator TokenEnum) { ScriptToken Token = TokenEnum.Current; if (Token == null) return null; // setup handler ScriptEventHandler Handler = new ScriptEventHandler(); Handler.Signature = Token.Value + " "; Handler.Line = Token.OrigLine; Handler.Filename = Token.Filename; // setup scope ScriptScope Scope = new ScriptScope(); Scope.Owner = Handler; Scope.StartLine = Token.StartLine; Scope.StartCol = Token.StartCol; while (TokenEnum.MoveNext()) { Token = TokenEnum.Current; if (Token.IsComment) continue; if (Token.IsString) { Handler.Signature += Token.Value; Handler.Name = Token.Value.Trim(new char[] { '\"' }); break; } else return null; } EventHandlers.Add(Handler); return Scope; }
////////////////////////////////////////////////////////////////////////// private ScriptScope ParseFunction(ref List<ScriptToken>.Enumerator TokenEnum) { ScriptToken Token = TokenEnum.Current; if(Token==null) return null; // setup function ScriptFunction Func = new ScriptFunction(); Func.Signature = Token.Value + " "; Func.Line = Token.OrigLine; Func.Filename = Token.Filename; switch(Token.Value) { case "function": Func.Type = ScriptFunctionType.Function; break; case "method": Func.Type = ScriptFunctionType.Method; break; case "external": Func.Type = ScriptFunctionType.External; break; default: Func.Type = ScriptFunctionType.Unknown; break; } // setup scope ScriptScope Scope = new ScriptScope(); Scope.Owner = Func; Scope.StartLine = Token.StartLine; Scope.StartCol = Token.StartCol; bool ReadingName = true; bool ReadingParams = false; while (TokenEnum.MoveNext()) { Token = TokenEnum.Current; if (Token.IsComment) continue; if (ReadingName) { if (!Token.IsIdentifier) { if(Func.Type==ScriptFunctionType.External) { Func.Signature += Token.Value + " "; } else return null; } else { Func.Name = Token.Value; Func.Signature += Token.Value; ReadingName = false; } } else if(ReadingParams) { if (Token.IsOperator && Token.Value == ")") { Func.Signature += Token.Value; break; } else if(Token.IsOperator && Token.Value==",") { Func.Signature += Token.Value + " "; } else { ScriptVariable Var = ParseVariable(ref TokenEnum, true); if (Var == null) return null; else { Func.Signature += Var.Signature; Func.Params.Add(Var.Signature); if(Var.Name!="") Scope.Variables.Add(Var); // hack because of unnamed external's parameters Token = TokenEnum.Current; if(Token.IsOperator && Token.Value==")") { Func.Signature += Token.Value; break; } } } } else { if (Token.IsOperator && Token.Value == "(") { ReadingParams = true; Func.Signature += Token.Value; } else return null; } } Functions.Add(Func); return Scope; }
////////////////////////////////////////////////////////////////////////// private bool Parse() { // cleanup GlobalScope = new ScriptScope(); Scopes = new List<ScriptScope>(); Functions = new List<ScriptFunction>(); EventHandlers = new List<ScriptEventHandler>(); _Tokenizer = new ScriptTokenizer(Reader); if (!_Tokenizer.GetTokens()) return false; ScriptScope CurrentScope = GlobalScope; bool ReadingBlock = false; int BlockNest = 0; List<ScriptToken>.Enumerator TokenEnum = _Tokenizer.Tokens.GetEnumerator(); while(TokenEnum.MoveNext()) { ScriptToken Token = TokenEnum.Current; if (Token.IsComment) continue; // functions if (Token.IsKeyword && (Token.Value == "function" || Token.Value == "method" || Token.Value == "external")) { ScriptScope Scope = ParseFunction(ref TokenEnum); if(Scope != null) { if(ReadingBlock) { CurrentScope.EndLine = Token.StartLine; CurrentScope.EndCol = Token.StartCol; } CurrentScope = Scope; Scopes.Add(Scope); ReadingBlock = true; BlockNest = 0; } } // event handles else if(Token.IsKeyword && Token.Value=="on") { ScriptScope Scope = ParseEventHandler(ref TokenEnum); if (Scope != null) { if (ReadingBlock) { CurrentScope.EndLine = Token.StartLine; CurrentScope.EndCol = Token.StartCol; } CurrentScope = Scope; Scopes.Add(Scope); ReadingBlock = true; BlockNest = 0; } } // variables else if(Token.IsKeyword && (Token.Value=="var" || Token.Value=="global" || Token.Value=="const")) { ScriptVariable Var = ParseVariable(ref TokenEnum, false); if(Var!=null && Var.Name!="") { if(ReadingBlock && BlockNest>0) CurrentScope.Variables.Add(Var); else GlobalScope.Variables.Add(Var); } } // curly braces else if(Token.IsOperator) { if (Token.Value == "{" && ReadingBlock) BlockNest++; else if(Token.Value=="}" && ReadingBlock) { BlockNest--; if (BlockNest <= 0) { ReadingBlock = false; CurrentScope.EndLine = Token.EndLine; CurrentScope.EndCol = Token.EndCol; } } else if(Token.Value==";" && ReadingBlock && BlockNest==0) { ReadingBlock = false; CurrentScope.EndLine = Token.EndLine; CurrentScope.EndCol = Token.EndCol; } } } return true; }