Skip to content

Commit 8041d01

Browse files
committed
Provide alternative output for Preprocessor::Process (Issue #7)
1 parent 118b1fe commit 8041d01

File tree

4 files changed

+190
-8
lines changed

4 files changed

+190
-8
lines changed

source/tcppLibrary.hpp

Lines changed: 122 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,26 @@
2222
not be applied to this library, at least for now. There is a list of unimplemented features placed
2323
below
2424
25+
##Configuration
26+
27+
There are list of available options presented below. To enable some option just use #define directive before inclusion library's header file.
28+
Do not forget to provide this definitions in header files to provide access to specific types in case you need to use them.
29+
30+
\code
31+
#define TCPP_SOME_EXAMPLE_CONFIG
32+
//... other configs
33+
#define TCPP_IMPLEMENTATION
34+
#include "tcppLibrary.hpp
35+
\endcode
36+
37+
* TCPP_OUTPUT_TOKENS_EXTENSION_ENABLED: The config determines which approach is used to provide processed output for a user.
38+
Originally Preprocessor::Process returns output data as a std::string's instance. **TokensOutputStream** is returned with Preprocessor::Process
39+
in case of TCPP_OUTPUT_TOKENS_EXTENSION_ENABLED is defined
40+
2541
\todo Implement support of char literals
2642
\todo Improve existing performance for massive input files
2743
\todo Add support of integral literals like L, u, etc
2844
\todo Implement built-in directives like #pragma, #error and others
29-
\todo Provide support of variadic macros
3045
*/
3146

3247
#pragma once
@@ -180,9 +195,37 @@ namespace tcpp
180195
} TToken, *TTokenPtr;
181196

182197

183-
using TTokensSequence = std::vector<TToken>;
198+
using TTokensSequence = std::vector<TToken>;
199+
using TTokensSequenceIter = TTokensSequence::iterator;
200+
using TTokensSequenceConstIter = TTokensSequence::const_iterator;
184201

185202

