行尾lex

时间:2019-05-12 19:34:43

标签: flex-lexer lex

我正在使用lex和yacc编写用于汇编的解释器。问题是我需要解析一个严格位于文件末尾的单词。我了解到有一个锚点$,可以为您提供帮助。但是它没有按我预期的那样工作。我已经在lex文件中写了这个:

ABC$    {printf("QWERTY\n");}

输入文件为:

ABC

没有空格或任何其他不可见的符号。因此,我期望outputput为QWERTY,但是我得到的是:

ABC

我猜这意味着程序无法解析它。然后我想,$可能是lex中的常规符号,所以我将输入文件更改为:

ABC$

因此,如果$不是特殊符号,则它将被解析为普通符号,并且输出将为QWERTY。不会发生,输出为:

ABC$

问题是lex中的$是普通符号还是特殊符号。

1 个答案:

答案 0 :(得分:2)

在(f)lex中,$匹配零个字符,后跟换行符

与许多正则表达式库不同,在这些正则表达式库中,$将在输入末尾匹配。因此,如果您的文件末尾没有换行符(如您的问题所示)(假设您认为换行符是不可见的字符),则该文件将不匹配。

正如@ sepp2k在注释中建议的那样,如果输入文件恰好使用Windows行尾(由序列\r\n组成),则该模式也将不匹配,除非生成的flex文件针对视窗。因此,如果您在Windows上创建文件并在Unix环境中运行flex生成的扫描器,则\r也会导致模式匹配失败。在这种情况下,您可以使用(f)lex的尾随上下文运算符:

ABC/\r?\n   { puts("Matched ABC at the end of a line"); }

有关尾随上下文运算符的完整说明,请参见flex documentation for patterns。 (在该页面上搜索“跟踪上下文”;它大约在中间。)$ 完全等同于/\n

在文件的末尾仍然与ABC不匹配。在文件末尾匹配字符串有些棘手,但是如果可以识别出文件末尾以外的字符串,可以用两种模式来完成,从而触发不同的操作:

ABC/.    { /* Do nothing. This ABC is not at the end of a line or the file */ }
ABC      { puts("ABC recognised at the end of a line"); }

之所以可行,是因为只要ABC之后有一些非换行符,第一个模式就会匹配。 (.匹配换行符以外的任何字符。有关详细信息,请参见上面的链接。)如果还需要使用Windows行尾,则需要在第一个模式中修改尾随上下文。