3

这是一个特定于 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 库的人,您如何实现定义非空白的规则?

4

2 回答 2

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 更难,因为它是一个庞大的集合,而且你的列表变得又大又乱。 生活吧。我们的DMS Software Reengineering Toolkit用于为多种语言构建解析器,并且必须支持 ASCII 词法分析器、许多 z 的 ISO8859-z 和 Unicode。DMS 允许减法正则表达式,而不是编写复杂的“加法”正则表达式范围,因此我们可以编写:

 <UniCodeLegalCharacters>-<UniCodeWhiteSpace>

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

于 2011-03-03T19:14:23.697 回答
2

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

nonwhitespace ::= anycharacter - whitespace

这要求您有一个定义整个可能符号范围的“任意字符”文字,并明确定义哪些字符是空格。

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

Sequence( TestNot(WhiteSpace()) , ANY )
于 2013-10-04T09:51:58.650 回答