Skip to content

Commit 9250ff8

Browse files
Parsing tools: added FindNextPreprocessorDirective function
1 parent 49f6b0a commit 9250ff8

File tree

2 files changed

+90
-26
lines changed

2 files changed

+90
-26
lines changed

Common/interface/ParsingTools.hpp

Lines changed: 63 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,55 @@ inline int GetArrayIndex(const std::string& Var, std::string& NameWithoutBracket
12281228
}
12291229

12301230

1231+
/// Finds the next preprocessor directive in the given range.
1232+
///
1233+
/// # define MACRO
1234+
/// ^ ^ ^
1235+
/// | | NameEnd
1236+
/// | NameStart
1237+
/// Return value
1238+
template <typename InteratorType>
1239+
inline InteratorType FindNextPreprocessorDirective(const InteratorType& Start, const InteratorType& End, InteratorType& NameStart, InteratorType& NameEnd)
1240+
{
1241+
NameStart = End;
1242+
NameEnd = End;
1243+
1244+
auto Pos = Start;
1245+
while (Pos != End)
1246+
{
1247+
// // Comment
1248+
// ^
1249+
Pos = SkipDelimitersAndComments(Pos, End);
1250+
if (Pos == End)
1251+
break;
1252+
1253+
if (*Pos == '#')
1254+
{
1255+
// # define MACRO
1256+
// ^
1257+
// Pos
1258+
1259+
NameStart = SkipDelimiters(Pos + 1, End, " \t");
1260+
// # define MACRO
1261+
// ^
1262+
// NameStart
1263+
1264+
NameEnd = SkipIdentifier(NameStart, End);
1265+
// # define MACRO
1266+
// ^
1267+
// NameEnd
1268+
1269+
break;
1270+
}
1271+
else
1272+
{
1273+
Pos = SkipLine(Pos, End, /* GoToNextLine = */ true);
1274+
}
1275+
}
1276+
1277+
return Pos;
1278+
}
1279+
12311280
/// Strips all preprocessor directives from the source string.
12321281
inline void StripPreprocessorDirectives(std::string& Source, const std::vector<std::string>& Directives)
12331282
{
@@ -1237,41 +1286,29 @@ inline void StripPreprocessorDirectives(std::string& Source, const std::vector<s
12371286
auto Pos = Source.begin();
12381287
while (Pos != Source.end())
12391288
{
1240-
// // Comment
1241-
// ^
1242-
Pos = SkipDelimitersAndComments(Pos, Source.end());
1289+
std::string::iterator NameStart, NameEnd;
1290+
Pos = FindNextPreprocessorDirective(Pos, Source.end(), NameStart, NameEnd);
12431291
if (Pos == Source.end())
12441292
break;
12451293

1246-
if (*Pos == '#')
1247-
{
1248-
const auto DirectiveStart = Pos;
1249-
// # version 450
1250-
// ^
1294+
// # version 450
1295+
// ^ ^ ^
1296+
// | | NameEnd
1297+
// | NameStart
1298+
// Pos
12511299

1252-
++Pos;
1253-
if (Pos == Source.end())
1254-
break;
1255-
1256-
Pos = SkipDelimiters(Pos, Source.end(), " \t");
1257-
// # version 450
1258-
// ^
1300+
const std::string DirectiveIdentifier{NameStart, NameEnd};
1301+
if (!DirectiveIdentifier.empty() && std::find(Directives.begin(), Directives.end(), DirectiveIdentifier) != Directives.end())
1302+
{
1303+
// Keep the newline character
1304+
const auto LineEnd = SkipLine(NameEnd, Source.end(), /* GoToNextLine = */ false);
12591305

1306+
Pos = Source.erase(Pos, LineEnd);
12601307
if (Pos == Source.end())
12611308
break;
1262-
1263-
const std::string DirectiveIdentifier{Pos, SkipIdentifier(Pos, Source.end())};
1264-
if (!DirectiveIdentifier.empty() && std::find(Directives.begin(), Directives.end(), DirectiveIdentifier) != Directives.end())
1265-
{
1266-
const auto LineEnd = SkipLine(Pos, Source.end(), false);
1267-
1268-
Pos = Source.erase(DirectiveStart, LineEnd);
1269-
if (Pos == Source.end())
1270-
break;
1271-
}
12721309
}
12731310

1274-
Pos = SkipLine(Pos, Source.end(), true);
1311+
Pos = SkipLine(Pos, Source.end(), /* GoToNextLine = */ true);
12751312
}
12761313
}
12771314

Tests/DiligentCoreTest/src/Common/ParsingToolsTest.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,33 @@ TEST(Common_ParsingTools, GetArrayIndex)
14421442
Test("xy7[12 ", 3, INT_MIN);
14431443
}
14441444

1445+
1446+
TEST(Common_ParsingTools, FindNextPreprocessorDirective)
1447+
{
1448+
auto Test = [](std::string Source, const std::string& RefDirectiveStart, const std::string& Directive) {
1449+
std::string::iterator NameStart, NameEnd;
1450+
1451+
auto DirectiveStart = FindNextPreprocessorDirective(Source.begin(), Source.end(), NameStart, NameEnd);
1452+
EXPECT_STREQ(RefDirectiveStart.c_str(), std::string(DirectiveStart, Source.end()).c_str());
1453+
EXPECT_STREQ(Directive.c_str(), std::string(NameStart, NameEnd).c_str());
1454+
};
1455+
1456+
Test("", "", "");
1457+
Test(" ", "", "");
1458+
Test("ABC", "", "");
1459+
Test("\r\n", "", "");
1460+
Test("#", "#", "");
1461+
Test("# ", "# ", "");
1462+
Test("# define XYZ", "# define XYZ", "define");
1463+
Test("/* Comment */ # define XYZ", "# define XYZ", "define");
1464+
1465+
Test(R"(
1466+
// #version XYZ
1467+
# define ABC)",
1468+
"# define ABC",
1469+
"define");
1470+
}
1471+
14451472
TEST(Common_ParsingTools, StripPreprocessorDirectives)
14461473
{
14471474
auto Test = [](std::string Source, const std::string& RefSource, const std::vector<std::string>& Directives) {

0 commit comments

Comments
 (0)