203+
#ifdef TCPP_OUTPUT_TOKENS_EXTENSION_ENABLED
204+
205+
class TokensOutputStream
206+
{
207+
public:
208+
explicit TokensOutputStream(TTokensSequence tokens) TCPP_NOEXCEPT;
209+
210+
// Methods to provide support of iterating over the sequence using for loop
211+
TTokensSequenceIter begin() TCPP_NOEXCEPT;
212+
TTokensSequenceIter end() TCPP_NOEXCEPT;
213+
TTokensSequenceConstIter begin() const TCPP_NOEXCEPT;
214+
TTokensSequenceConstIter end() const TCPP_NOEXCEPT;
215+
216+
const TToken& GetNextToken() TCPP_NOEXCEPT;
217+
const TToken& PeekNextToken(size_t offset = 1) TCPP_NOEXCEPT;
218+
bool HasNextToken() const TCPP_NOEXCEPT;
219+
220+
const TTokensSequence& GetSequence() const TCPP_NOEXCEPT;
221+
private:
222+
TTokensSequence mTokens{};
223+
private:
224+
TTokensSequenceIter mCurrIt{};
225+
};
226+
227+
#endif
228+
186229
/*!
187230
class Lexer
188231
@@ -340,6 +383,14 @@ namespace tcpp
340383
} TIfStackEntry, *TIfStackEntryPtr;
341384

342385
using TIfStack = std::stack<TIfStackEntry>;
386+
387+
using TPreprocessResult =
388+
#ifdef TCPP_OUTPUT_TOKENS_EXTENSION_ENABLED
389+
TokensOutputStream;
390+
#else
391+
TTokensSequence;
392+
#endif
393+
343394
public:
344395
Preprocessor() TCPP_NOEXCEPT = delete;
345396
Preprocessor(const Preprocessor&) TCPP_NOEXCEPT = delete;
@@ -348,8 +399,8 @@ namespace tcpp
348399

349400
bool AddCustomDirectiveHandler(const std::string& directive, const TDirectiveHandler& handler) TCPP_NOEXCEPT;
350401

351-
TTokensSequence Process() TCPP_NOEXCEPT;
352-
static std::string ToString(const TTokensSequence& tokens) TCPP_NOEXCEPT;
402+
TPreprocessResult Process() TCPP_NOEXCEPT;
403+
static std::string ToString(const TPreprocessResult& tokens) TCPP_NOEXCEPT;
353404

354405
Preprocessor& operator= (const Preprocessor&) TCPP_NOEXCEPT = delete;
355406

@@ -1157,7 +1208,7 @@ namespace tcpp
11571208
}
11581209

11591210

1160-
TTokensSequence Preprocessor::Process() TCPP_NOEXCEPT
1211+
Preprocessor::TPreprocessResult Preprocessor::Process() TCPP_NOEXCEPT
11611212
{
11621213
TCPP_ASSERT(mpLexer);
11631214

@@ -1304,10 +1355,14 @@ namespace tcpp
13041355
}
13051356
}
13061357

1358+
#ifdef TCPP_OUTPUT_TOKENS_EXTENSION_ENABLED
1359+
return TokensOutputStream{ processedTokens };
1360+
#else
13071361
return processedTokens;
1362+
#endif
13081363
}
13091364

1310-
std::string Preprocessor::ToString(const TTokensSequence& tokens) TCPP_NOEXCEPT
1365+
std::string Preprocessor::ToString(const TPreprocessResult& tokens) TCPP_NOEXCEPT
13111366
{
13121367
std::string output = EMPTY_STR_VALUE;
13131368

@@ -2211,5 +2266,66 @@ namespace tcpp
22112266
return !mConditionalBlocksStack.empty() && (mConditionalBlocksStack.top().mShouldBeSkipped || !mConditionalBlocksStack.top().mIsParentBlockActive);
22122267
}
22132268

2269+
2270+
#ifdef TCPP_OUTPUT_TOKENS_EXTENSION_ENABLED
2271+
2272+
TokensOutputStream::TokensOutputStream(TTokensSequence tokens) TCPP_NOEXCEPT
2273+
: mTokens(std::move(tokens)), mCurrIt(mTokens.begin())
2274+
{
2275+
}
2276+
2277+
TTokensSequenceIter TokensOutputStream::begin() TCPP_NOEXCEPT
2278+
{
2279+
return mTokens.begin();
2280+
}
2281+
2282+
TTokensSequenceIter TokensOutputStream::end() TCPP_NOEXCEPT
2283+
{
2284+
return mTokens.end();
2285+
}
2286+
2287+
TTokensSequenceConstIter TokensOutputStream::begin() const TCPP_NOEXCEPT
2288+
{
2289+
return mTokens.cbegin();
2290+
}
2291+
2292+
TTokensSequenceConstIter TokensOutputStream::end() const TCPP_NOEXCEPT
2293+
{
2294+
return mTokens.cend();
2295+
}
2296+
2297+
const TToken& TokensOutputStream::GetNextToken() TCPP_NOEXCEPT
2298+
{
2299+
if (mCurrIt == mTokens.end())
2300+
{
2301+
return mTokens.back();
2302+
}
2303+
2304+
return *mCurrIt++;
2305+
}
2306+
2307+
const TToken& TokensOutputStream::PeekNextToken(size_t offset) TCPP_NOEXCEPT
2308+
{
2309+
TTokensSequenceIter peekIt = mCurrIt + offset;
2310+
if (peekIt == mTokens.end())
2311+
{
2312+
return mTokens.back();
2313+
}
2314+
2315+
return *peekIt;
2316+
}
2317+
2318+
bool TokensOutputStream::HasNextToken() const TCPP_NOEXCEPT
2319+
{
2320+
return mCurrIt != mTokens.end();
2321+
}
2322+
2323+
const TTokensSequence& TokensOutputStream::GetSequence() const TCPP_NOEXCEPT
2324+
{
2325+
return mTokens;
2326+
}
2327+
2328+
#endif
2329+
22142330
#endif
22152331
}

tests/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,14 @@ set(SOURCES
2727
"${CMAKE_CURRENT_SOURCE_DIR}/coreTests.cpp"
2828
"${CMAKE_CURRENT_SOURCE_DIR}/lexerTests.cpp"
2929
"${CMAKE_CURRENT_SOURCE_DIR}/stringInputStreamTests.cpp"
30+
"${CMAKE_CURRENT_SOURCE_DIR}/tokensOutputStreamTests.cpp"
3031
"${CMAKE_CURRENT_SOURCE_DIR}/main.cpp")
3132

3233
source_group("includes" FILES ${HEADERS})
3334
source_group("sources" FILES ${SOURCES})
3435

36+
add_definitions(-DTCPP_OUTPUT_TOKENS_EXTENSION_ENABLED)
37+
3538
if (MSVC) #cl.exe compiler's options
3639

3740
#Debug compiler's options
@@ -42,7 +45,6 @@ if (MSVC) #cl.exe compiler's options
4245
#Release compiler's options
4346
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /std:c++14 /permissive- /GS /GL /analyze- /W3 /Gy /Zc:wchar_t /Zi /O2 /sdl /Zc:inline")
4447
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /fp:precise /D _WINDLL /D _MBCS /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MD /EHsc /nologo /diagnostics:classic")
45-
4648
endif(MSVC)
4749

4850

tests/coreTests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ TEST_CASE("Preprocessor Tests")
3232
Lexer lexer(std::make_unique<StringInputStream>(inputSource));
3333

3434
Preprocessor preprocessor(lexer, { errorCallback });
35-
REQUIRE(!preprocessor.Process().empty());
35+
REQUIRE(!Preprocessor::ToString(preprocessor.Process()).empty());
3636
}
3737

3838
SECTION("TestProcess_PassSourceWithSimpleMacro_ReturnsSourceWithExpandedMacro")

tests/tokensOutputStreamTests.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#include <catch2/catch.hpp>
2+
#include "tcppLibrary.hpp"
3+
#include <string>
4+
5+
using namespace tcpp;
6+
7+
8+
TEST_CASE("TokensOutputStream Tests")
9+
{
10+
const TTokensSequence tokens
11+
{
12+
TToken { E_TOKEN_TYPE::COMMENTARY },
13+
TToken { E_TOKEN_TYPE::OPEN_BRACKET },
14+
TToken { E_TOKEN_TYPE::CLOSE_BRACKET },
15+
TToken { E_TOKEN_TYPE::END },
16+
};
17+
18+
TokensOutputStream stream{ tokens };
19+
20+
SECTION("TestBeginEnd_IterateThroughUsingRangeBasedFor_AllElementsVisited")
21+
{
22+
int i = 0;
23+
24+
for (const TToken& currToken : stream)
25+
{
26+
REQUIRE(currToken.mType == tokens[i++].mType);
27+
}
28+
}
29+
30+
SECTION("TestGetNextToken_IterateThroughSequence_AllElementsVisited")
31+
{
32+
int i = 0;
33+
34+
while (stream.HasNextToken())
35+
{
36+
REQUIRE(stream.GetNextToken().mType == tokens[i++].mType);
37+
}
38+
}
39+
40+
SECTION("TestGetNextToken_TryToGetNextTokenWhenNoItemsRemain_ReturnsLastElement")
41+
{
42+
int i = 0;
43+
44+
while (stream.HasNextToken())
45+
{
46+
REQUIRE(stream.GetNextToken().mType == tokens[i++].mType);
47+
}
48+
49+
REQUIRE(!stream.HasNextToken());
50+
51+
const TToken& outboundsToken = stream.GetNextToken();
52+
REQUIRE(outboundsToken.mType == E_TOKEN_TYPE::END);
53+
}
54+
55+
SECTION("TestPeekNextToken_TryToIterateThroughAllElements_AllElementsVisited")
56+
{
57+
size_t i = 0;
58+
59+
for (const TToken& expectedToken : tokens)
60+
{
61+
REQUIRE(expectedToken.mType == stream.PeekNextToken(i++).mType);
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)