2016-12-26 6 views
0

Ich habe ein Problem, wenn ich verschiedene Regex verwenden, um Wörter und Kommentare im Dokument (RichEditControl) wie SQL hervorzuheben.Regex für Highlight

Dies ist mein erster Regex:

(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(--.*) 

Das funktioniert gut in: /*blahblah*/ und --blahblah

Und ich habe eine andere Regex:

((""(.|/[[:blank:]]/)*?"")|('(.|/[[:blank:]]/)*?')) 

Das funktioniert gut in: 'blahblah' (wie sql string)

Aber wenn ich dies tut:

'/*blahblah*/' 

Bevor ich das letzte ' das Programm zeigt mir eine Ausnahme schreiben:

Eine nicht behandelte Ausnahme des Typs 'System.ArgumentException' aufgetreten in DevExpress.Office.v15.2. Core.dll

Vielen Dank im Voraus für die Hilfe.

Dies ist der vollständige Code:

private List<SyntaxHighlightToken> ParseTokens() 
    { 
     List<SyntaxHighlightToken> tokens = new List<SyntaxHighlightToken>();    
     DocumentRange[] ranges = null;    

     #region SearchSimpleCommas 
     Regex quotations = new Regex(@"((""(.|/[[:blank:]]/)*?"")|('(.|/[[:blank:]]/)*?'))"); 
     ranges = document.FindAll(quotations); 
     foreach (var range in ranges) 
     { 
      if (!IsRangeInTokens(range, tokens)) 
       tokens.Add(new SyntaxHighlightToken(range.Start.ToInt(), range.Length, StringSettings)); 
     } 
     #endregion 

     #region SearchComment--/**/ 
     Regex comment = new Regex(@"(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(--.*)", RegexOptions.IgnoreCase | RegexOptions.Multiline); 
     ranges = document.FindAll(comment); 
     for (int i = 0; i < ranges.Length; i++) 
     { 
      tokens.Add(new SyntaxHighlightToken(ranges[i].Start.ToInt(), ranges[i].Length, CommentsSettings)); 
     } 
     #endregion 

     tokens.Sort(new SyntaxHighlightTokenComparer()); 
     // fill in gaps in document coverage 
     AddPlainTextTokens(tokens); 
     return tokens; 
    } 

    private void AddPlainTextTokens(List<SyntaxHighlightToken> tokens) 
    { 
     int count = tokens.Count; 
     if (count == 0) 
     { 
      tokens.Add(new SyntaxHighlightToken(0, document.Range.End.ToInt(), defaultSettings)); 
      return; 
     } 
     tokens.Insert(0, new SyntaxHighlightToken(0, tokens[0].Start, defaultSettings)); 
     for (int i = 1; i < count; i++) 
     { 
      tokens.Insert(i * 2, new SyntaxHighlightToken(tokens[i * 2 - 1].End, tokens[i * 2].Start - tokens[i * 2 - 1].End, defaultSettings)); 
     } 
     tokens.Add(new SyntaxHighlightToken(tokens[count * 2 - 1].End, document.Range.End.ToInt() - tokens[count * 2 - 1].End, defaultSettings)); 
    } 

    private bool IsRangeInTokens(DocumentRange range, List<SyntaxHighlightToken> tokens) 
    { 
     return tokens.Any(t => IsIntersect(range, t));    
    } 
    bool IsIntersect(DocumentRange range, SyntaxHighlightToken token) 
    { 
     int start = range.Start.ToInt(); 
     if (start >= token.Start && start < token.End) 
      return true; 
     int end = range.End.ToInt() - 1; 
     if (end >= token.Start && end < token.End) 
      return true; 
     return false; 
    } 

    #region ISyntaxHighlightServiceMembers 
    public void ForceExecute() 
    { 
     Execute(); 
    } 
    public void Execute() 
    {//The Exepction show in this part 
     document.ApplySyntaxHighlight(ParseTokens()); 
    } 
    #endregion 

EDIT: Danke Harrison Mc.

ich den Code, den ich für den Fall verwendet, teilen Sie es jemand braucht, nur das, was geändert I (innen Methode ParseTokens):

#region SearchComments&Strings 
    Regex definitiveRegex = new Regex(@"(?<string>'[^\\']*(?>\\.[^\\']*)*')|(?<comment>(?>/\*(?>[^*]|[\r\n]|(?>\*+(?>[^*/]|[\r\n])))*\*+/)|(?>--.*))"); 
    MatchCollection matches = definitiveRegex.Matches(document.Text); 
    foreach (System.Text.RegularExpressions.Match match in matches) 
    { 
     try 
     { 
      System.Text.RegularExpressions.GroupCollection groups = match.Groups; 
      if (groups["string"].Value.Length > 0) 
      { 
       ranges = null; 
       for (int s = 0; s < groups.Count; s++) 
       { 
        if (groups[s].Value != string.Empty) 
        { 
         ranges = document.FindAll(groups[s].Value, SearchOptions.None); 
         for (int z = 0; z < ranges.Length; z++) 
         { 
          if(!IsRangeInTokens(ranges[z], tokens)) 
           tokens.Add(new SyntaxHighlightToken(ranges[z].Start.ToInt(), ranges[z].Length, StringSettings)); 
         } 
        } 
       } 
      } 
      else if (groups["comment"].Value.Length > 0) 
      { 
       ranges = null; 
       for (int c = 0; c < groups.Count; c++) 
       { 
        if (groups[c].Value != string.Empty) 
        { 
         ranges = document.FindAll(groups[c].Value.Trim(), SearchOptions.None); 
         for (int k = 0; k < ranges.Length; k++) 
         { 
          if (!IsRangeInTokens(ranges[k], tokens)) 
           tokens.Add(new SyntaxHighlightToken(ranges[k].Start.ToInt(), ranges[k].Length, CommentsSettings)); 
         } 
        } 
       } 
      } 
     } 
     catch(Exception ex){ } 
    } 
    #endregion 
+0

Ich weiß nicht, was das Problem ist * (Ich bin zu müde dafür:)) *, aber: '[^ *] 'enthält bereits CR und LF, Sie müssen nicht' | [\ r \ n] 'hinzufügen. Ein einfaches Muster, um C mehrzeiligen Kommentaren zu entsprechen, ist: '/ \ * [^ *] * (?> \ * + (?! /) [^ *] *) * \ * /' –

