首页 > 解决方案 > 展开 flex 检测到的转义序列

问题描述

在我的scanner.lex 文件中,我有这个:

{Some rule that matches strings} return STRING; //STRING is enum

在我的 c++ 文件中,我有这个:

if (yylex == STRING) {
    cout << "STRING: " << yytext << endl;

显然有一些逻辑可以从标准输入中获取输入。现在,如果这个程序得到输入“Hello\nWorld”,我的输出是"STRING: Hello\nWorld",而我希望我的输出是:

Hello
World

其他转义字符也是如此,例如\", \0, \x<hex_number>, \t, \\... 但我不知道如何实现这一点。我什至不确定这是否是一个弹性问题,或者我是否可以仅使用 c++ 工具来解决这个问题......

我怎样才能完成这项工作?

标签: c++flex-lexer

解决方案


正如@Some 程序员花花公子在评论中提到的那样,Flex 文档中有一个如何使用开始条件来执行此操作的示例。该示例将转义规则置于单独的开始条件中;每个规则都是通过将未转义的文本附加到缓冲区来实现的。这就是通常的做法。

当然,您可能会找到一个对 C 样式转义字符串进行转义的外部库,您可以在 flex 返回的字符串上调用它。但这会比 Flex 手册中建议的方法更慢且更不灵活:更慢是因为它需要对字符串进行第二次扫描,而且灵活性更低,因为库可能对要处理的转义有自己的想法。

如果您使用 C++,您可能会发现修改该示例以使用std::string缓冲区而不是任意固定大小的字符数组更优雅。您可以使用 C++ 编译 flex 生成的扫描仪,因此在您的扫描仪代码中使用 C++ 标准库对象没有问题。

根据您管理的各种语义值类型,您可能需要修改yylex原型以使用额外的引用参数或更结构化的返回类型,以便将令牌值返回给调用者。请注意,虽然可以yytext在下一次调用之前使用yylex它,但它通常不被认为是好的样式,因为它不适用于大多数解析器:通常,解析器需要能够提前查看一个或多个标记,因此yytext很可能在解析器需要它的值时被覆盖。flex 手册记录了用于修改yylex()原型的宏钩子。


推荐阅读