Skip to content

Commit 95d6ac1

Browse files
committed
chore: Update parseDirective to return ParsedDirective variant
Signed-off-by: Roberto Raggi <[email protected]>
1 parent 2c6b24c commit 95d6ac1

File tree

2 files changed

+156
-81
lines changed

2 files changed

+156
-81
lines changed

src/parser/cxx/preprocessor.cc

Lines changed: 141 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,13 @@
2626
#include <cxx/diagnostics_client.h>
2727
#include <cxx/lexer.h>
2828
#include <cxx/literals.h>
29+
#include <cxx/preprocessor.h>
2930
#include <cxx/private/path.h>
30-
31-
// fmt
32-
#include <format>
33-
34-
// utf8
3531
#include <utf8/unchecked.h>
3632

37-
// stl
38-
#include <cxx/preprocessor.h>
39-
4033
#include <algorithm>
4134
#include <cassert>
35+
#include <format>
4236
#include <forward_list>
4337
#include <fstream>
4438
#include <functional>
@@ -716,9 +710,10 @@ struct Preprocessor::Private {
716710
std::string_view local;
717711
Include include;
718712
bool isIncludeNext = false;
719-
int value = 0;
713+
bool exists = false;
720714
};
721715
std::vector<Dep> dependencies_;
716+
std::function<void()> continuation_;
722717
int localCount_ = 0;
723718

724719
int counter_ = 0;
@@ -1167,8 +1162,15 @@ struct Preprocessor::Private {
11671162
TokList *loc = nullptr;
11681163
};
11691164

1165+
struct ParsedIfDirective {
1166+
std::function<void()> resume;
1167+
};
1168+
1169+
using ParsedDirective =
1170+
std::variant<std::monostate, ParsedIncludeDirective, ParsedIfDirective>;
1171+
11701172
[[nodiscard]] auto parseDirective(SourceFile *source, TokList *start)
1171-
-> std::optional<ParsedIncludeDirective>;
1173+
-> ParsedDirective;
11721174

