行尾 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 行结尾,则需要修改尾随上下文在第一个模式中。
我正在使用 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 行结尾,则需要修改尾随上下文在第一个模式中。