2016-12-26 8 views
0

異なるリテックスを使用して、SQLのような文書(RichEditControl)内の単語やコメントを強調表示すると、問題が発生します。ハイライト用正規表現

これが私の最初の正規表現です:

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

これはで良い作品:/*blahblah*/--blahblah

そして、私は別の正規表現を持っている:

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

これはで良い作品:よう'blahblah'( SQL文字列)

しかし、私

タイプの未処理の例外「System.ArgumentExceptionのは」 DevExpress.Office.v15.2で発生しました:私は最後の'プログラムは私に例外を示し書く前

'/*blahblah*/' 

:これを行います。 Core.dll

ご協力いただきありがとうございます。

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:感謝ハリソンMcの

これは完全なコードです。

私は誰もがそれを必要とする場合に使用されるコードを共有し、唯一の私は(メソッドの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

私は(私はそのためにあまりにも疲れている)*問題が何であるかを知りません*] 'に既にCRとLFが含まれているので、' | [\ r \ n] 'を追加する必要はありません。 Cの複数行のコメントに一致する簡単なパターンは次のとおりです。 '/ \ * [^ *] *(?> \ * +(?!/)[^ *] *)* \ * /' –

+0

引用符付き文字列について: [^ \\ '] *(?> \\。[^ \\'] *)* '| "[^ \\"] *(?> \\。[^ \\ "] * )* "' –

答えて

0

コメント内の文字列のコメントや文字列を強調表示しないようにするためには、あなた正規表現では簡単には得られない、ある種の「状態」が必要です。これらの状況は、個々の文字列とコメントの正規表現が対処するのが難しいでしょう。文字列を検索するときにコメントになっているかどうかを追跡する必要があります。

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

あなたはコメントに対して一致文字列の異なるグループを持つ1つの正規表現を使用する場合は、文字の貪欲な消費は、物事をいじりからコメント内の文字列または「文字列」に「コメント」を防止するであろうアップ。

私はこの正規表現をテストしました。文字列の "コメント"とコメントの "文字列"(両方とも複数行)の両方で動作するように見えました。

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

ここで重要なのは、正規表現は、我々は、文字列の途中でやコメントの真ん中にいるかどうかを判断し、「状態」を追跡していることです。

これを使用するには、全体の一致から個々のグループを取得する必要があります。 (?<name>group)構文は名前付きグループを作成します。このグループは後で抽出することができます。 <string>グループに一致するグループがある場合は文字列、<comment>グループに一致するグループがある場合はコメントです。私はdocument.FindAll方法に精通していないよので、私はregex.Matchesメソッドを使用して.NETドキュメントからの例を採用した:

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 
    } 
} 

をうまくいけば、このことができます!

P.S. regex101.comを使って正規表現をテストしましたが、そうするためにスラッシュをエスケープして二重引用符をエスケープしなくてはなりませんでした。私は彼らを戻すために最善を尽くしましたが、私は1つか2つを見逃しているかもしれません。

参考文献:^ [ `*)、しかし:

+0

ありがとう!例と参考文献は非常に有用でした。私はhaha xD(ur exampleとFindAll method)の両方の方法を混在させなければならなかったが、今はすべて正常に動作する。ここでは、プロセスがエディタを遅らせることのない方法を探します。これは、常にドキュメント全体を検索するためです。もう一度、ありがとう! :D – Guharo