2016-12-26 2 views
0

다른 정규 표현식을 사용하여 SQL과 같은 문서 (RichEditControl)의 단어 및 주석을 강조 표시 할 때 문제가 있습니다. 같은 ('blahblah' :하이라이트 용 정규식

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

이 좋은 작동합니다 :

이 내 첫 정규 표현식입니다 /*blahblah*/--blahblah

그리고 또 다른 정규식이 :

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

이 좋은 작품을 SQL 문자열)

하지만, 만약 내가 이 작업을 수행 :

'/*blahblah*/' 

를 내가 마지막 ' 프로그램이 나에게 예외 보여 작성하기 전에 'System.ArgumentException'형식의

처리되지 않은 예외가 DevExpress.Office.v15.2 발생했습니다. 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 

편집 : : 감사 해리슨 맥

이 전체 코드입니다.

나는 사람이 그것을 필요로하는 경우에 사용되는 코드를 공유 만 나는 (방법 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. */ 

그러나 문자의 욕심 소비는 문자열에 "코멘트"또는 장난 일에서 코멘트에서 "문자열"을 방지 할 수 쪽으로.

이 정규 표현식을 테스트 한 결과 문자열의 "주석"과 주석의 "문자열"(둘 다 여러 줄로 된) 모두에서 작동하는 것처럼 보였습니다. 여기

(?<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. regex101.com을 사용하여 정규식을 테스트했지만, 그렇게하려면 슬래시를 벗어나서 큰 따옴표를 벗어나지 않아야했습니다. 나는 그들을 다시 추가하기 위해 최선을 다했지만, 나는 하나 또는 둘을 놓칠지도 모른다.

참고 :

내가 문제 * (I가 너무 피곤 해요 :) 무엇인지 모르는
+0

고마워! 예와 참고 문헌은 매우 유용했습니다. 나는 haha ​​xD (ur example과 FindAll method) 두 가지 방법을 혼합해야했지만 이제는 모든 것이 제대로 작동한다. 이제는 문서가 항상 전체 문서를 검색하므로 프로세스가 편집기를 느리게하지 않는 방법을 살펴 보겠습니다. 다시 고마워! :디 – Guharo