2012-05-09 7 views
6

式は次のとおりです。このBackus-Naur Form式をRegex(.Net)に変換するにはどうしたらいいですか?

N | (1 { A | B | C | D | E1 | E2 | E3 }) 

繰り返しなし記述子「N」または列挙された記述子の一つ以上の意味します。

私が持っている最高のは、次のとおりです。

@"^(N|(A|B|C|D|E1|E2|E3){1,})$" 

しかし、それは繰り返しを防ぐことはできません。

@"^(N|(A{0,1}B{0,1}...)$" 

これは繰り返しを防ぎますが、要素に対して特定の順序を必要とします。これは実際には問題ありません。

アイデア?

(私はBNF式自体は繰り返しを禁止することを実際に確認していないが、それは私が必要なものである。)

+0

http://kore-nordmann.de/blog/do_NOT_parse_using_regexp.html正規表現を使用して、構造ではなく単語を認識します。 –

+0

私はそれが理にかなっていると思います。しかし、私はこの構造を認識するために何を使用するでしょうか? @DavidBrabant このフォームの入力を検証するために使用されます。 – Daniel

+0

PCREはあなたが提案している方法ですか? – Daniel

答えて

4

さて、あなたはできますが、それはかなりありません:

Regex regexObj = new Regex(
    @"^   # Start of string 
    (?:   # Either match... 
    N   # N 
    |    # or... 
    (?:   # Match one of the following: 
     A(?!.*A) # A unless followed somewhere later by another A 
    |   # or 
     B(?!.*B) # B unless... 
    |   # etc. etc. 
     C(?!.*C) 
    | 
     D(?!.*D) 
    | 
     E1(?!.*E1) 
    | 
     E2(?!.*E2) 
    | 
     E3(?!.*E3) 
    )+   # one or more times 
    )    # End of alternation 
    $    # End of string", 
    RegexOptions.IgnorePatternWhitespace); 

このソリューションはnegative lookahead assertionsを使用しています。

+0

ニース、ありがとう! – Daniel

+0

ただの質問です@ティム。 「?:」にはどのような機能がありますか?その2つがなければ働いているようです。 – Daniel

+0

@Daniel:唯一の違いは '(...)'は*捕獲*グループだということです。つまり、正規表現エンジンはそのグループの中で一致したものを後方参照に格納し、後で参照することができます。あなたがそれをする必要がなければ、 '(?:...)'はまったく同じ働きをしますが、マッチのその部分を保存しません。したがって、それらはもう少し効率的です。 –

1

私はそれがより強力である(でも、.NET Regexは可能だかわかりませんこれを行うための「正規言語」の厳密な定義)とにかく、あなただけRegexを使用する必要がない限り、(私の心に)間違って何もしてありません。

bool IsValid(string input) 
{ 
    var Ns = input.Count(c => c == 'N'); 
    var As = input.Count(c => c == 'A'); 
    // etc 
    var E1s = Regex.Matches(input, "E1").Count 
    // etc 

    var maxDescriptorCount = (new[] { As, ... ,E1s, ... }).Max(); 

    var isValid = 
     ((Ns == 1) && (maxDescriptorCount == 0)) 
     || 
     ((Ns == 0) && (maxDescriptorCount == 1)) 
     ; 

    return isValid; 
} 

それは問題を解決最短コードですか?いいえ、それは可読で保守可能ですか?私はそう思う。

(あなたが望んでいた場合は、署名int MaxN(params int[] numbers)とユーティリティメソッドを書くことができる)

関連する問題