【问题标题】:How to handle x*, x+, or x? regex-like operators in an LR parser?如何处理 x*、x+ 或 x? LR解析器中的类似正则表达式的运算符?
【发布时间】:2015-04-26 03:57:52
【问题描述】:

我过去已经实现了递归下降和类似 PEG 的解析器,您可以在其中执行以下操作:

Path -> Segment+
Segment -> Slash Name
Segment -> /
Name -> /\w+/
Slash -> /
  • 其中Segment+ 表示“匹配一个或多个Segment
  • 还有一个普通的旧正则表达式,用于将一个或多个单词字符与\w+ 匹配

您通常如何使用 LR 语法/解析器完成同样的事情?我见过的所有LR解析器的例子都很基础,比如解析1 + 2 * 3,或者(())(),其中的模式很简单,似乎不涉及“一个或多个”功能(或零个或多个)使用*,或可选使用?)。你通常如何在 LR 解析器中做到这一点?

或者 LR 解析首先需要词法分析阶段(即 LR 解析器需要终端和非终端“令牌”)。希望有一种方法可以在没有这样两个阶段的情况下进行 LR 解析。 LR 解析器的定义谈到了我一直在阅读的书籍/网站中的“输入字符”,但随后您会不经意/巧妙地看到如下一行:

语法的终结符号是词法扫描器在输入流中找到的多字符符号或“标记”。

就像什么,扫描仪是从哪里来的。

【问题讨论】:

    标签: regex parsing context-free-grammar parser-generator lr


    【解决方案1】:

    您当然可以为一种语言编写无扫描仪语法,但在大多数情况下它不会是 LR(1),因为当标记是单个标记时,前瞻标记的 1 个标记并不多字符。

    通常,LALR(1) 解析器生成器(如 bison)与扫描器生成器(如 flex)结合使用。

    【讨论】:

      【解决方案2】:

      每当您有一个解析器在令牌流上运行时,总会有一个问题是什么产生了令牌流。对于大多数解析器生成器,标记的语法规范和词法规范是分开的,主要是因为解析器生成器和词法生成器的操作方式不同。

      将正则表达式运算符添加到“语法”很方便。但是它们并没有扩展上下文无关语法的力量。

      在语法中使用类似正则表达式的运算符有 3 种选择。

      1) 在整个语法中一致地在字符级别使用它们。如果您这样做,您的解析器将使用作为单个字符的标记进行操作。这对于大多数解析器生成器来说可能效果不佳,因为大多数解析器生成器的决定仅基于下一个输入流标记,在这种情况下,是单个字符。要完成这项工作,您要么需要一个回溯解析器,要么需要一个通过替代解析空间尝试多条路径的解析器; LR 和 LL 解析器不这样做。如果您不介意 GLR 基于每个字符的额外开销,则可以使用无扫描仪 GLR 解析器。 (另外,如果在字符级别操作,您可能已经明确指定了空格和注释语法)。

      2) 将它们用作单个令牌字符序列的规范(如 OP 的“名称 -> /w+/”)。在这种形式中,您最终要做的是编写与语法集成的词汇标记规范。然后可以将语法处理为两部分:词汇规范和更传统的 BNF。这个想法与许多词法分析器和解析器生成器兼容;它仍然没有改变表现力。

      3) 仅在语法元素上使用正则表达式运算符。这些都是 很容易转化为常规的 BNF 语法规则:

        Path -> Segment +
      

      相当于:

        Path -> Segment 
        Path -> Path Segment
      

      经过此类转换后,结果与大多数解析器生成器兼容。这使得如何指定语法标记的词法句法保持开放。

      您可以实现结合 1) 和 2) 的混合方案,这似乎是 OP 所做的。

      【讨论】:

        【解决方案3】:

        在一些 LR 解析器生成器的 BNF 语法中允许使用正则表达式。 LRSTAR 9.1 允许使用正则表达式。 Yacc 和 Bison 不允许在 BNF 语法中使用正则表达式。

        词法标记应在词法文法中指定,与 BNF(解析器)文法分开。在解析器看到它们之前已经定义了标记,这使解析器的工作变得更加轻松。

        PEG 不会强迫您将词汇符号与语法符号分开,从而产生一些严重的问题,例如在某些情况下需要无限前瞻。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-17
          • 1970-01-01
          • 2010-12-04
          • 1970-01-01
          • 2016-08-30
          • 1970-01-01
          相关资源
          最近更新 更多