////////////////////////////////////////////////////////////////////////// public int GetTokenIndexAt(int Line, int Col) { for (int i = 0; i < Tokens.Count; i++) { ScriptToken Token = Tokens[i]; if ((Token.StartLine < Line || (Token.StartLine == Line && Token.StartCol <= Col)) && (Token.EndLine > Line || (Token.EndLine == Line && Token.EndCol >= Col))) { return(i); } } return(-1); }
////////////////////////////////////////////////////////////////////////// public ScriptToken GetPrevToken(ScriptToken Token) { if (Token == null) { return(null); } int Index = Tokens.IndexOf(Token) - 1; if (Index < 0) { return(null); } else { return(Tokens[Index]); } }
////////////////////////////////////////////////////////////////////////// public ScriptToken GetNearestTokenAt(int Line, int Col) { ScriptToken PrevToken = null; foreach (ScriptToken Token in Tokens) { if (PrevToken != null) { if ((Token.StartLine > Line || (Token.StartLine == Line && Token.StartCol > Col))) { return(PrevToken); } } PrevToken = Token; } return(PrevToken); }
////////////////////////////////////////////////////////////////////////// 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); }
////////////////////////////////////////////////////////////////////////// public int GetNearestLeftTokenIndexAt(int Line, int Col) { int PrevTokenIndex = -1; for (int i = 0; i < Tokens.Count; i++) { ScriptToken Token = Tokens[i]; if (PrevTokenIndex >= 0) { if ((Token.StartLine > Line || (Token.StartLine == Line && Token.StartCol >= Col))) { return(PrevTokenIndex); } } PrevTokenIndex = i; } return(PrevTokenIndex); }
////////////////////////////////////////////////////////////////////////// private void StoreToken(string TokenStr, ScriptToken.TokenType Type, int StartLine, int StartCol, int EndLine, int EndCol) { if (TokenStr == "") { return; } if (Type == ScriptToken.TokenType.Unknown) { if (IsKeyword(TokenStr)) { Type = ScriptToken.TokenType.Keyword; } else if (IsOperator(TokenStr)) { Type = ScriptToken.TokenType.Operator; } else if (char.IsNumber(TokenStr[0])) { Type = ScriptToken.TokenType.Number; } else { Type = ScriptToken.TokenType.Identifier; } } ScriptToken Token = new ScriptToken(TokenStr, Type, Filename, StartLine, StartCol, EndLine, EndCol); Tokens.Add(Token); // handle #includes if (Type == ScriptToken.TokenType.String && Tokens.Count > 1) { ScriptToken PrevToken = Tokens[Tokens.Count - 2]; if (PrevToken.Type == ScriptToken.TokenType.Identifier && PrevToken.Value == "#include") { String IncPath = FileManager.GetFullPath(Token.Value.Trim(new char[] { '\"' })); if (IncPath != null) { ReadInclude(IncPath); } } } }
////////////////////////////////////////////////////////////////////////// public ScriptToken GetNextToken(ScriptToken Token) { if (Token == null) { return(null); } int Index = Tokens.IndexOf(Token); if (Index < 0) { return(null); } Index++; if (Index < Tokens.Count) { return(Tokens[Index]); } else { return(null); } }
////////////////////////////////////////////////////////////////////////// private void StoreToken(string TokenStr, ScriptToken.TokenType Type, int StartLine, int StartCol, int EndLine, int EndCol) { if (TokenStr == "") return; if(Type==ScriptToken.TokenType.Unknown) { if (IsKeyword(TokenStr)) Type = ScriptToken.TokenType.Keyword; else if (IsOperator(TokenStr)) Type = ScriptToken.TokenType.Operator; else if (char.IsNumber(TokenStr[0])) Type = ScriptToken.TokenType.Number; else Type = ScriptToken.TokenType.Identifier; } ScriptToken Token = new ScriptToken(TokenStr, Type, Filename, StartLine, StartCol, EndLine, EndCol); Tokens.Add(Token); // handle #includes if(Type==ScriptToken.TokenType.String && Tokens.Count > 1) { ScriptToken PrevToken = Tokens[Tokens.Count - 2]; if(PrevToken.Type==ScriptToken.TokenType.Identifier && PrevToken.Value=="#include") { String IncPath = FileManager.GetFullPath(Token.Value.Trim(new char[] { '\"' })); if (IncPath != null) ReadInclude(IncPath); } } }
////////////////////////////////////////////////////////////////////////// public ScriptToken GetPrevToken(ScriptToken Token) { if (Token == null) return null; int Index = Tokens.IndexOf(Token) - 1; if (Index < 0) return null; else return Tokens[Index]; }
////////////////////////////////////////////////////////////////////////// public ScriptToken GetNextToken(ScriptToken Token) { if (Token == null) return null; int Index = Tokens.IndexOf(Token); if (Index < 0) return null; Index++; if (Index < Tokens.Count) return Tokens[Index]; else return null; }
////////////////////////////////////////////////////////////////////////// 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); }
////////////////////////////////////////////////////////////////////////// private ScriptVariable ParseVariable(ref List <ScriptToken> .Enumerator TokenEnum, bool Param) { ScriptToken Token = TokenEnum.Current; if (Token == null) { return(null); } ScriptVariable Var = new ScriptVariable(); Var.Line = Token.OrigLine; Var.Filename = Token.Filename; if (Param) { Var.Type = ScriptVariableType.Parameter; } else { switch (Token.Value) { case "var": Var.Type = ScriptVariableType.Var; break; case "global": Var.Type = ScriptVariableType.Global; break; case "const": Var.Type = ScriptVariableType.Const; break; default: Var.Type = ScriptVariableType.Unknown; break; } } while (true) { if (!Token.IsComment) { if (Token.IsIdentifier) { if (Var.Name == "") { Var.Name = Token.Value; } Var.Signature += Token.Value + " "; if (Param) { break; } } else if (Token.IsOperator && (Token.Value == ";" || Token.Value == ",")) { break; } else if (Token.IsOperator && Param && Token.Value == ")") { break; } else { Var.Signature += Token.Value + " "; } } if (!TokenEnum.MoveNext()) { return(null); } Token = TokenEnum.Current; } Var.Signature = Var.Signature.Trim(); if (Var.Signature != "") { Var.ValidAfterLine = Token.EndLine; Var.ValidAfterCol = Token.EndCol; return(Var); } else { return(null); } }
////////////////////////////////////////////////////////////////////////// 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); }