void PushStack(SyntaxMatch curMatch, IEnumerable <SyntaxContext> nextContexts) { if (nextContexts != null) { bool first = true; foreach (var nextContext in nextContexts) { var ctx = nextContext; if (curMatch.WithPrototype != null) { ctx = new SyntaxContextWithPrototype(nextContext, curMatch.WithPrototype); } if (first) { MatchStack = MatchStack.Push(curMatch); first = false; } else { MatchStack = MatchStack.Push(null); } ContextStack = ContextStack.Push(ctx); PushScopeStack(ctx.MetaScope); PushScopeStack(ctx.MetaContentScope); } } }
void PopMetaContentScopeStack(SyntaxContext currentContext, SyntaxMatch curMatch) { if (ContextStack.Count() == 1) { return; } PopScopeStack(currentContext.MetaContentScope); }
void PopStack(SyntaxContext currentContext, SyntaxMatch curMatch) { if (ContextStack.Count() == 1) { MatchStack = MatchStack.Clear(); ScopeStack = new ScopeStack(highlighting.definition.Scope); return; } ContextStack = ContextStack.Pop(); if (!MatchStack.IsEmpty) { PopScopeStack(MatchStack.Peek()?.Scope); MatchStack = MatchStack.Pop(); } PopScopeStack(currentContext.MetaScope); if (curMatch.Scope.Count > 0 && !ScopeStack.IsEmpty) { for (int i = 0; i < curMatch.Scope.Count; i++) { ScopeStack = ScopeStack.Pop(); } } }
public Task <HighlightedLine> GetColoredSegments(ITextSource text, int startOffset, int length, CancellationToken cancellationToken = default) { if (ContextStack.IsEmpty || length > maxLineLength) { return(Task.FromResult(new HighlightedLine(new TextSegment(startOffset, length), new [] { new ColoredSegment(0, length, ScopeStack.Empty) }))); } SyntaxContext currentContext = null; Match match = null; SyntaxMatch curMatch = null; var segments = new List <ColoredSegment> (); int offset = 0; int curSegmentOffset = 0; int endOffset = offset + length; int lastMatch = -1; var highlightedSegment = new TextSegment(startOffset, length); string lineText = text.GetTextAt(startOffset, length); var initialState = state.Clone(); int timeoutOccursAt; unchecked { timeoutOccursAt = Environment.TickCount + (int)matchTimeout.TotalMilliseconds; } restart: if (cancellationToken.IsCancellationRequested) { return(Task.FromResult(new HighlightedLine(new TextSegment(startOffset, length), new [] { new ColoredSegment(0, length, ScopeStack.Empty) }))); } if (offset >= lineText.Length) { goto end; } lastMatch = offset; currentContext = ContextStack.Peek(); match = null; curMatch = null; foreach (var m in currentContext.Matches) { if (m.GotTimeout) { continue; } var r = m.GetRegex(); if (r == null) { continue; } try { Match possibleMatch; if (r.pattern == "(?<=\\})" && offset > 0) // HACK to fix typescript highlighting. { possibleMatch = r.Match(lineText, offset - 1, length, matchTimeout); } else { possibleMatch = r.Match(lineText, offset, length, matchTimeout); } if (possibleMatch.Success) { if (match == null || possibleMatch.Index < match.Index) { match = possibleMatch; curMatch = m; // Console.WriteLine (match.Index + " possible match : " + m + "/" + possibleMatch.Index + "-" + possibleMatch.Length); } else { // Console.WriteLine (match.Index + " skip match : " + m + "/" + possibleMatch.Index + "-" + possibleMatch.Length); } } else { // Console.WriteLine ("fail match : " + m); } } catch (RegexMatchTimeoutException) { LoggingService.LogWarning("Warning: Regex " + m.Match + " timed out on line:" + text.GetTextAt(offset, length)); m.GotTimeout = true; continue; } } if (length <= 0 && curMatch == null) { goto end; } if (Environment.TickCount >= timeoutOccursAt) { if (curMatch != null) { curMatch.GotTimeout = true; } goto end; } if (match != null) { // Console.WriteLine (match.Index + " taken match : " + curMatch + "/" + match.Index + "-" + match.Length); var matchEndOffset = match.Index + match.Length; if (curSegmentOffset < match.Index && match.Length > 0) { segments.Add(new ColoredSegment(curSegmentOffset, match.Index - curSegmentOffset, ScopeStack)); curSegmentOffset = match.Index; } if (curMatch.Pop) { PopMetaContentScopeStack(currentContext, curMatch); } PushScopeStack(curMatch.Scope); if (curMatch.Captures.Groups.Count > 0) { for (int i = 0; i < curMatch.Captures.Groups.Count; ++i) { var capture = curMatch.Captures.Groups[i]; var grp = match.Groups [capture.Item1]; if (grp == null || grp.Length == 0) { continue; } if (curSegmentOffset < grp.Index) { ReplaceSegment(segments, new ColoredSegment(curSegmentOffset, grp.Index - curSegmentOffset, ScopeStack)); } ReplaceSegment(segments, new ColoredSegment(grp.Index, grp.Length, ScopeStack.Push(capture.Item2))); curSegmentOffset = Math.Max(curSegmentOffset, grp.Index + grp.Length); } } if (curMatch.Captures.NamedGroups.Count > 0) { for (int i = 0; i < curMatch.Captures.NamedGroups.Count; ++i) { var capture = curMatch.Captures.NamedGroups[i]; var grp = match.Groups [capture.Item1]; if (grp == null || grp.Length == 0) { continue; } if (curSegmentOffset < grp.Index) { ReplaceSegment(segments, new ColoredSegment(curSegmentOffset, grp.Index - curSegmentOffset, ScopeStack)); } ReplaceSegment(segments, new ColoredSegment(grp.Index, grp.Length, ScopeStack.Push(capture.Item2))); curSegmentOffset = grp.Index + grp.Length; } } if (curMatch.Scope.Count > 0 && curSegmentOffset < matchEndOffset && match.Length > 0) { segments.Add(new ColoredSegment(curSegmentOffset, matchEndOffset - curSegmentOffset, ScopeStack)); curSegmentOffset = matchEndOffset; } if (curMatch.Pop) { if (matchEndOffset - curSegmentOffset > 0) { segments.Add(new ColoredSegment(curSegmentOffset, matchEndOffset - curSegmentOffset, ScopeStack)); } //if (curMatch.Scope != null) // scopeStack = scopeStack.Pop (); PopStack(currentContext, curMatch); curSegmentOffset = matchEndOffset; } else if (curMatch.Set != null) { // if (matchEndOffset - curSegmentOffset > 0) // segments.Add (new ColoredSegment (curSegmentOffset, matchEndOffset - curSegmentOffset, ScopeStack)); //if (curMatch.Scope != null) // scopeStack = scopeStack.Pop (); PopMetaContentScopeStack(currentContext, curMatch); PopStack(currentContext, curMatch); //curSegmentOffset = matchEndOffset; var nextContexts = curMatch.Set.GetContexts(currentContext); PushStack(curMatch, nextContexts); goto skip; } else if (curMatch.Push != null) { var nextContexts = curMatch.Push.GetContexts(currentContext); PushStack(curMatch, nextContexts); } else { if (curMatch.Scope.Count > 0) { for (int i = 0; i < curMatch.Scope.Count; i++) { ScopeStack = ScopeStack.Pop(); } } } if (curSegmentOffset < matchEndOffset && match.Length > 0) { segments.Add(new ColoredSegment(curSegmentOffset, matchEndOffset - curSegmentOffset, ScopeStack)); curSegmentOffset = matchEndOffset; } skip: length -= curSegmentOffset - offset; offset = curSegmentOffset; goto restart; } end: if (endOffset - curSegmentOffset > 0) { segments.Add(new ColoredSegment(curSegmentOffset, endOffset - curSegmentOffset, ScopeStack)); } return(Task.FromResult(new HighlightedLine(highlightedSegment, segments) { IsContinuedBeyondLineEnd = !initialState.Equals(state) })); }
internal void AddMatch(SyntaxMatch match) { this.matches.Add(match); }
public Task <HighlightedLine> GetColoredSegments(ITextSource text, int startOffset, int length) { if (ContextStack.IsEmpty) { return(Task.FromResult(new HighlightedLine(new TextSegment(startOffset, length), new [] { new ColoredSegment(0, length, ScopeStack.Empty) }))); } SyntaxContext currentContext = null; List <SyntaxContext> lastContexts = new List <SyntaxContext> (); Match match = null; SyntaxMatch curMatch = null; var segments = new List <ColoredSegment> (); int offset = 0; int curSegmentOffset = 0; int endOffset = offset + length; int lastMatch = -1; var highlightedSegment = new TextSegment(startOffset, length); string lineText = text.GetTextAt(startOffset, length); restart: if (lastMatch == offset) { if (lastContexts.Contains(currentContext)) { offset++; length--; } else { lastContexts.Add(currentContext); } } else { lastContexts.Clear(); lastContexts.Add(currentContext); } if (length <= 0) { goto end; } lastMatch = offset; currentContext = ContextStack.Peek(); match = null; curMatch = null; foreach (var m in currentContext.Matches) { if (m.GotTimeout) { continue; } var r = m.GetRegex(); if (r == null) { continue; } try { var possibleMatch = r.Match(lineText, offset, length, matchTimeout); if (possibleMatch.Success) { if (match == null || possibleMatch.Index < match.Index) { match = possibleMatch; curMatch = m; // Console.WriteLine (match.Index + " possible match : " + m + "/" + possibleMatch.Index + "-" + possibleMatch.Length); } else { // Console.WriteLine (match.Index + " skip match : " + m + "/" + possibleMatch.Index + "-" + possibleMatch.Length); } } else { // Console.WriteLine ("fail match : " + m); } } catch (RegexMatchTimeoutException) { LoggingService.LogWarning("Warning: Regex " + m.Match + " timed out on line:" + text.GetTextAt(offset, length)); m.GotTimeout = true; continue; } } if (match != null) { // Console.WriteLine (match.Index + " taken match : " + curMatch + "/" + match.Index + "-" + match.Length); var matchEndOffset = match.Index + match.Length; if (curSegmentOffset < match.Index && match.Length > 0) { segments.Add(new ColoredSegment(curSegmentOffset, match.Index - curSegmentOffset, ScopeStack)); curSegmentOffset = match.Index; } if (curMatch.Pop) { PopMetaContentScopeStack(currentContext, curMatch); } PushScopeStack(curMatch.Scope); if (curMatch.Captures.Groups.Count > 0) { for (int i = 0; i < curMatch.Captures.Groups.Count; ++i) { var capture = curMatch.Captures.Groups[i]; var grp = match.Groups [capture.Item1]; if (grp == null || grp.Length == 0) { continue; } if (curSegmentOffset < grp.Index) { ReplaceSegment(segments, new ColoredSegment(curSegmentOffset, grp.Index - curSegmentOffset, ScopeStack)); } ReplaceSegment(segments, new ColoredSegment(grp.Index, grp.Length, ScopeStack.Push(capture.Item2))); curSegmentOffset = Math.Max(curSegmentOffset, grp.Index + grp.Length); } } if (curMatch.Captures.NamedGroups.Count > 0) { for (int i = 0; i < curMatch.Captures.NamedGroups.Count; ++i) { var capture = curMatch.Captures.NamedGroups[i]; var grp = match.Groups [capture.Item1]; if (grp == null || grp.Length == 0) { continue; } if (curSegmentOffset < grp.Index) { ReplaceSegment(segments, new ColoredSegment(curSegmentOffset, grp.Index - curSegmentOffset, ScopeStack)); } ReplaceSegment(segments, new ColoredSegment(grp.Index, grp.Length, ScopeStack.Push(capture.Item2))); curSegmentOffset = grp.Index + grp.Length; } } if (curMatch.Scope.Count > 0 && curSegmentOffset < matchEndOffset && match.Length > 0) { segments.Add(new ColoredSegment(curSegmentOffset, matchEndOffset - curSegmentOffset, ScopeStack)); curSegmentOffset = matchEndOffset; } if (curMatch.Pop) { if (matchEndOffset - curSegmentOffset > 0) { segments.Add(new ColoredSegment(curSegmentOffset, matchEndOffset - curSegmentOffset, ScopeStack)); } //if (curMatch.Scope != null) // scopeStack = scopeStack.Pop (); PopStack(currentContext, curMatch); curSegmentOffset = matchEndOffset; } else if (curMatch.Set != null) { // if (matchEndOffset - curSegmentOffset > 0) // segments.Add (new ColoredSegment (curSegmentOffset, matchEndOffset - curSegmentOffset, ScopeStack)); //if (curMatch.Scope != null) // scopeStack = scopeStack.Pop (); PopMetaContentScopeStack(currentContext, curMatch); PopStack(currentContext, curMatch); //curSegmentOffset = matchEndOffset; var nextContexts = curMatch.Set.GetContexts(currentContext); PushStack(curMatch, nextContexts); goto skip; } else if (curMatch.Push != null) { var nextContexts = curMatch.Push.GetContexts(currentContext); PushStack(curMatch, nextContexts); } else { if (curMatch.Scope.Count > 0) { for (int i = 0; i < curMatch.Scope.Count; i++) { ScopeStack = ScopeStack.Pop(); } } } if (curSegmentOffset < matchEndOffset && match.Length > 0) { segments.Add(new ColoredSegment(curSegmentOffset, matchEndOffset - curSegmentOffset, ScopeStack)); curSegmentOffset = matchEndOffset; } skip: length -= curSegmentOffset - offset; offset = curSegmentOffset; goto restart; } end: if (endOffset - curSegmentOffset > 0) { segments.Add(new ColoredSegment(curSegmentOffset, endOffset - curSegmentOffset, ScopeStack)); } return(Task.FromResult(new HighlightedLine(highlightedSegment, segments))); }