+0

Über in Anführungszeichen gesetzte Zeichenfolgen: Sie können etwas verwenden so: ''[^ \\'] * (?> \\. [^ \\ '] *) *' |" [^ \\ "] * (?> \\. [^ \\"] *) * "' –

Antwort

0

Um Kommentare markieren Kommentare in Strings und Strings zu vermeiden, können Sie brauche eine Art von "Zustand", den reguläre Ausdrücke nicht leicht geben können. Diese Situationen wären für einzelne reguläre Ausdrücke und Kommentare mit regulären Ausdrücken schwierig, da Sie bei der Suche nach einer Zeichenfolge verfolgen müssen, ob Sie in einem Kommentar sind oder nicht, und umgekehrt.

"This string looks like it contains a /*comment*/ but it does not." 
/* This comment looks like it contains a 'string' but it does not. */ 

Wenn Sie jedoch einen regulären Ausdruck verwenden, die verschiedenen Gruppen für Matchstrings im Vergleich zu Kommentaren, die gierigen raubend von Zeichen einen „Kommentar“ in einem String oder einen „string“ aus Messing Dingen in einem Kommentar würden verhindern oben.

Ich testete diesen regulären Ausdruck, und es schien für "Kommentare" in Strings und "Strings" in Kommentaren (beide mit mehreren Zeilen) zu funktionieren.

(?<string>'[^\\']*(?>\\.[^\\']*)*'|""[^\\""]*(?>\\.[^\\""]*)*"")|(?<comment>(?>/\*(?>[^*]|[\r\n]|(?>\*+(?>[^*/]|[\r\n])))*\*+/)|(?>--.*)) 

Der Schlüssel hier ist, dass der reguläre Ausdruck Spur des „Staates“ hält, dass, wenn wir einen Kommentar sind in der Mitte eines Strings oder in der Mitte bestimmt.

Um dies zu verwenden, müssen Sie die einzelnen Gruppen aus der Gesamtübereinstimmung herausnehmen. Die (?<name>group)-Syntax erstellt eine benannte Gruppe, die Sie später extrahieren können. Wenn die Gruppe <string> eine Übereinstimmung aufweist, handelt es sich um eine Zeichenfolge. Wenn die Gruppe <comment> eine Übereinstimmung aufweist, handelt es sich um einen Kommentar.Da ich mit der document.FindAll Methode nicht vertraut bin, angenommen ich ein Beispiel aus der .NET-Dokumentation mit der regex.Matches Methode:

Regex stringAndCommentRegex = new Regex(@"(?<string>'[^\\']*..."); 
MatchCollection matches = stringAndCommentRegex.Matches(text); 
foreach (Match match in matches) 
{ 
    GroupCollection groups = match.Groups; 
    if (match.groups["string"].Value.Length > 0) 
    { 
     // handle string 
    } 
    else if (match.groups["comment"].Value.Length > 0) 
    { 
     // handle comment 
    } 
} 

Hoffentlich hilft!

P.S. Ich habe regex101.com benutzt, um die Regex zu testen, aber dazu musste ich den Schrägstrichen entkommen und nicht den Anführungszeichen entgehen. Ich habe mein Bestes versucht, sie wieder hinzuzufügen, aber ich habe vielleicht ein oder zwei verpasst.

Referenzen:

+0

Danke! Das Beispiel und die Referenzen waren sehr nützlich. Ich musste beide Wege haha ​​xD (ur Beispiel und FindAll Methode) mischen, aber jetzt funktioniert alles richtig. Jetzt werde ich nach der Art und Weise suchen, wie der Prozess den Editor nicht verlangsamt, da er immer das gesamte Dokument durchsucht. Noch einmal Danke! : D – Guharo