是否可以将以下Backus–Naur形式(BNF)语法转换为.Net正则表达式? (我并不拘泥于BNF,但我认为这可能是解释我正在尝试做的最好的方法)。

<field> ::= "<<" <fieldname> <options> ">>"

<options> ::= "" | "(" <option> ")"

<option> ::= "" |
             <option> <non-paren> |
             <option> <escaped-character>

<escaped-character> ::= "\\" | "\)"

<non-paren> ::= any character but paren

<fieldname> ::= any string that doesn't contain "(" or ">>"


我已经接近了,但是我不知道如何处理转义的\)。这将捕获命名组中的fieldnameoption

<<(?<fieldname>.\*?)(\((?<option>.*?)\))?>>




编辑

事实证明,我对BNF语法的怀疑比我想象的要生锈。

我想知道的是括号是特殊字符。在“选项”部分中,必须用斜杠将其转义。 (并且也必须转义斜线)。

最佳答案

BNF用于描述无上下文语言,而regex通常无法描述这种语言。区分上下文无关的语言和正则表达式的是,上下文无关的语言可以同时在两侧进行递归。一个经典的例子是平衡括号问题。

paren = paren paren
      | '(' paren ')'  <-- there are characters on both sides of the recursion
      | ''


在您的情况下,您不使用任何双面递归,因此可以简化为常规语言。

fieldname = /(?:>?[^(>])+/    //No double >, but single ones are ok.
option = /(?:[^()\\]|\\.)*/   //No parens, unless preceeded by \

pattern = /<<(?<fieldname>   )(?:\((?<option>   )\))?>>/


把它放在一起:

pattern = /<<(?<fieldname>(?:>?[^(>])+)(?:\((?<option>(?:[^()\\]|\\.)*)\))?>>/


一些边境案件:

<<f>oo(bar>>)>> --> ('f>oo', 'bar>>')
<<foo(bar\))>>  --> ('foo', 'bar\)')
<<foo(bar\\)>>  --> ('foo', 'bar\\')
<<foo\(bar)>>   --> ('foo\', 'bar')




编辑:

如果要在<<>>中转义任何多余的括号字符(和反斜杠),可以执行以下操作:

fieldname = /(?:<?[^()\\<]|<?\\[()\\])+/
options = /(?:[^()\\]|\\[()\\])*/
pattern = /<<(?<fieldname>   )(?:\((?<option>   )\))?>>/

/<<(?<fieldname>(?:<?[^()\\]|<?\\[()\\])+)(?:\((?<option>(?:[^()\\]|\\[()\\])*)\))?>>/


更新:

<<f>oo(bar>>)>> --> ('f>oo', 'bar>>')
<<foo(bar\))>>  --> ('foo', 'bar\)')
<<foo(bar\\)>>  --> ('foo', 'bar\\')
<<foo\(bar)>>   --> doesn't match
<<foo\((bar)>>  --> ('foo\(', 'bar')

10-04 18:17