行尾 lex

End of line lex

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

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

输入文件是:

ABC

没有空格或任何其他不可见的符号。所以我希望输出是 QWERTY,但是我得到的是:

ABC

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

ABC$

所以,如果 $ 不是特殊符号,那么它将被解析为普通符号,输出将是 QWERTY。这不会发生,输出是:

ABC$

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

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

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

正如@sepp2k 在评论中建议的那样,如果输入文件恰好使用 Windows 行结尾(由序列 \r\n 组成),模式也不会匹配,除非生成的 flex 文件是为 Windows 编译的。因此,如果您在 Unix 环境中的 Windows 和 运行 上创建了 flex-generated 扫描程序,\r 也会导致模式无法匹配。在这种情况下,您可以使用 (f)lex 的尾随上下文运算符:

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

有关尾随上下文运算符的完整说明,请参阅 flex documentation for patterns。 (在该页面上搜索 "trailing context";它大约在一半处。)$ 完全 等同于 /\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 后面有 non-newline 个字符,第一个模式就会匹配。 (. 匹配换行符以外的任何字符。有关详细信息,请参阅上面的 link。)如果您还需要使用 Windows 行结尾,则需要修改尾随上下文在第一个模式中。