【问题标题】:EBNF / parboiled: how to translate regexp into PEG?EBNF / parboiled:如何将正则表达式翻译成 PEG?
【发布时间】:2011-03-03 18:06:22
【问题描述】:

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

【问题讨论】:

  • 等等,重复量词在哪里?据我所知,语法只能是一个字母等
  • 见identifier-tail
  • 呃,好吧,我试图将它作为一个 EBNF 语法来阅读,其中 * 本来应该在括号之前......

标签: java parsing ebnf parboiled


【解决方案1】:

您被词法生成器用于指定字符范围和字符范围操作的约定所困。

许多词法分析器生成器接受十六进制值(类似于 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 的 ISO8859-z 和 Unicode。 DMS 允许减法正则表达式,而不是编写复杂的“加法”正则表达式范围,因此我们可以这样写:

 <UniCodeLegalCharacters>-<UniCodeWhiteSpace>

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

【讨论】:

    【解决方案2】:

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

    nonwhitespace ::= anycharacter - whitespace
    

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

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

    Sequence( TestNot(WhiteSpace()) , ANY )
    

    【讨论】:

      猜你喜欢
      • 2015-04-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多