EBNF / parboiled:如何将正则表达式翻译成PEG?

时间:2011-03-03 18:06:23

标签: java parsing ebnf parboiled

这是一个特定于parboiled解析器框架和一般BNF / PEG的问题。

假设我有一个相当简单的正则表达式

^\\s*([A-Za-z_][A-Za-z_0-9]*)\\s*=\\s*(\\S+)\\s*$

代表

的伪EBNF
<line>               ::= <ws>? <identifier> <ws>? '=' <nonwhitespace> <ws>?
<ws>                 ::= (' ' | '\t' | {other whitespace characters})+
<identifier>         ::= <identifier-head> <identifier-tail>
<identifier-head>    ::= <letter> | '_'    
<identifier-tail>    ::= (<letter> | <digit> | '_')*
<letter>             ::= ('A'..'Z') | ('a'..'z')
<digit>              ::= '0'..'9'
<nonwhitespace>      ::= ___________

如何在EBNF中定义非空白(一个或多个不是空格的字符)?

对于熟悉Java parboiled库的人,如何实现定义非空白的规则?

2 个答案:

答案 0 :(得分:5)

您仍然坚持使用词法生成器的约定来指定字符范围和字符范围操作。

许多词法分析器生成器接受十六进制值(类似于0x)来表示字符,因此您可以编写:

 '0'..'9'
 0x30..\0x39

表示数字。

对于非空白,您需要知道您正在使用哪个字符集。对于7位ASCII,非空白在概念上是所有打印字符:

0x21..\0x7E

对于ISO8859-1:

( 0x21..\0x7E | 0x80-0xFF )

你可以自己决定0x80以上的字符代码是否为空格(空格是不间断的空格?)。您还可以决定控制字符0x0..0x1F的状态。标签(0x9)是一个空白字符? CR 0xD和LF 0xA怎么样? ETB控制字符怎么样?

Unicode更难,因为它是一个巨大的集合,你的列表变得庞大而混乱。 C'est la vie 。我们的DMS Software Reengineering Toolkit用于构建各种语言的解析器,并且必须支持ASCII的词法分析器,许多z的Unicode和ISO8859-z。而不是编写复杂的“加法”正则表达式范围,DMS允许减法正则表达式,因此我们可以写:

 <UniCodeLegalCharacters>-<UniCodeWhiteSpace>

更容易理解并在第一次尝试时正确。

答案 1 :(得分:2)

在EBNF中,我只是将非空白定义为任何不是空格的字符:

nonwhitespace ::= anycharacter - whitespace

这要求你有一个'anycharacter'文字定义了整个可能的符号范围,并明确定义了哪些字符是空格。

在Parboiled中,您可以使用TestNotANY规则执行此操作,例如 nonwhitespace将被定义为与WhiteSpace()规则不匹配的任何字符:

Sequence( TestNot(WhiteSpace()) , ANY )