@@ -195,6 +195,14 @@ namespace tcpp
195195
196196 TToken GetNextToken () TCPP_NOEXCEPT;
197197
198+ /* !
199+ \brief The method allows to peek token without changing current pointer
200+
201+ \param[in] offset Distance of overlooking, passing 0 is equivalent to invoking GetNextToken()
202+ */
203+
204+ TToken PeekNextToken (size_t offset = 1 );
205+
198206 bool HasNextToken () const TCPP_NOEXCEPT;
199207
200208 void AppendFront (const std::vector<TToken>& tokens) TCPP_NOEXCEPT;
@@ -205,6 +213,8 @@ namespace tcpp
205213 size_t GetCurrLineIndex () const TCPP_NOEXCEPT;
206214 size_t GetCurrPos () const TCPP_NOEXCEPT;
207215 private:
216+ TToken _getNextTokenInternal (bool ignoreQueue) TCPP_NOEXCEPT;
217+
208218 TToken _scanTokens (std::string& inputLine) TCPP_NOEXCEPT;
209219
210220 std::string _requestSourceLine () TCPP_NOEXCEPT;
@@ -450,24 +460,27 @@ namespace tcpp
450460
451461 TToken Lexer::GetNextToken () TCPP_NOEXCEPT
452462 {
453- if (!mTokensQueue .empty ())
463+ return _getNextTokenInternal (false );
464+ }
465+
466+ TToken Lexer::PeekNextToken (size_t offset)
467+ {
468+ if (!mTokensQueue .empty () && offset < mTokensQueue .size ())
454469 {
455- auto currToken = mTokensQueue .front ( );
456- mTokensQueue . pop_front ();
470+ return * std::next ( mTokensQueue .begin (), offset );
471+ }
457472
458- return currToken;
473+ for (size_t i = 0 ; i < (offset - mTokensQueue .size ()); i++)
474+ {
475+ mTokensQueue .push_back (_getNextTokenInternal (true ));
459476 }
460477
461- if (mCurrLine .empty ())
478+ if (mTokensQueue .empty ())
462479 {
463- // \note if it's still empty then we've reached the end of the source
464- if ((mCurrLine = _requestSourceLine ()).empty ())
465- {
466- return mEOFToken ;
467- }
480+ return GetNextToken ();
468481 }
469482
470- return _scanTokens ( mCurrLine );
483+ return mTokensQueue . back ( );
471484 }
472485
473486 bool Lexer::HasNextToken () const TCPP_NOEXCEPT
@@ -585,6 +598,28 @@ namespace tcpp
585598 }
586599
587600
601+ TToken Lexer::_getNextTokenInternal (bool ignoreQueue) TCPP_NOEXCEPT
602+ {
603+ if (!ignoreQueue && !mTokensQueue .empty ())
604+ {
605+ auto currToken = mTokensQueue .front ();
606+ mTokensQueue .pop_front ();
607+
608+ return currToken;
609+ }
610+
611+ if (mCurrLine .empty ())
612+ {
613+ // \note if it's still empty then we've reached the end of the source
614+ if ((mCurrLine = _requestSourceLine ()).empty ())
615+ {
616+ return mEOFToken ;
617+ }
618+ }
619+
620+ return _scanTokens (mCurrLine );
621+ }
622+
588623 TToken Lexer::_scanTokens (std::string& inputLine) TCPP_NOEXCEPT
589624 {
590625 char ch = ' \0 ' ;
@@ -983,10 +1018,19 @@ namespace tcpp
9831018 }
9841019
9851020
1021+ static const std::vector<std::string> BuiltInDefines
1022+ {
1023+ " __LINE__" ,
1024+ };
1025+
1026+
9861027 Preprocessor::Preprocessor (Lexer& lexer, const TOnErrorCallback& onErrorCallback, const TOnIncludeCallback& onIncludeCallback) TCPP_NOEXCEPT:
9871028 mpLexer(&lexer), mOnErrorCallback(onErrorCallback), mOnIncludeCallback(onIncludeCallback)
9881029 {
989- mSymTable .push_back ({ " __LINE__" });
1030+ for (auto && currSystemDefine : BuiltInDefines)
1031+ {
1032+ mSymTable .push_back ({ currSystemDefine });
1033+ }
9901034 }
9911035
9921036 bool Preprocessor::AddCustomDirectiveHandler (const std::string& directive, const TDirectiveHandler& handler) TCPP_NOEXCEPT
@@ -1253,7 +1297,7 @@ namespace tcpp
12531297 {
12541298 static const std::unordered_map<std::string, std::function<TToken ()>> systemMacrosTable
12551299 {
1256- { " __LINE__ " , [&idToken]() { return TToken { E_TOKEN_TYPE::BLOB, std::to_string (idToken.mLineId ) }; } }
1300+ { BuiltInDefines[ 0 ] , [&idToken]() { return TToken {E_TOKEN_TYPE::BLOB, std::to_string (idToken.mLineId )}; }} // __LINE__
12571301 };
12581302
12591303 auto iter = systemMacrosTable.find (macroDesc.mName );
0 commit comments