Introduction 簡介

The Wave C++ preprocessor library is a Standards conformant implementation of the mandated C99/C++ preprocessor functionality packed behind a simple to use interface, which integrates well with the well known idioms of the Standard Template Library (STL).
Wave C++預處理器庫是一個符合標準的委託型C99/C++預處理器實現,其功能被包裝在一個易於使用的接口之後,該接口與著名的標準模板庫(STL)慣用法集成得很好。

The Wave C++ preprocessor is not a monolithic application, it's rather a modular library, which exposes mainly a context object and an iterator interface. The context object helps to configure the actual preprocessing process (as search path's, predefined macros, etc.). The exposed iterators are generated by this context object too. Iterating over the sequence defined by the two iterators will return the preprocessed tokens, which are built on the fly from the given input stream.
Wave C++預處理器不是一個單模塊的應用,而是一個模板化的庫,它暴露的主要是一個上下文對像和一個迭代器接口。上下文對像用於配置實際的預處理過程(如查找 路徑、預定義宏,等等)。暴露的迭代器也是由這個上下文對像生成的。對由兩個迭代器定義的序列進行遍歷將返回預處理單詞,這些單詞是從給定的輸入流就地創 建的。

The C++ preprocessor iterator itself is fed by a C++ lexer iterator, which implements an abstract interface. The C++ lexers packaged with the Wave library may be used standalone, too, and are not tied to the C++ preprocessor iterator at all.
C++預處理迭代器本身就是依靠一個C++ lexer 迭代器,後者實現了一個抽像接口。與Wave庫一起打包的C++ lexer也可以單獨使用,並沒有與C++預處理迭代器捆綁在一起。

To make the C++ preprocessing library modular, the C++ lexer is held completely separate and independent from the preprocessor. To prove this concept, two different, but functionally identical C++ lexers were implemented. Additionally there is implemented a IDL lexer, which allows to use the preprocessor library as the lexing component of a IDL oriented tool. All these lexers implement the mentioned abstract interface, so that the C++ preprocessor iterator may be used with all of them. The abstraction of the lexer from the preprocessor iterator library was done to allow plugging in different lexers without the need to reimplement the preprocessor. This will allow for benchmarking and specific fine tuning of the process of preprocessing itself.
要 使得C++預處理器庫模板化,C++ lexer必須與預處理器完全分開並獨立。為了證實這一概念,我們實現了兩個不同但功能一樣的C++ lexer。此外還實現了一個IDL lexer,允許將預處理器庫用作某個面向IDL的工具的lexing組件。所有這些lexer都實現前述的抽像接口,這樣C++預處理迭代器就可以與所 有這些lexer共用。來自於這個預處理迭代器庫的lexer抽像實現允許插入不同的lexer而無須重新實現預處理器。這樣就可以對預處理過程本身進行 基準測試和專門的調優。

The first of these C++ lexers is implemented with the help of the well known Re2C [3] tool, which generates C code from given regular expressions. The lexers generated with Re2C are known to be very fast, because they are not table driven but directly code the token building logic (very similar to hand coded lexers).
第一個C++ lexer是借助著名的Re2C [3]工具實現的,它由給定的正則表達式生成C代碼。這個用Re2C生成的lexer速度非常快,因為它們不是表驅動的,而是直接對單詞構建邏輯進行編碼(與手工編碼的lexer非常相似)。

The second of these C++ lexers is built around a table driven lexer, where the DFA tables (discrete finite automaton tables) are generated from regular expressions with the help of a Spirit-based lexer generating framework named Slex [5]. The Slex is fed during runtime with the token definitions (regular expressions) and generates the resulting DFA table. This table is used to combine the input characters into corresponding lexemes (tokens). The generated DFA table can be saved to disk to avoid the generation process at program startup.
第二個C++ lexer則是圍繞一個表驅動lexer來構建的,其中的DFA表(離散有限自動表)是借助一個名為Slex [5]的基於Spirit的lexer生成框架,由正則表達式生成的。Slex在運行期被傳入相應的單詞定義(正則表達式),並生成DFA表。該表用於將輸入的字符組合成相應的單詞。生成的DFA表可以保存到磁盤中,以避免在程序啟動時的表生成過程。

Wave may be used for preprocessing IDL files too, since the token set needed for the IDL language is very similar to the C++ token set. That's the reason, why the Wave preprocessor library contains also an IDL lexer. The IDL lexer is also based on the Re2C tool, but recognizes a different set of tokens. So this lexer does not recognize any keywords (except true and false, which are needed by the preprocessor itself). This is needed because there exist different IDL language flavours, where identifiers of one flavour may be keywords of others - Ok, this requires postponement of keyword identification until after the preprocessing, but allows to use Wave for all of the IDL derivatives.
Wave還可以用於預處理IDL文件,因為IDL語言所用的單詞集與C++單詞集非常相似。這正是為什麼Wave預處理器庫還包含有一個IDL lexer的原因。這個IDL lexer也是基於Re2C工具的,不過識別的是另一個單詞集。因此,這個lexer不識別任何關鍵字(除了truefalse,因為預處理器本身需要它們)。這是必須的,因為存在不同的IDL語言風格,某一種風格的標識符可能是另一種風格的關鍵字 - 是的,這需要將關鍵字的識別延遲到預處理之後,不過這樣可以允許將Wave用於所有的IDL衍生版本。

It is possible to build other C++ lexers if needed. Currently there are plans to adapt the Spirit C++ lexer example cpplexer [6], which is completely based on static Spirit[4] grammars.
如果需要,還可以構建其它的C++ lexer。目前已有計劃移植Spirit C++ lexer示例cpplexer [6],它是完全基於靜態Spirit[4]語法的。

Both of the included lexers and the library itself are able to act in a C99 compliant mode. In this mode the lexers reject C++-only tokens ('::', '->*', '.*' and the alternate keywords such as 'and', etc.). The preprocessor additionally handles placemarkers (empty macro arguments) and variadics (macros with variable parameter counts). As an extension to the C++ Standard, the library can be enabled to handle placemarkers and variadics in C++ mode too.
內含的lexer和庫本身都可以按符合C99的模式運作。在這種模式下,lexer將拒絕只用於C++的單詞('::', '->*', '.*' 以及其它關鍵字如'and'等等)。預處理器還可以處理placemarkers(空的宏參數)和variadics(帶可變數量參數的宏)。作為C++標準的擴展,該庫在C++模式下也可以被設置為處理placemarkers和variadics。