样本

Wave库包含几个演示如何使用不同功能的示例。本节将介绍这些示例及其主要特点。

quick_start 示例

quick_start示例演示了使用Wave预处理器库的最小化方法。它只是打开作为第一个命令行参数提供的文件,假定没有其他包含路径或宏定义,然后对其进行预处理,并输出从给定输入文件中生成的标记的文本表示。此示例可用于了解Wave,因为它不包含更复杂示例中暴露的所有潜在的附加复杂性。

lexed_tokens 示例

lexed_tokens示例演示了在不使用预处理器的情况下,使用 Wave 的 C++ 词法分析组件的最小化方法。它打开作为第一个命令行参数指定的输入文件,并打印出词法分析器返回的标记内容。

cpp_tokens 示例

cpp_tokens示例转储由Wave库提供的迭代器返回的标记中包含的信息。它展示了如何将Wave库与自定义词法分析器和自定义标记类型结合使用。此示例中使用的词法分析器是SLex [5] 基础的,即它在运行时(启动时)以标记定义(正则表达式)进行馈送,并生成一个结果 DFA 表。此表用于标记识别,并在之后保存到磁盘以避免下次程序启动时进行表生成过程。保存 DFA 表的文件名为wave_slex_lexer.dfa.

与默认的SLexRe2C[3] 生成的词法分析器相比,基于 的词法分析器的一个主要优点是,它不仅提供识别特定标记的行信息,还提供相关的列位置。否则,基于SLex的词法分析器在功能上与基于[3] 生成的词法分析器相比,基于的词法分析器完全兼容,也就是说,如果您还需要从预处理中获取列信息,您可以始终将应用程序切换到使用它。

由于此示例不支持其他命令行参数,因此它无法很好地处理与检查的输入文件不在同一目录中的包含文件。命令行语法非常直接。

    cpp_tokens input_file

list_includes 示例

list_includes示例演示了如何使用Wave库为特定输入文件生成包含文件依赖列表。它完全依赖于默认的库配置。此示例的命令行语法如下所示:

    Usage: list_includes [options] file ...:
        -h [ --help ]        : print out program usage (this message)
        -v [ --version ]     : print the version number
        -I [ --path ] dir    : specify additional include directory
        -S [ --syspath ] dir : specify additional system include directory

但请注意,此示例只会输出对预处理器可见的包含文件名称,即给定以下代码片段,在预处理期间只有两个包含文件指令中的一个会被触发,因此只有相应的文件名会被list_includes示例报告。

    #if defined(INCLUDE_FILE_A)
    #  include "file_a.h" 
    #else
    #  include "file_b.h"
    #endif

advanced_hooks 示例

advanced_hooks示例基于上面提到的quick_start示例。它展示了如何使用Wave库的高级预处理钩子 advanced preprocessing hooks,以便在输出中不仅获得已评估条件块的预处理标记,还可以获得在未评估条件块中识别的标记。为了使生成的标记流可用于进一步处理,未评估条件块中的标记被注释掉了。

以下是advanced_hooks示例执行情况的小示例。考虑以下输入

    #define TEST 1
    #if defined(TEST)
    "TEST was defined: " TEST
    #else
    "TEST was not defined!"
    #endif

这将产生如下输出

    //"#if defined(TEST)
    "TEST was defined: " 1
    //"#else
    //"TEST was not defined!"
    //"#endif

正如您所看到的,示例应用程序也以注释掉的方式打印出条件指令。

wave 示例

由于其通用性,wave示例不位于库的示例目录中,而是位于 Boost 的工具目录中。wave 示例可用作任何其他 C++ 编译器之上的功能齐全的预处理器可执行文件。它输出从给定输入文件生成的预处理标记的文本表示。在此处有更详细的描述 here

waveidl 示例

的主要目的是waveidl示例,它展示了如何将完全独立的词法分析器类型与Wave库的默认标记类型结合使用。此示例中使用的词法分析器用于基于 IDL 语言的预处理器。它也基于[3] 生成的词法分析器相比,基于工具,但识别的标记集与Wave库中包含的默认 C++ 词法分析器不同。因此,此词法分析器不识别任何关键字(除了trueandfalse,这些关键字是预处理器本身需要的)。这是因为存在不同的 IDL 语言,其中一种语言的标识符可能是其他语言的关键字。这当然意味着将关键字识别推迟到预处理之后,但允许将Wave用于所有 IDL 派生。

