将Backus-Naur形式语法转换为.Net正则表达式

Ada*_*gen 4 .net regex bnf

有没有办法将以下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 ">>"
Run Code Online (Sandbox Code Playgroud)

我很接近,但我无法弄清楚如何应对逃避\).这将捕获命名组中的fieldnameoption:

<<(?<fieldname>.\*?)(\((?<option>.*?)\))?>>
Run Code Online (Sandbox Code Playgroud)

编辑

事实证明,我对BNF语法比我想象的更生气.

我试图得到的是括号是特殊字符.在"选项"部分中,它们必须通过斜杠进行转义.(还必须转义斜线).

Mar*_*rot 8

BNF用于描述正则表达式通常无法描述的无上下文语言.无上下文语言与正则表达式的区别在于无上下文语言可以同时在双方进行递归.一个典型的例子是平衡括号问题.

paren = paren paren
      | '(' paren ')'  <-- there are characters on both sides of the recursion
      | ''
Run Code Online (Sandbox Code Playgroud)

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

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

pattern = /<<(?<fieldname>   )(?:\((?<option>   )\))?>>/
Run Code Online (Sandbox Code Playgroud)

把它放在一起:

pattern = /<<(?<fieldname>(?:>?[^(>])+)(?:\((?<option>(?:[^()\\]|\\.)*)\))?>>/
Run Code Online (Sandbox Code Playgroud)

一些边境案件:

<<f>oo(bar>>)>> --> ('f>oo', 'bar>>')
<<foo(bar\))>>  --> ('foo', 'bar\)')
<<foo(bar\\)>>  --> ('foo', 'bar\\')
<<foo\(bar)>>   --> ('foo\', 'bar')
Run Code Online (Sandbox Code Playgroud)

编辑:

如果你想要任何额外的括号字符(和回斜线)不得不在里面逃脱<<>>,你可以这样做:

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

/<<(?<fieldname>(?:<?[^()\\]|<?\\[()\\])+)(?:\((?<option>(?:[^()\\]|\\[()\\])*)\))?>>/
Run Code Online (Sandbox Code Playgroud)

更新:

<<f>oo(bar>>)>> --> ('f>oo', 'bar>>')
<<foo(bar\))>>  --> ('foo', 'bar\)')
<<foo(bar\\)>>  --> ('foo', 'bar\\')
<<foo\(bar)>>   --> doesn't match
<<foo\((bar)>>  --> ('foo\(', 'bar')
Run Code Online (Sandbox Code Playgroud)


Joe*_*Joe 0

我一直在思考一个答案,并希望有人能跳到我身上,这样我就可以停下来。:)

BNF 的递归性质通常是一个很好的开端指标,如果您的问题可以很好地映射到 BNF,那么它就不能很好地映射到正则表达式。

我必须承认,我不确定我是否能算出你的 BNF。例如: x ::= << Boo ( abc321 ) >>

建议您的“选项”对是 c3、b2 和 a1。这假设 char 是有效的“选项” - 您没有为不是空字符串的选项定义任何有效的终端值。这真的是意图吗?

假设您不想递归...处理转义和其他所有事情...您可能最好编写代码。这看起来比其他任何事情都更容易遍历字符串并进行处理。您想要的感觉表明您不需要任何前瞻或回顾逻辑。