Flex C++ - #ifdef inside flex 块
Flex C++ - #ifdef inside flex block
我想在预处理器中定义常量,它仅在定义时启动匹配某些模式。是否有可能这样做,或者有其他方法如何处理这个问题?
即在 C:
中删除单行注释的简化版本
%{
#define COMMENT
%}
%%
#ifdef COMMENT
[\/][\/].*$ ;
#endif
[1-9][0-9]* printf("It's a number, and it works with and without defining COMMENT");
%%
这个(非常合理的)请求没有很好的解决方案,但有一些可能性。
(F)lex 开始条件
Flex start conditions 使定义一些可选模式变得相当简单,但它们组合得不好。如果您只有一个控制变量,此解决方案将最有效,因为您需要为每个可能的控制变量组合定义一个单独的开始条件。
例如:
%s NO_COMMENTS
%%
<NO_COMMENTS>"//".* ; /* Ignore comments in `NO_COMMENTS mode. */
%s
声明意味着所有未标记的规则也适用于N_COMMENTS
状态;您通常会在示例中看到 %x
(“独占”),但这会迫使您明确标记几乎所有规则。
一旦您以这种方式修改了语法,您就可以 select 适当的规则集 在 运行-time 通过设置词法分析器的状态BEGIN(INITIAL)
或 BEGIN(NO_COMMENTS)
。 (BEGIN
宏仅在 flex 生成的文件中定义,因此您需要导出执行这两个操作之一的函数。)
将 cpp 用作实用程序。
flex 中没有预处理器功能。您可以使用 C 预处理器在将 flex 文件传递给 flex 之前对其进行预处理,但是您必须非常小心地处理您的输入文件:
C 预处理器期望其输入是一系列有效的 C 预处理器标记。由于非常不同的引用规则,许多常见的 flex 模式将不符合这个假设。 (举个简单的例子,识别 C 注释的常见模式包括字符 class [^/*]
,C 预处理器会将其解释为包含 C 注释的开头。)
flex 输入文件可能有许多行是有效的 #include
指令。没有办法避免这些指令被扩展(除了从文件中删除它们)。一旦扩展并合并到源代码中,头文件就不再包含保护,因此您必须告诉 flex 不要从它自己的模板中插入任何 #include
文件。我相信这是可能的,但它会有点脆弱。
C 预处理器可能会扩展看起来像宏调用的内容。
C 预处理器可能不会保留线性空白,从而改变 flex 扫描器定义的含义。
m4 和其他预处理器
使用m4
作为预处理器会更安全,但这当然意味着学习m4
。 (你不需要安装它,因为 flex
已经依赖于它。所以如果你有 flex
你也有 m4
。)你仍然需要非常小心引用序列。 M4
允许您自定义这些序列,因此它比 cpp 更易于管理。但是不要复制将 [[
定义为引号定界符的常见习语;它在正则表达式中很常见。
此外,m4
不会插入 #line
指令,任何重要的使用都会改变输入行的数量,使错误消息更难解释。 (更不用说调试的挑战了。)在这个非常简单的情况下,您可能可以避免这个问题,但问题会再次出现。
您也可以编写自己的简单预处理器,但您仍然需要解决上述问题。
我想在预处理器中定义常量,它仅在定义时启动匹配某些模式。是否有可能这样做,或者有其他方法如何处理这个问题? 即在 C:
中删除单行注释的简化版本%{
#define COMMENT
%}
%%
#ifdef COMMENT
[\/][\/].*$ ;
#endif
[1-9][0-9]* printf("It's a number, and it works with and without defining COMMENT");
%%
这个(非常合理的)请求没有很好的解决方案,但有一些可能性。
(F)lex 开始条件
Flex start conditions 使定义一些可选模式变得相当简单,但它们组合得不好。如果您只有一个控制变量,此解决方案将最有效,因为您需要为每个可能的控制变量组合定义一个单独的开始条件。
例如:
%s NO_COMMENTS
%%
<NO_COMMENTS>"//".* ; /* Ignore comments in `NO_COMMENTS mode. */
%s
声明意味着所有未标记的规则也适用于N_COMMENTS
状态;您通常会在示例中看到 %x
(“独占”),但这会迫使您明确标记几乎所有规则。
一旦您以这种方式修改了语法,您就可以 select 适当的规则集 在 运行-time 通过设置词法分析器的状态BEGIN(INITIAL)
或 BEGIN(NO_COMMENTS)
。 (BEGIN
宏仅在 flex 生成的文件中定义,因此您需要导出执行这两个操作之一的函数。)
将 cpp 用作实用程序。
flex 中没有预处理器功能。您可以使用 C 预处理器在将 flex 文件传递给 flex 之前对其进行预处理,但是您必须非常小心地处理您的输入文件:
C 预处理器期望其输入是一系列有效的 C 预处理器标记。由于非常不同的引用规则,许多常见的 flex 模式将不符合这个假设。 (举个简单的例子,识别 C 注释的常见模式包括字符 class
[^/*]
,C 预处理器会将其解释为包含 C 注释的开头。)flex 输入文件可能有许多行是有效的
#include
指令。没有办法避免这些指令被扩展(除了从文件中删除它们)。一旦扩展并合并到源代码中,头文件就不再包含保护,因此您必须告诉 flex 不要从它自己的模板中插入任何#include
文件。我相信这是可能的,但它会有点脆弱。C 预处理器可能会扩展看起来像宏调用的内容。
C 预处理器可能不会保留线性空白,从而改变 flex 扫描器定义的含义。
m4 和其他预处理器
使用m4
作为预处理器会更安全,但这当然意味着学习m4
。 (你不需要安装它,因为 flex
已经依赖于它。所以如果你有 flex
你也有 m4
。)你仍然需要非常小心引用序列。 M4
允许您自定义这些序列,因此它比 cpp 更易于管理。但是不要复制将 [[
定义为引号定界符的常见习语;它在正则表达式中很常见。
此外,m4
不会插入 #line
指令,任何重要的使用都会改变输入行的数量,使错误消息更难解释。 (更不用说调试的挑战了。)在这个非常简单的情况下,您可能可以避免这个问题,但问题会再次出现。
您也可以编写自己的简单预处理器,但您仍然需要解决上述问题。