只有在Wave库可以用来编写 IDL 预处理器,因为两种语言的标记集非常相似。要由waveidlIDL 语言预处理器识别的标记几乎是完整 C++ 标记集的子集。

此示例可用的命令行语法如下所示。

  Usage: waveidl [options] [@config-file(s)] file:


    Options allowed on the command line only:
      -h [ --help ]           : print out program usage (this message)
      -v [ --version ]        : print the version number
      -c [ --copyright ]      : print out the copyright statement
      --config-file filepath  : specify a config file (alternatively: @filepath)

        
    Options allowed additionally in a config file:
      -o [ --output ] path    : specify a file to use for output instead of stdout
      -I [ --include ] path   : specify an additional include directory
      -S [ --sysinclude ] syspath : specify an additional system include directory
      -D [ --define ] macro[=[value]] : specify a macro to define
      -P [ --predefine ] macro[=[value]] : specify a macro to predefine
      -U [ --undefine ] macro : specify a macro to undefine

hannibal 示例

hannibal示例演示了如何基于Wave库构建 spirit 语法。它最初由 Danny Havenith 编写并贡献给Wave库(请参阅他相关的网页 here)。此示例的语法使用Wave作为其预处理器。它实现了《C++ 程序设计语言第三版》中大约 250 条语法规则中的 120 条。这 120 条规则允许解析 C++ 源文件以获取所有类型信息和声明。实际上,此语法可以解析几乎任何内容,它可以解析 C++ 声明,包括类和模板定义,但会跳过函数体。如果配置得当,程序将输出生成的解析树的 XML 转储。

它可能是用于逆向工程(如某些 UML 建模工具)的语法的良好起点。或者,如果您需要一个能为您提供文件中所有模板和类及其成员列表的语法,还可以用于其他任何用途。

check_macro_naming 示例

check_macro_naming示例演示了如何使用 context hooks 来理解宏如何在代码库中定义。一些项目(例如 Boost 本身)对宏的名称有约定。此示例将递归地搜索一个目录,查找头文件并在每个文件中搜索宏定义。任何不符合提供的约定(默认为^BOOST_.*)的宏都会被报告,并附有作为包含保护的注释。用户还可以指定任意数量的目录来忽略。

命令行语法

Usage: check_macro_naming [options] directory:
  -h [ --help ]            print out options
  --match arg (=^BOOST_.*) pattern defined macros must match
  --exclude arg            subdirectory to skip

使用示例

$ check_macro_naming --exclude ./test/testwave/testfiles include
CPP_CONTEXT_HPP_907485E2_6649_4A87_911B_7F7225F3E5B8_INCLUDED include/boost/wave/cpp_context.hpp (guard)
WHITESPACE_HANDLING_HPP_INCLUDED include/boost/wave/whitespace_handling.hpp (guard)
...
TRACE_CPP_TIME_CONVERSION include/boost/wave/util/time_conversion_helper.hpp
spirit_append_actor include/boost/wave/util/time_conversion_helper.hpp
spirit_assign_actor include/boost/wave/util/time_conversion_helper.hpp

custom_directives 示例

custom_directives示例演示了如何通过重写 found_unknown_directive 钩子来定义自己的指令,以添加#versionand#extension指令(来自 GLSL)。

emit_custom_line_directives 示例

emit_custom_line_directives示例演示了如何使用 emit_line_directive 预处理钩子来定制任何生成的 #line 指令的格式。该示例将发出与 gcc 生成的兼容格式的 #line 指令。

    # <lineno> <rel_file_name>

preprocess_pragma_output 示例

preprocess_pragma_output示例演示了如何使用 interpret_pragma 钩子来安装自定义 pragma 处理代码。具体来说,它定义了一个新的#pragma wave pp(),它解释当前预处理器上下文中的一个字符串。示例输入使用此机制从传递给pp.

的引号字符串中定义新的宏。

real_positions 示例real_positions

,方法是通过修正返回标记中的位置,使它们看起来是连续的(忽略宏定义中的位置)。

token_statistics 示例

token_statistics示例收集预处理输入中每种标记类型的计数并进行报告。它演示了