11731175
[[nodiscard]] auto parseIncludeDirective(TokList *directive, TokList *ts)
11741176
-> std::optional<ParsedIncludeDirective>;
@@ -1203,7 +1205,9 @@ struct Preprocessor::Private {
12031205
[[nodiscard]] auto copyLine(TokList *ts, bool inMacroBody = false)
12041206
-> TokList *;
12051207

1206-
[[nodiscard]] auto constantExpression(TokList *ts) -> long;
1208+
[[nodiscard]] auto prepareConstantExpression(TokList *ts) -> TokList *;
1209+
1210+
[[nodiscard]] auto evaluateConstantExpression(TokList *ts) -> long;
12071211
[[nodiscard]] auto conditionalExpression(TokList *&ts) -> long;
12081212
[[nodiscard]] auto binaryExpression(TokList *&ts) -> long;
12091213
[[nodiscard]] auto binaryExpressionHelper(TokList *&ts, long lhs, int minPrec)
@@ -1647,7 +1651,7 @@ auto Preprocessor::Private::expandTokens(TokIterator it, TokIterator last,
16471651

16481652
auto Preprocessor::Private::expand(
16491653
const std::function<void(const Tok *)> &emitToken) -> Status {
1650-
if (buffers_.empty()) return IsDone{};
1654+
if (buffers_.empty()) return ProcessingComplete{};
16511655

16521656
auto buffer = buffers_.back();
16531657
buffers_.pop_back();
@@ -1672,8 +1676,11 @@ auto Preprocessor::Private::expand(
16721676
// skip the rest of the line
16731677
it = skipLine(it, last);
16741678

1675-
if (auto parsedInclude = parseDirective(source, start.toTokList())) {
1676-
NeedToResolveInclude status{
1679+
auto parsedDirective = parseDirective(source, start.toTokList());
1680+
1681+
if (auto parsedInclude =
1682+
std::get_if<ParsedIncludeDirective>(&parsedDirective)) {
1683+
PendingInclude status{
16771684
.preprocessor = *preprocessor_,
16781685
.include = parsedInclude->header,
16791686
.isIncludeNext = parsedInclude->includeNext,
@@ -1691,6 +1698,37 @@ auto Preprocessor::Private::expand(
16911698
// reset the token stream, so we can start processing the continuation
16921699
it = last;
16931700

1701+
return status;
1702+
} else if (auto directive =
1703+
std::get_if<ParsedIfDirective>(&parsedDirective)) {
1704+
// suspend and resolve the dependencies
1705+
continuation_ = std::move(directive->resume);
1706+
1707+
// suspend the current file and start processing the continuation
1708+
buffers_.push_back(Buffer{
1709+
.source = source,
1710+
.currentPath = currentPath_,
1711+
.ts = it.toTokList(),
1712+
.includeDepth = includeDepth_,
1713+
});
1714+
1715+
// reset the token stream, so we can start processing the continuation
1716+
it = last;
1717+
1718+
std::vector<PendingHasIncludes::Rquest> dependencies;
1719+
for (auto &dep : dependencies_) {
1720+
dependencies.push_back({
1721+
.include = dep.include,
1722+
.isIncludeNext = dep.isIncludeNext,
1723+
.exists = dep.exists,
1724+
});
1725+
}
1726+
1727+
PendingHasIncludes status{
1728+
.preprocessor = *preprocessor_,
1729+
.requests = dependencies,
1730+
};
1731+
16941732
return status;
16951733
}
16961734
} else if (skipping) {
@@ -1701,16 +1739,16 @@ auto Preprocessor::Private::expand(
17011739
}
17021740
}
17031741

1704-
if (buffers_.empty()) return IsDone{};
1742+
if (buffers_.empty()) return ProcessingComplete{};
17051743

1706-
return CanContinue{};
1744+
return CanContinuePreprocessing{};
17071745
}
17081746

17091747
auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
1710-
-> std::optional<ParsedIncludeDirective> {
1748+
-> ParsedDirective {
17111749
auto directive = start->next;
17121750

1713-
if (!lookat(directive, TokenKind::T_IDENTIFIER)) return std::nullopt;
1751+
if (!lookat(directive, TokenKind::T_IDENTIFIER)) return std::monostate{};
17141752

17151753
dependencies_.clear();
17161754

@@ -1725,7 +1763,11 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
17251763
case PreprocessorDirectiveKind::T_INCLUDE_NEXT:
17261764
case PreprocessorDirectiveKind::T_INCLUDE: {
17271765
if (skipping) break;
1728-
return parseIncludeDirective(directive, ts);
1766+
auto includeDirective = parseIncludeDirective(directive, ts);
1767+
if (includeDirective.has_value()) {
1768+
return *includeDirective;
1769+
}
1770+
break;
17291771
}
17301772

17311773
case PreprocessorDirectiveKind::T_DEFINE: {
@@ -1781,11 +1823,23 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
17811823
if (skipping) {
17821824
pushState(std::tuple(true, false));
17831825
} else {
1784-
const auto value = constantExpression(ts);
1785-
if (value) {
1786-
pushState(std::tuple(skipping, false));
1826+
auto expression = prepareConstantExpression(ts);
1827+
1828+
auto resume = [=, this] {
1829+
const auto value = evaluateConstantExpression(expression);
1830+
1831+
if (value) {
1832+
pushState(std::tuple(skipping, false));
1833+
} else {
1834+
pushState(std::tuple(true, !skipping));
1835+
}
1836+
};
1837+
1838+
if (dependencies_.empty()) {
1839+
resume();
17871840
} else {
1788-
pushState(std::tuple(true, !skipping));
1841+
// rewquest the resolution of the dependencies
1842+
return ParsedIfDirective{.resume = std::move(resume)};
17891843
}
17901844
}
17911845

@@ -1796,11 +1850,23 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
17961850
if (!evaluating) {
17971851
setState(std::tuple(true, false));
17981852
} else {
1799-
const auto value = constantExpression(ts);
1800-
if (value) {
1801-
setState(std::tuple(!evaluating, false));
1853+
auto expression = prepareConstantExpression(ts);
1854+
1855+
auto resume = [=, this] {
1856+
const auto value = evaluateConstantExpression(expression);
1857+
1858+
if (value) {
1859+
setState(std::tuple(!evaluating, false));
1860+
} else {
1861+
setState(std::tuple(true, evaluating));
1862+
}
1863+
};
1864+
1865+
if (dependencies_.empty()) {
1866+
resume();
18021867
} else {
1803-
setState(std::tuple(true, evaluating));
1868+
// rewquest the resolution of the dependencies
1869+
return ParsedIfDirective{.resume = std::move(resume)};
18041870
}
18051871
}
18061872

@@ -1899,7 +1965,7 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
18991965
break;
19001966
} // switch
19011967

1902-
return std::nullopt;
1968+
return std::monostate{};
19031969
}
19041970

19051971
auto Preprocessor::Private::parseIncludeDirective(TokList *directive,
@@ -2348,18 +2414,22 @@ auto Preprocessor::Private::copyLine(TokList *ts, bool inMacroBody)
23482414
return line;
23492415
}
23502416

2351-
auto Preprocessor::Private::constantExpression(TokList *ts) -> long {
2417+
auto Preprocessor::Private::prepareConstantExpression(TokList *ts)
2418+
-> TokList * {
23522419
auto line = copyLine(ts);
2420+
23532421
dependencies_.clear();
2422+
23542423
auto it = expandTokens(TokIterator{line}, TokIterator{},
23552424
/*inConditionalExpression*/ true);
2356-
// evaluate the deps
2357-
for (auto &d : dependencies_) {
2358-
auto resolved = resolve(d.include, d.isIncludeNext);
2359-
d.value = resolved.has_value();
2360-
}
2361-
auto e = it.toTokList();
2362-
return conditionalExpression(e);
2425+
2426+
auto expression = it.toTokList();
2427+
2428+
return expression;
2429+
}
2430+
2431+
auto Preprocessor::Private::evaluateConstantExpression(TokList *ts) -> long {
2432+
return conditionalExpression(ts);
23632433
}
23642434

23652435
auto Preprocessor::Private::conditionalExpression(TokList *&ts) -> long {
@@ -2543,7 +2613,7 @@ auto Preprocessor::Private::primaryExpression(TokList *&ts) -> long {
25432613
for (const auto &dep : dependencies_) {
25442614
if (dep.local == tk->text) {
25452615
ts = ts->next;
2546-
return dep.value;
2616+
return dep.exists;
25472617
}
25482618
}
25492619
}
@@ -2856,37 +2926,28 @@ void Preprocessor::preprocess(std::string source, std::string fileName,
28562926
Preprocessor &self;
28572927
bool done = false;
28582928

2859-
void operator()(const IsDone &) { done = true; }
2929+
void operator()(const ProcessingComplete &) { done = true; }
28602930

2861-
void operator()(const CanContinue &) {
2862-
// keep going
2863-
}
2931+
void operator()(const CanContinuePreprocessing &) {}
28642932

2865-
void operator()(const NeedToResolveInclude &status) {
2933+
void operator()(const PendingInclude &status) {
28662934
auto d = self.d.get();
28672935

2868-
if (auto resolvedInclude =
2869-
d->resolve(status.include, status.isIncludeNext)) {
2870-
status.continueWith(resolvedInclude.value());
2871-
return;
2872-
}
2873-
2874-
auto loc = static_cast<TokList *>(status.loc);
2936+
auto resolvedInclude = d->resolve(status.include, status.isIncludeNext);
28752937

2876-
const auto file = getHeaderName(status.include);
2877-
2878-
d->error(loc, std::format("file '{}' not found", file));
2938+
status.resolveWith(resolvedInclude);
28792939
}
28802940

2881-
void operator()(const NeedToKnowIfFileExists &status) {
2882-
auto exists = self.d->fileExists(status.fileName);
2883-
status.setFileExists(exists);
2884-
}
2941+
void operator()(const PendingHasIncludes &status) {
2942+
auto d = self.d.get();
28852943

2886-
void operator()(const NeedToReadFile &status) {
2887-
auto source = self.d->readFile(status.fileName);
2888-
status.setContents(std::move(source));
2944+
std::ranges::for_each(
2945+
status.requests, [&](const PendingHasIncludes::Rquest &dep) {
2946+
auto resolved = d->resolve(dep.include, dep.isIncludeNext);
2947+
dep.setExists(resolved.has_value());
2948+
});
28892949
}
2950+
28902951
} state{*this};
28912952

28922953
beginPreprocessing(std::move(source), std::move(fileName), tokens);
@@ -2898,11 +2959,18 @@ void Preprocessor::preprocess(std::string source, std::string fileName,
28982959
endPreprocessing(tokens);
28992960
}
29002961

2901-
void Preprocessor::NeedToResolveInclude::continueWith(
2902-
std::string fileName) const {
2962+
void Preprocessor::PendingInclude::resolveWith(
2963+
std::optional<std::string> fileName) const {
29032964
auto d = preprocessor.d.get();
29042965

2905-
auto continuation = d->findOrCreateSourceFile(fileName);
2966+
if (!fileName.has_value()) {
2967+
const auto &header = getHeaderName(include);
2968+
d->error(static_cast<TokList *>(loc),
2969+
std::format("file '{}' not found", header));
2970+
return;
2971+
}
2972+
2973+
auto continuation = d->findOrCreateSourceFile(*fileName);
29062974
if (!continuation) return;
29072975

29082976
// make the continuation the current file
@@ -2917,10 +2985,6 @@ void Preprocessor::NeedToResolveInclude::continueWith(
29172985
});
29182986
}
29192987

2920-
void Preprocessor::NeedToKnowIfFileExists::setFileExists(bool exists) const {}
2921-
2922-
void Preprocessor::NeedToReadFile::setContents(std::string contents) const {}
2923-
29242988
void Preprocessor::beginPreprocessing(std::string source, std::string fileName,
29252989
std::vector<Token> &tokens) {
29262990
assert(!d->findSourceFile(fileName));
@@ -2948,6 +3012,11 @@ void Preprocessor::beginPreprocessing(std::string source, std::string fileName,
29483012
}
29493013

29503014
void Preprocessor::endPreprocessing(std::vector<Token> &tokens) {
3015+
// consume the continuation if there is one
3016+
std::function<void()> continuation;
3017+
std::swap(continuation, d->continuation_);
3018+
if (continuation) continuation();
3019+
29513020
if (tokens.empty()) return;
29523021

29533022
// assume the main source file is the first one
@@ -2960,7 +3029,13 @@ void Preprocessor::endPreprocessing(std::vector<Token> &tokens) {
29603029
}
29613030

29623031
auto Preprocessor::continuePreprocessing(std::vector<Token> &tokens) -> Status {
3032+
// consume the continuation if there is one
3033+
std::function<void()> continuation;
3034+
std::swap(continuation, d->continuation_);
3035+
if (continuation) continuation();
3036+
29633037
auto emitToken = [&](const Tok *tk) { d->finalizeToken(tokens, tk); };
3038+
29643039
return d->expand(emitToken);
29653040
}
29663041

0 commit comments

Comments
 (0)