我正在编写玩具终端,我使用Flex来解析我从tty获得的普通文本和控制序列。 Cocoa机制的一个细节是它从tty读取1024字节的块,这样我的.lex文件中描述的任何令牌在任何时候都可以分成两部分:令牌的某些字节是第一个1024块的最后一个字节,剩余字节是下一个1024字节块的第一个字节。
所以我需要以某种方式:
我是Flex的新手,所以我正在寻找一种正确的方法来实现这一目标。
我已创建dumb simple lexer来协助此讨论。
关于这个演示的问题是:
我怎样才能发现最后一个" FO" (未完成" FOO")令牌实际上是一个未完成的令牌,它不是我的语法的例外,而只需要它的" O"从下一个输入块?
答案 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。