我正在使用lex和yacc编写用于汇编的解释器。问题是我需要解析一个严格位于文件末尾的单词。我了解到有一个锚点$
,可以为您提供帮助。但是它没有按我预期的那样工作。我已经在lex文件中写了这个:
ABC$ {printf("QWERTY\n");}
输入文件为:
ABC
没有空格或任何其他不可见的符号。因此,我期望outputput为QWERTY,但是我得到的是:
ABC
我猜这意味着程序无法解析它。然后我想,$
可能是lex中的常规符号,所以我将输入文件更改为:
ABC$
因此,如果$
不是特殊符号,则它将被解析为普通符号,并且输出将为QWERTY。不会发生,输出为:
ABC$
问题是lex中的$
是普通符号还是特殊符号。
答案 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行尾,则需要在第一个模式中修改尾随上下文。