如何检测部分未完成的令牌并加入从两个后续输入部分获得的部分?

时间:2016-03-27 01:27:43

标签: flex-lexer lex lexer

我正在编写玩具终端,我使用Flex来解析我从tty获得的普通文本和控制序列。 Cocoa机制的一个细节是它从tty读取1024字节的块,这样我的.lex文件中描述的任何令牌在任何时候都可以分成两部分:令牌的某些字节是第一个1024块的最后一个字节,剩余字节是下一个1024字节块的第一个字节。

所以我需要以某种方式:

  1. 首先检测这种情况:当一个令牌被分成两个1024字节的块时。
  2. 记住令牌的第一部分
  3. 当第二个1024块到达时,以某种方式将第一部分放在第二块之前恢复第一部分。
  4. 我是Flex的新手,所以我正在寻找一种正确的方法来实现这一目标。

    我已创建dumb simple lexer来协助此讨论。

    关于这个演示的问题是:

    我怎样才能发现最后一个" FO" (未完成" FOO")令牌实际上是一个未完成的令牌,它不是我的语法的例外,而只需要它的" O"从下一个输入块?

2 个答案:

答案 0 :(得分:1)

你应该让flex进行阅读。它旨在以这种方式工作;它将完成所有必要的缓冲,包括令牌在两个(或更多)输入缓冲区之间分割的情况。

如果你不能简单地使用标准fread函数从stdin读取,那么你可以通过重新定义宏YY_INPUT来重新定义flex生成的解析器输入的方式。有关此宏的说明,请参阅"Generated Parser" chapter of the flex manual

答案 1 :(得分:0)

我已经接受@ rici的答案是正确的,因为它给了我关于重新定义宏YY_INPUT的重要提示。

在这个答案中,我只想分享像我这样的新手的一些细节。

我使用How to make YY_INPUT point to a string rather than stdin in Lex & Yacc (Solaris)作为自定义YY_INPUT的示例,这使我的人工示例与部分令牌一起正常工作。

要使Flex与部分​​标记一起正常工作,输入不应包含'\ 0'符号,即扫描过程应为“无穷无尽”。以下是重新定义YY_INPUT的方法:

int readInputForLexer(char *buffer, int *numBytesRead, int maxBytesToRead) {
    static int Flip = 0;

    if ((Flip++ % 2) == 0) {
        strcpy(buffer, "FOO F");

        *numBytesRead = 5; // IMPORTANT: this is 5, not 6, to cut off \0
    } else {
        strcpy(buffer, "OO FOO");
        *numBytesRead = 6; // IMPORTANT: this is 6, not 7, to cut off \0
    }

    return 0;
}

在此示例中,部分令牌F-OO由Flex粘贴到正确的FOO中:FOO。

正如@rici在评论中指出的那样,停止扫描的正确方法是设置:*numBytesRead = 0

另见@rici关于类似SO问题的另一个答案:Flex, continuous scanning stream (from socket). Did I miss something using yywrap()?

有关详细信息,请参阅my example