表驱动lexing需要多少缓冲?

时间:2015-03-04 00:52:19

标签: rust lex lexical-analysis dfa

我正在Rust中编写一个POSIX shell实现。这带来了一些相当尴尬的要求:

  • 必须逐行读取输入。如果输入来自不可搜索的源,则意味着必须一次读取一个字节的输入。
  • 反斜杠 - 换行符,如果不加引号,则为续行。它不是一个标记分隔符,理想情况下应该在lexing之前处理。

如果词法分析器一次读取一个字符并允许规则设置可以由词法分析器的字符源查询的内部状态,则可以轻松处理这两个要求(Rust不允许C解决方案在全局变量中填充状态)。我现在的词霸就是这么做的。然而,它是398行高度重复的代码,包括一些(不充分)测试。此代码需要自动生成。

自动生成的词法分析器通常使用基于有限自动机的表驱动设计。我对此并不十分熟悉,并且想知道这种设计是否具有前瞻性或通常不使用。如果通常不使用前瞻,那么我可以修改现有的词法分析器来做我想要的事情;否则,我可能会遇到手写代码。

1 个答案:

答案 0 :(得分:2)

这可能是一个过于宽泛的问题,或者产生包含太多意见的答案,而不是good attribute of an SO question。它非常关注一个问题,询问现有词法生成器算法的实现,有限自动机的编程,shell语言的词法要求以及Rust程序的特性以及可能还有一些其他主题。

首先,让我们来处理有关工具生成词法分析器功能的问题。让我们考虑一下最常用的flex GNU词法分析器生成器。答案是;它可以为你建立一个符合你想要的词法分析器。它足够灵活,包含足够的不同功能来完成工作(与其他类似工具一样)。它会变得简单直接吗?不必要。该工具使您可以使用内置读取和有限状态自动机,但您可以提供自己的输入例程,编写自己的状态机,甚至可以处理自编代码中的困难位(在 C < / strong>或C ++)。有很多关于如何在手册,教程网站,教程视频,教科书和questions here on SO中实现这一目标的示例。

在Rust编码时,这有何帮助,因为flex会在 C 或C ++中生成代码?我们需要一个基于Rust的词法分析器。一旦可以进行文献检索并查看可用的内容。维基百科适用于列表,并且有list of available parser and lexer generator tools。但是,这些都不会产生Rust。 Rust中有这样的工具,但是:

由于这些都是正在进行的实验性工作,因此您需要自己进行评估。

另一种方法是使用自己的开源工具版本(如flex)来使用Rust。这可以通过两种方式完成:

  1. 您可以对flex的输出进行后处理,将 C 代码转换为Rust代码,然后进行编译。
  2. 您可以修改工具的代码以生成Rust而不是 C 。 (它不需要用Rust编写,以达到你想要的目的。)
  3. 这些方法已多次完成,以便能够定位其他新语言。结果是a whole raft of compiler generator tools for a myriad of languages

    接下来的问题是手写lexer代码的大小和性质。 There are standardised and recognised ways of programming finite state automata in any language. Experienced programmers would should know the pattern

    while ( NOT <<EOF>> ) {
      switch ( next_symbol() ) {
    
         case state_symbol[1]: 
                  ....
                 break;
    
          case state_symbol[2]:
                  ....
                  break;
    
           default:
                 error(diagnostic);
      }
    }
    

    甚至可以在功能上完成:

    action[state_symbol[next_symbol()]];
    

    有可能手写一个非常紧凑和高效的常规语言解析FSA来做lexing,但这是语言和算法的经验问题。

    你的广泛和不精确的问题导致了一个广泛而不精确的答案:是的,一切皆有可能,它不依赖于缓冲和回溯。