public IEnumerable<SnippetCompletion> EnumSnippets( SymbolDefinition context, FGGrammar.TokenSet expectedTokens, SyntaxToken tokenLeft, Scope scope) { if (scope == null) yield break; var bodyScope = scope as BodyScope ?? scope.parentScope as BodyScope; if (bodyScope == null) yield break; var contextType = bodyScope.definition as TypeDefinitionBase; if (contextType == null || contextType.kind != SymbolKind.Class && contextType.kind != SymbolKind.Struct) yield break; context = contextType; if (tokenLeft == null || tokenLeft.parent == null || tokenLeft.parent.parent == null) yield break; if (tokenLeft.tokenKind != SyntaxToken.Kind.Punctuator) yield break; if (tokenLeft.text != "{" && tokenLeft.text != "}" && tokenLeft.text != ";") yield break; for (var i = contextType.members.Count; i --> 0; ) { var member = contextType.members[i]; if (member.kind == SymbolKind.Field) { var type = member.TypeOf(); if (type == null || type.kind == SymbolKind.Error || !(type is TypeDefinitionBase)) continue; var fieldName = member.name; if (string.IsNullOrEmpty(fieldName) || fieldName[0] == '.') continue; fieldName = char.ToUpperInvariant(fieldName[0]) + fieldName.Substring(1); var propertyName = fieldName; for (var suffix = 1; contextType.members.Contains(propertyName, -1); ++suffix) propertyName = fieldName + suffix.ToString(); yield return new MyCompletion(propertyName, member, true);// "{0} {{ get {{...}} set {{...}} }}"); yield return new MyCompletion(propertyName, member, false);// "{0} {{ get {{...}} }}"); } } }
public IEnumerable<SnippetCompletion> EnumSnippets( SymbolDefinition context, FGGrammar.TokenSet expectedTokens, SyntaxToken tokenLeft, Scope scope) { OverrideMethod.context = scope; if (tokenLeft == null || tokenLeft.parent == null || tokenLeft.parent.parent == null) yield break; if (tokenLeft.tokenKind != SyntaxToken.Kind.Keyword) yield break; if (tokenLeft.text != "override") yield break; var bodyScope = scope as BodyScope; if (bodyScope == null) yield break; var contextType = bodyScope.definition as TypeDefinitionBase; if (contextType == null || contextType.kind != SymbolKind.Class && contextType.kind != SymbolKind.Struct) yield break; var baseType = contextType.BaseType(); if (baseType == null || baseType.kind != SymbolKind.Class && baseType.kind != SymbolKind.Struct) yield break; var overrideMethodCandidates = new List<MethodDefinition>(); baseType.ListOverrideCandidates(overrideMethodCandidates, contextType.Assembly); if (overrideMethodCandidates.Count == 0) yield break; var textBuffer = FGTextBuffer.activeEditor.TextBuffer; var firstToken = tokenLeft.parent.parent.GetFirstLeaf().token; if (firstToken.formatedLine != tokenLeft.formatedLine) { firstToken = tokenLeft.formatedLine.tokens[0]; while (firstToken.tokenKind <= SyntaxToken.Kind.LastWSToken) firstToken = firstToken.formatedLine.tokens[firstToken.TokenIndex + 1]; } var tokenSpan = textBuffer.GetTokenSpan(firstToken.parent); OverrideMethod.overrideTextLength = FGTextBuffer.activeEditor.caretPosition.characterIndex - tokenSpan.StartPosition.index; foreach (var method in overrideMethodCandidates) { var methodGroup = contextType.FindName(method.name, -1, false) as MethodGroupDefinition; if (methodGroup != null) { bool skipThis = false; var signature = method.PrintParameters(method.GetParameters(), true); foreach (var m in methodGroup.methods) { if (method.NumTypeParameters == m.NumTypeParameters && signature == m.PrintParameters(m.GetParameters())) { skipThis = true; break; } } if (skipThis) continue; } var overrideCompletion = new OverrideMethod(method); yield return overrideCompletion; } }
private new SyntaxToken ScanIdentifierOrKeyword(string line, ref int startAt) { bool identifier = false; int i = startAt; if (i >= line.Length) return null; char c = line[i]; if (!char.IsLetter(c) && c != '_') return null; ++i; while (i < line.Length) { if (char.IsLetterOrDigit(line, i) || line[i] == '_') ++i; else break; } var word = line.Substring(startAt, i - startAt); startAt = i; var token = new SyntaxToken(identifier ? SyntaxToken.Kind.Identifier : SyntaxToken.Kind.Keyword, word); if (token.tokenKind == SyntaxToken.Kind.Keyword && !IsKeyword(token.text) && !IsBuiltInType(token.text)) token.tokenKind = SyntaxToken.Kind.Identifier; return token; }
protected override void Tokenize(string line, FGTextBuffer.FormatedLine formatedLine) { var tokens = new List<SyntaxToken>(); formatedLine.tokens = tokens; int startAt = 0; int length = line.Length; SyntaxToken token; SyntaxToken ws = ScanWhitespace(line, ref startAt); if (ws != null) { tokens.Add(ws); ws.formatedLine = formatedLine; } var inactiveLine = formatedLine.regionTree.kind > FGTextBuffer.RegionTree.Kind.LastActive; while (startAt < length) { switch (formatedLine.blockState) { case FGTextBuffer.BlockState.None: ws = ScanWhitespace(line, ref startAt); if (ws != null) { tokens.Add(ws); ws.formatedLine = formatedLine; continue; } if (inactiveLine) { tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, line.Substring(startAt)) { formatedLine = formatedLine }); startAt = length; break; } if (line[startAt] == '#') { tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, "#") { formatedLine = formatedLine }); ++startAt; tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, line.Substring(startAt)) { formatedLine = formatedLine }); startAt = length; break; } if (line[startAt] == '/' && startAt < length - 1) { if (line[startAt + 1] == '/') { tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, "//") { formatedLine = formatedLine }); startAt += 2; tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, line.Substring(startAt)) { formatedLine = formatedLine }); startAt = length; break; } else if (line[startAt + 1] == '*') { tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, "/*") { formatedLine = formatedLine }); startAt += 2; formatedLine.blockState = FGTextBuffer.BlockState.CommentBlock; break; } } if (line[startAt] == '\'') { token = ScanCharLiteral(line, ref startAt); tokens.Add(token); token.formatedLine = formatedLine; break; } if (line[startAt] == '\"') { if (startAt < length - 2 && line[startAt + 1] == '\"' && line[startAt + 2] == '\"') { token = new SyntaxToken(SyntaxToken.Kind.VerbatimStringBegin, line.Substring(startAt, 3)) { formatedLine = formatedLine }; tokens.Add(token); startAt += 3; formatedLine.blockState = FGTextBuffer.BlockState.StringBlock; break; } token = ScanStringLiteral(line, ref startAt); tokens.Add(token); token.formatedLine = formatedLine; break; } if (line[startAt] >= '0' && line[startAt] <= '9' || startAt < length - 1 && line[startAt] == '.' && line[startAt + 1] >= '0' && line[startAt + 1] <= '9') { token = ScanNumericLiteral_JS(line, ref startAt); tokens.Add(token); token.formatedLine = formatedLine; break; } token = ScanIdentifierOrKeyword(line, ref startAt); if (token != null) { tokens.Add(token); token.formatedLine = formatedLine; break; } // Multi-character operators / punctuators // "++", "--", "<<", ">>", "<=", ">=", "==", "!=", "&&", "||", "??", "+=", "-=", "*=", "/=", "%=", // "&=", "|=", "^=", "<<=", ">>=", "=>", "::", "->", "^=" var punctuatorStart = startAt++; if (startAt < line.Length) { switch (line[punctuatorStart]) { case '?': if (line[startAt] == '?') ++startAt; break; case '+': if (line[startAt] == '+' || line[startAt] == '=' || line[startAt] == '>') ++startAt; break; case '-': if (line[startAt] == '-' || line[startAt] == '=') ++startAt; break; case '<': if (line[startAt] == '=') ++startAt; else if (line[startAt] == '<') { ++startAt; if (startAt < line.Length && line[startAt] == '=') ++startAt; } break; case '>': if (line[startAt] == '=') ++startAt; else if (startAt < line.Length && line[startAt] == '>') { ++startAt; if (line[startAt] == '=') ++startAt; } break; case '=': if (line[startAt] == '=' || line[startAt] == '>') ++startAt; break; case '&': if (line[startAt] == '=' || line[startAt] == '&') ++startAt; break; case '|': if (line[startAt] == '=' || line[startAt] == '|') ++startAt; break; case '*': case '/': case '%': case '^': case '!': if (line[startAt] == '=') ++startAt; break; case ':': if (line[startAt] == ':') ++startAt; break; } } tokens.Add(new SyntaxToken(SyntaxToken.Kind.Punctuator, line.Substring(punctuatorStart, startAt - punctuatorStart)) { formatedLine = formatedLine }); break; case FGTextBuffer.BlockState.CommentBlock: int commentBlockEnd = line.IndexOf("*/", startAt, StringComparison.Ordinal); if (commentBlockEnd == -1) { tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, line.Substring(startAt)) { formatedLine = formatedLine }); startAt = length; } else { tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, line.Substring(startAt, commentBlockEnd + 2 - startAt)) { formatedLine = formatedLine }); startAt = commentBlockEnd + 2; formatedLine.blockState = FGTextBuffer.BlockState.None; } break; case FGTextBuffer.BlockState.StringBlock: int i = startAt; int closingQuote = line.IndexOf('\"', startAt); while (closingQuote != -1 && closingQuote < length - 2 && (line[closingQuote + 1] != '\"' || line[closingQuote + 2] != '\"')) { i = closingQuote + 2; closingQuote = line.IndexOf('\"', i); } if (closingQuote == -1) { tokens.Add(new SyntaxToken(SyntaxToken.Kind.VerbatimStringLiteral, line.Substring(startAt)) { formatedLine = formatedLine }); startAt = length; } else { tokens.Add(new SyntaxToken(SyntaxToken.Kind.VerbatimStringLiteral, line.Substring(startAt, closingQuote - startAt)) { formatedLine = formatedLine }); startAt = closingQuote; tokens.Add(new SyntaxToken(SyntaxToken.Kind.VerbatimStringLiteral, line.Substring(startAt, 3)) { formatedLine = formatedLine }); startAt += 3; formatedLine.blockState = FGTextBuffer.BlockState.None; } break; } } }
protected static SyntaxToken ScanNumericLiteral_JS(string line, ref int startAt) { bool hex = false; bool point = false; bool exponent = false; var i = startAt; SyntaxToken token; char c; if (line[i] == '0' && i < line.Length - 1 && (line[i + 1] == 'x')) { i += 2; hex = true; while (i < line.Length) { c = line[i]; if (c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F') ++i; else break; } } else { while (i < line.Length && line[i] >= '0' && line[i] <= '9') ++i; } if (i > startAt && i < line.Length) { c = line[i]; if (c == 'l' || c == 'L') { ++i; token = new SyntaxToken(SyntaxToken.Kind.IntegerLiteral, line.Substring(startAt, i - startAt)); startAt = i; return token; } } if (hex) { token = new SyntaxToken(SyntaxToken.Kind.IntegerLiteral, line.Substring(startAt, i - startAt)); startAt = i; return token; } while (i < line.Length) { c = line[i]; if (!point && !exponent && c == '.') { if (i < line.Length - 1 && line[i+1] >= '0' && line[i+1] <= '9') { point = true; ++i; continue; } else { break; } } if (!exponent && i > startAt && (c == 'e' || c == 'E')) { exponent = true; ++i; if (i < line.Length && (line[i] == '-' || line[i] == '+')) ++i; continue; } if (c == 'f' || c == 'F' || c == 'd' || c == 'D') { point = true; ++i; break; } if (c < '0' || c > '9') break; ++i; } token = new SyntaxToken( point || exponent ? SyntaxToken.Kind.RealLiteral : SyntaxToken.Kind.IntegerLiteral, line.Substring(startAt, i - startAt)); startAt = i; return token; }
protected static SyntaxToken ScanStringLiteral(string line, ref int startAt) { var i = startAt + 1; while (i < line.Length) { if (line[i] == '\"') { ++i; break; } if (line[i] == '\\' && i < line.Length - 1) ++i; ++i; } var token = new SyntaxToken(SyntaxToken.Kind.StringLiteral, line.Substring(startAt, i - startAt)); startAt = i; return token; }
protected static SyntaxToken ScanWord(string line, ref int startAt) { int i = startAt; while (i < line.Length) { if (!Char.IsLetterOrDigit(line, i) && line[i] != '_') break; ++i; } var token = new SyntaxToken(SyntaxToken.Kind.Identifier, line.Substring(startAt, i - startAt)); startAt = i; return token; }
protected static SyntaxToken ScanWhitespace(string line, ref int startAt) { int i = startAt; while (i < line.Length && (line[i] == ' ' || line[i] == '\t')) ++i; if (i == startAt) return null; var token = new SyntaxToken(SyntaxToken.Kind.Whitespace, line.Substring(startAt, i - startAt)); startAt = i; return token; }
public static IEnumerable<SnippetCompletion> EnumSnippets(SymbolDefinition context, FGGrammar.TokenSet expected, SyntaxToken tokenLeft, Scope scope) { foreach (var snippet in snippets) { var text = snippet.Value; if (IsValid(ref text, context, expected)) yield return new SnippetCompletion(snippet.Key + "..."); } if (snippetsProviders == null) { snippetsProviders = new List<ISnippetProvider>(); var types = typeof(CodeSnippets).Assembly.GetTypes(); foreach (var type in types) if (typeof(ISnippetProvider).IsAssignableFrom(type) && type.IsClass && !type.IsAbstract) try { var instance = System.Activator.CreateInstance(type) as ISnippetProvider; snippetsProviders.Add(instance); } catch (System.Exception e) { Debug.LogException(e); } } foreach (var snippetsProvider in snippetsProviders) { foreach (var snippet in snippetsProvider.EnumSnippets(context, expected, tokenLeft, scope)) yield return snippet; } }
protected override void Tokenize(string line, FGTextBuffer.FormatedLine formatedLine) { var tokens = new List<SyntaxToken>(); formatedLine.tokens = tokens; int startAt = 0; int length = line.Length; SyntaxToken token; SyntaxToken ws = ScanWhitespace(line, ref startAt); if (ws != null) { tokens.Add(ws); ws.formatedLine = formatedLine; } if (formatedLine.blockState == FGTextBuffer.BlockState.None && startAt < length && line[startAt] == '#') { tokens.Add(new SyntaxToken(SyntaxToken.Kind.Preprocessor, "#") { formatedLine = formatedLine }); ++startAt; ws = ScanWhitespace(line, ref startAt); if (ws != null) { tokens.Add(ws); ws.formatedLine = formatedLine; } var error = false; var commentsOnly = false; var preprocessorCommentsAllowed = true; token = ScanWord(line, ref startAt); if (Array.BinarySearch(preprocessorKeywords, token.text) < 0) { token.tokenKind = SyntaxToken.Kind.PreprocessorDirectiveExpected; tokens.Add(token); token.formatedLine = formatedLine; error = true; } else { token.tokenKind = SyntaxToken.Kind.Preprocessor; tokens.Add(token); token.formatedLine = formatedLine; ws = ScanWhitespace(line, ref startAt); if (ws != null) { tokens.Add(ws); ws.formatedLine = formatedLine; } if (token.text == "if") { bool active = ParsePPOrExpression(line, formatedLine, ref startAt); bool inactiveParent = formatedLine.regionTree.kind > FGTextBuffer.RegionTree.Kind.LastActive; if (active && !inactiveParent) { OpenRegion(formatedLine, FGTextBuffer.RegionTree.Kind.If); commentsOnly = true; } else { OpenRegion(formatedLine, FGTextBuffer.RegionTree.Kind.InactiveIf); commentsOnly = true; } } else if (token.text == "elif") { bool active = ParsePPOrExpression(line, formatedLine, ref startAt); bool inactiveParent = formatedLine.regionTree.kind > FGTextBuffer.RegionTree.Kind.LastActive; if (formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.If || formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.Elif || formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.InactiveElif) { OpenRegion(formatedLine, FGTextBuffer.RegionTree.Kind.InactiveElif); } else if (formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.InactiveIf) { inactiveParent = formatedLine.regionTree.parent.kind > FGTextBuffer.RegionTree.Kind.LastActive; if (active && !inactiveParent) { OpenRegion(formatedLine, FGTextBuffer.RegionTree.Kind.Elif); } else { OpenRegion(formatedLine, FGTextBuffer.RegionTree.Kind.InactiveElif); } } else { token.tokenKind = SyntaxToken.Kind.PreprocessorUnexpectedDirective; } } else if (token.text == "else") { if (formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.If || formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.Elif) { OpenRegion(formatedLine, FGTextBuffer.RegionTree.Kind.InactiveElse); } else if (formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.InactiveIf || formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.InactiveElif) { bool inactiveParent = formatedLine.regionTree.parent.kind > FGTextBuffer.RegionTree.Kind.LastActive; if (inactiveParent) OpenRegion(formatedLine, FGTextBuffer.RegionTree.Kind.InactiveElse); else OpenRegion(formatedLine, FGTextBuffer.RegionTree.Kind.Else); } else { token.tokenKind = SyntaxToken.Kind.PreprocessorUnexpectedDirective; } } else if (token.text == "endif") { if (formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.If || formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.Elif || formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.Else || formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.InactiveIf || formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.InactiveElif || formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.InactiveElse) { CloseRegion(formatedLine); } else { token.tokenKind = SyntaxToken.Kind.PreprocessorUnexpectedDirective; } } else if (token.text == "region") { var inactive = formatedLine.regionTree.kind > FGTextBuffer.RegionTree.Kind.LastActive; if (inactive) { OpenRegion(formatedLine, FGTextBuffer.RegionTree.Kind.InactiveRegion); } else { OpenRegion(formatedLine, FGTextBuffer.RegionTree.Kind.Region); } preprocessorCommentsAllowed = false; } else if (token.text == "endregion") { if (formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.Region || formatedLine.regionTree.kind == FGTextBuffer.RegionTree.Kind.InactiveRegion) { CloseRegion(formatedLine); } else { token.tokenKind = SyntaxToken.Kind.PreprocessorUnexpectedDirective; } preprocessorCommentsAllowed = false; } else if (token.text == "define" || token.text == "undef") { var symbol = FGParser.ScanIdentifierOrKeyword(line, ref startAt); if (symbol != null && symbol.text != "true" && symbol.text != "false") { symbol.tokenKind = SyntaxToken.Kind.PreprocessorSymbol; formatedLine.tokens.Add(symbol); symbol.formatedLine = formatedLine; scriptDefinesChanged = true; var inactive = formatedLine.regionTree.kind > FGTextBuffer.RegionTree.Kind.LastActive; if (!inactive) { if (token.text == "define") { if (!scriptDefines.Contains(symbol.text)) { scriptDefines.Add(symbol.text); //scriptDefinesChanged = true; } } else { if (scriptDefines.Contains(symbol.text)) { scriptDefines.Remove(symbol.text); //scriptDefinesChanged = true; } } } } } else if (token.text == "error" || token.text == "warning") { preprocessorCommentsAllowed = false; } } if (!preprocessorCommentsAllowed) { ws = ScanWhitespace(line, ref startAt); if (ws != null) { tokens.Add(ws); ws.formatedLine = formatedLine; } if (startAt < length) { var textArgument = line.Substring(startAt); textArgument.TrimEnd(new [] {' ', '\t'}); tokens.Add(new SyntaxToken(SyntaxToken.Kind.PreprocessorArguments, textArgument) { formatedLine = formatedLine }); startAt = length - textArgument.Length; if (startAt < length) tokens.Add(new SyntaxToken(SyntaxToken.Kind.Whitespace, line.Substring(startAt)) { formatedLine = formatedLine }); } return; } while (startAt < length) { ws = ScanWhitespace(line, ref startAt); if (ws != null) { tokens.Add(ws); ws.formatedLine = formatedLine; continue; } var firstChar = line[startAt]; if (startAt < length - 1 && firstChar == '/' && line[startAt + 1] == '/') { tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, line.Substring(startAt)) { formatedLine = formatedLine }); break; } else if (commentsOnly) { tokens.Add(new SyntaxToken(SyntaxToken.Kind.PreprocessorCommentExpected, line.Substring(startAt)) { formatedLine = formatedLine }); break; } if (char.IsLetterOrDigit(firstChar) || firstChar == '_') { token = ScanWord(line, ref startAt); token.tokenKind = SyntaxToken.Kind.PreprocessorArguments; tokens.Add(token); token.formatedLine = formatedLine; } else if (firstChar == '"') { token = ScanStringLiteral(line, ref startAt); token.tokenKind = SyntaxToken.Kind.PreprocessorArguments; tokens.Add(token); token.formatedLine = formatedLine; } else if (firstChar == '\'') { token = ScanCharLiteral(line, ref startAt); token.tokenKind = SyntaxToken.Kind.PreprocessorArguments; tokens.Add(token); token.formatedLine = formatedLine; } else { token = new SyntaxToken(SyntaxToken.Kind.PreprocessorArguments, firstChar.ToString()) { formatedLine = formatedLine }; tokens.Add(token); ++startAt; } if (error) { token.tokenKind = SyntaxToken.Kind.PreprocessorDirectiveExpected; } } return; } var inactiveLine = formatedLine.regionTree.kind > FGTextBuffer.RegionTree.Kind.LastActive; while (startAt < length) { switch (formatedLine.blockState) { case FGTextBuffer.BlockState.None: ws = ScanWhitespace(line, ref startAt); if (ws != null) { tokens.Add(ws); ws.formatedLine = formatedLine; continue; } if (inactiveLine) { tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, line.Substring(startAt)) { formatedLine = formatedLine }); startAt = length; break; } if (line[startAt] == '/' && startAt < length - 1) { if (line[startAt + 1] == '/') { tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, "//") { formatedLine = formatedLine }); startAt += 2; tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, line.Substring(startAt)) { formatedLine = formatedLine }); startAt = length; break; } else if (line[startAt + 1] == '*') { tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, "/*") { formatedLine = formatedLine }); startAt += 2; formatedLine.blockState = FGTextBuffer.BlockState.CommentBlock; break; } } if (line[startAt] == '\'') { token = ScanCharLiteral(line, ref startAt); tokens.Add(token); token.formatedLine = formatedLine; break; } if (line[startAt] == '\"') { token = ScanStringLiteral(line, ref startAt); tokens.Add(token); token.formatedLine = formatedLine; break; } if (startAt < length - 1 && line[startAt] == '@' && line[startAt + 1] == '\"') { token = new SyntaxToken(SyntaxToken.Kind.VerbatimStringBegin, line.Substring(startAt, 2)) { formatedLine = formatedLine }; tokens.Add(token); startAt += 2; formatedLine.blockState = FGTextBuffer.BlockState.StringBlock; break; } if (line[startAt] >= '0' && line[startAt] <= '9' || startAt < length - 1 && line[startAt] == '.' && line[startAt + 1] >= '0' && line[startAt + 1] <= '9') { token = ScanNumericLiteral(line, ref startAt); tokens.Add(token); token.formatedLine = formatedLine; break; } token = ScanIdentifierOrKeyword(line, ref startAt); if (token != null) { tokens.Add(token); token.formatedLine = formatedLine; break; } // Multi-character operators / punctuators // "++", "--", "<<", ">>", "<=", ">=", "==", "!=", "&&", "||", "??", "+=", "-=", "*=", "/=", "%=", // "&=", "|=", "^=", "<<=", ">>=", "=>", "::" var punctuatorStart = startAt++; if (startAt < line.Length) { switch (line[punctuatorStart]) { case '?': if (line[startAt] == '?') ++startAt; break; case '+': if (line[startAt] == '+' || line[startAt] == '=') ++startAt; break; case '-': if (line[startAt] == '-' || line[startAt] == '=') ++startAt; break; case '<': if (line[startAt] == '=') ++startAt; else if (line[startAt] == '<') { ++startAt; if (startAt < line.Length && line[startAt] == '=') ++startAt; } break; case '>': if (line[startAt] == '=') ++startAt; //else if (startAt < line.Length && line[startAt] == '>') //{ // ++startAt; // if (line[startAt] == '=') // ++startAt; //} break; case '=': if (line[startAt] == '=' || line[startAt] == '>') ++startAt; break; case '&': if (line[startAt] == '=' || line[startAt] == '&') ++startAt; break; case '|': if (line[startAt] == '=' || line[startAt] == '|') ++startAt; break; case '*': case '/': case '%': case '^': case '!': if (line[startAt] == '=') ++startAt; break; case ':': if (line[startAt] == ':') ++startAt; break; } } tokens.Add(new SyntaxToken(SyntaxToken.Kind.Punctuator, line.Substring(punctuatorStart, startAt - punctuatorStart)) { formatedLine = formatedLine }); break; case FGTextBuffer.BlockState.CommentBlock: int commentBlockEnd = line.IndexOf("*/", startAt); if (commentBlockEnd == -1) { tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, line.Substring(startAt)) { formatedLine = formatedLine }); startAt = length; } else { tokens.Add(new SyntaxToken(SyntaxToken.Kind.Comment, line.Substring(startAt, commentBlockEnd + 2 - startAt)) { formatedLine = formatedLine }); startAt = commentBlockEnd + 2; formatedLine.blockState = FGTextBuffer.BlockState.None; } break; case FGTextBuffer.BlockState.StringBlock: int i = startAt; int closingQuote = line.IndexOf('\"', startAt); while (closingQuote != -1 && closingQuote < length - 1 && line[closingQuote + 1] == '\"') { i = closingQuote + 2; closingQuote = line.IndexOf('\"', i); } if (closingQuote == -1) { tokens.Add(new SyntaxToken(SyntaxToken.Kind.VerbatimStringLiteral, line.Substring(startAt)) { formatedLine = formatedLine }); startAt = length; } else { tokens.Add(new SyntaxToken(SyntaxToken.Kind.VerbatimStringLiteral, line.Substring(startAt, closingQuote - startAt)) { formatedLine = formatedLine }); startAt = closingQuote; tokens.Add(new SyntaxToken(SyntaxToken.Kind.VerbatimStringLiteral, line.Substring(startAt, 1)) { formatedLine = formatedLine }); ++startAt; formatedLine.blockState = FGTextBuffer.BlockState.None; } break; } } }
public void InsertMissingToken(string errorMessage) { //Debug.Log("Missing at line " + (currentLine + 1) + "\n" + errorMessage); var missingAtLine = currentLine; var missingAtIndex = currentTokenIndex; while (true) { if (--missingAtIndex < 0) { if (--missingAtLine < 0) { missingAtLine = missingAtIndex = 0; break; } missingAtIndex = lines[missingAtLine].tokens.Count; continue; } var tokenKind = lines[missingAtLine].tokens[missingAtIndex].tokenKind; if (tokenKind > SyntaxToken.Kind.LastWSToken) { ++missingAtIndex; break; } else if (tokenKind == SyntaxToken.Kind.Missing) { ErrorToken = lines[missingAtLine].tokens[missingAtIndex].parent; return; } } var missingLine = lines[missingAtLine]; //for (var i = missingAtIndex; i < missingLine.tokens.Count; ++i) //{ // var token = missingLine.tokens[i]; // if (token.parent != null) // ++token.parent.tokenIndex; //} var missingToken = new SyntaxToken(SyntaxToken.Kind.Missing, string.Empty) { style = null, formatedLine = missingLine }; missingLine.tokens.Insert(missingAtIndex, missingToken); var leaf = ErrorParseTreeNode.AddToken(missingToken); leaf.missing = true; leaf.syntaxError = errorMessage; leaf.grammarNode = ErrorGrammarNode; //leaf.line = CurrentLine() - 1; if (ErrorToken == null) ErrorToken = leaf; if (missingAtLine == currentLine) ++currentTokenIndex; }
public bool CollectCompletions(TokenSet tokenSet) { var result = (CurrentGrammarNode ?? CsGrammar.instance.r_compilationUnit).CollectCompletions(tokenSet, this, grammar.tokenIdentifier); if (CurrentGrammarNode != null && tokenSet.Matches(Instance.tokenIdentifier)) { currentTokenCache = new SyntaxToken(SyntaxToken.Kind.Identifier, "special"); currentTokenCache.tokenId = grammar.tokenIdentifier; Lookahead(CurrentGrammarNode, 1); currentTokenCache = null; } return result; }
public Scanner(CsGrammar grammar, FGTextBuffer.FormatedLine[] formatedLines, string fileName) { this.grammar = grammar; this.fileName = fileName; lines = formatedLines; if (EOF == null) EOF = new SyntaxToken(SyntaxToken.Kind.EOF, string.Empty) { tokenId = grammar.tokenEOF }; }