Skip to content

Commit 2999482

Browse files
committed
chore: Preprocess with the streaming API
Signed-off-by: Roberto Raggi <[email protected]>
1 parent aefc149 commit 2999482

File tree

7 files changed

+134
-74
lines changed

7 files changed

+134
-74
lines changed

src/frontend/cxx/cxx_document.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,6 @@ void CxxDocument::parse(std::string source, std::string fileName) {
181181
unit.setSource(std::move(source), fileName);
182182

183183
auto preprocessor = unit.preprocessor();
184-
preprocessor->squeeze();
185184

186185
unit.parse(ParserConfiguration{
187186
.checkTypes = cli.opt_fcheck,

src/frontend/cxx/frontend.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,6 @@ auto runOnFile(const CLI& cli, const std::string& fileName) -> bool {
266266
}
267267

268268
if (!shouldExit) {
269-
preprocessor->squeeze();
270-
271269
unit.parse(ParserConfiguration{
272270
.checkTypes = cli.opt_fcheck,
273271
.fuzzyTemplateResolution = true,

src/parser/cxx/preprocessor.cc

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,7 @@ struct Preprocessor::Private {
11351135
[[nodiscard]] auto parseMacroDefinition(TokList *ts) -> Macro;
11361136

11371137
[[nodiscard]] auto expand(const std::function<void(const Tok *)> &emitToken)
1138-
-> Status;
1138+
-> PreprocessingState;
11391139

11401140
[[nodiscard]] auto expandTokens(TokIterator it, TokIterator last,
11411141
bool inConditionalExpression) -> TokIterator;
@@ -1650,7 +1650,7 @@ auto Preprocessor::Private::expandTokens(TokIterator it, TokIterator last,
16501650
}
16511651

16521652
auto Preprocessor::Private::expand(
1653-
const std::function<void(const Tok *)> &emitToken) -> Status {
1653+
const std::function<void(const Tok *)> &emitToken) -> PreprocessingState {
16541654
if (buffers_.empty()) return ProcessingComplete{};
16551655

16561656
auto buffer = buffers_.back();
@@ -2934,8 +2934,7 @@ void Preprocessor::preprocess(std::string source, std::string fileName,
29342934
endPreprocessing(tokens);
29352935
}
29362936

2937-
void Preprocessor::PendingInclude::resolveWith(
2938-
std::optional<std::string> fileName) const {
2937+
void PendingInclude::resolveWith(std::optional<std::string> fileName) const {
29392938
auto d = preprocessor.d.get();
29402939

29412940
if (!fileName.has_value()) {
@@ -2952,7 +2951,7 @@ void Preprocessor::PendingInclude::resolveWith(
29522951
fs::path dirpath = fs::path(continuation->fileName);
29532952
dirpath.remove_filename();
29542953

2955-
d->buffers_.push_back(Private::Buffer{
2954+
d->buffers_.push_back(Preprocessor::Private::Buffer{
29562955
.source = continuation,
29572956
.currentPath = dirpath,
29582957
.ts = continuation->tokens,
@@ -3003,7 +3002,8 @@ void Preprocessor::endPreprocessing(std::vector<Token> &tokens) {
30033002
tk.setFileId(mainSourceFileId);
30043003
}
30053004

3006-
auto Preprocessor::continuePreprocessing(std::vector<Token> &tokens) -> Status {
3005+
auto Preprocessor::continuePreprocessing(std::vector<Token> &tokens)
3006+
-> PreprocessingState {
30073007
// consume the continuation if there is one
30083008
std::function<void()> continuation;
30093009
std::swap(continuation, d->continuation_);
@@ -3208,24 +3208,20 @@ auto Preprocessor::resolve(const Include &include, bool isIncludeNext) const
32083208
return d->resolve(include, isIncludeNext);
32093209
}
32103210

3211-
void DefaultPreprocessorState::operator()(
3212-
const Preprocessor::ProcessingComplete &) {
3211+
void DefaultPreprocessorState::operator()(const ProcessingComplete &) {
32133212
done = true;
32143213
}
32153214

3216-
void DefaultPreprocessorState::operator()(
3217-
const Preprocessor::CanContinuePreprocessing &) {}
3215+
void DefaultPreprocessorState::operator()(const CanContinuePreprocessing &) {}
32183216

3219-
void DefaultPreprocessorState::operator()(
3220-
const Preprocessor::PendingInclude &status) {
3217+
void DefaultPreprocessorState::operator()(const PendingInclude &status) {
32213218
auto resolvedInclude = self.resolve(status.include, status.isIncludeNext);
32223219

32233220
status.resolveWith(resolvedInclude);
32243221
}
32253222

3226-
void DefaultPreprocessorState::operator()(
3227-
const Preprocessor::PendingHasIncludes &status) {
3228-
using Request = Preprocessor::PendingHasIncludes::Request;
3223+
void DefaultPreprocessorState::operator()(const PendingHasIncludes &status) {
3224+
using Request = PendingHasIncludes::Request;
32293225

32303226
std::ranges::for_each(status.requests, [&](const Request &dep) {
32313227
auto resolved = self.resolve(dep.include, dep.isIncludeNext);

src/parser/cxx/preprocessor.h

Lines changed: 7 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,14 @@
2020

2121
#pragma once
2222

23-
#include <cxx/cxx_fwd.h>
23+
#include <cxx/preprocessor_fwd.h>
2424

2525
#include <functional>
2626
#include <iosfwd>
2727
#include <memory>
2828
#include <optional>
2929
#include <string>
3030
#include <string_view>
31-
#include <variant>
3231
#include <vector>
3332

3433
namespace cxx {
@@ -40,25 +39,6 @@ class Preprocessor;
4039
class PreprocessorDelegate;
4140
class SourcePosition;
4241

43-
struct SystemInclude {
44-
std::string fileName;
45-
46-
SystemInclude() = default;
47-
48-
explicit SystemInclude(std::string fileName)
49-
: fileName(std::move(fileName)) {}
50-
};
51-
52-
struct QuoteInclude {
53-
std::string fileName;
54-
55-
QuoteInclude() = default;
56-
57-
explicit QuoteInclude(std::string fileName) : fileName(std::move(fileName)) {}
58-
};
59-
60-
using Include = std::variant<SystemInclude, QuoteInclude>;
61-
6242
class CommentHandler {
6343
public:
6444
virtual ~CommentHandler() = default;
@@ -108,37 +88,8 @@ class Preprocessor {
10888

10989
void endPreprocessing(std::vector<Token> &outputTokens);
11090

111-
struct PendingInclude {
112-
Preprocessor &preprocessor;
113-
Include include;
114-
bool isIncludeNext = false;
115-
void *loc = nullptr;
116-
117-
void resolveWith(std::optional<std::string> fileName) const;
118-
};
119-
120-
struct PendingHasIncludes {
121-
struct Request {
122-
Include include;
123-
bool isIncludeNext = false;
124-
bool &exists;
125-
126-
void setExists(bool value) const { exists = value; }
127-
};
128-
129-
Preprocessor &preprocessor;
130-
std::vector<Request> requests;
131-
};
132-
133-
struct CanContinuePreprocessing {};
134-
135-
struct ProcessingComplete {};
136-
137-
using Status = std::variant<PendingInclude, PendingHasIncludes,
138-
CanContinuePreprocessing, ProcessingComplete>;
139-
14091
[[nodiscard]] auto continuePreprocessing(std::vector<Token> &outputTokens)
141-
-> Status;
92+
-> PreprocessingState;
14293

14394
[[nodiscard]] auto sourceFileName(uint32_t sourceFileId) const
14495
-> const std::string &;
@@ -180,6 +131,7 @@ class Preprocessor {
180131
private:
181132
struct Private;
182133
struct ParseArguments;
134+
friend struct PendingInclude;
183135
std::unique_ptr<Private> d;
184136
};
185137

@@ -192,10 +144,10 @@ class DefaultPreprocessorState {
192144

193145
explicit operator bool() const { return !done; }
194146

195-
void operator()(const Preprocessor::ProcessingComplete &);
196-
void operator()(const Preprocessor::CanContinuePreprocessing &);
197-
void operator()(const Preprocessor::PendingInclude &status);
198-
void operator()(const Preprocessor::PendingHasIncludes &status);
147+
void operator()(const ProcessingComplete &);
148+
void operator()(const CanContinuePreprocessing &);
149+
void operator()(const PendingInclude &status);
150+
void operator()(const PendingHasIncludes &status);
199151
};
200152

201153
} // namespace cxx

src/parser/cxx/preprocessor_fwd.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) 2024 Roberto Raggi <[email protected]>
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy
4+
// of this software and associated documentation files (the "Software"), to deal
5+
// in the Software without restriction, including without limitation the rights
6+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
// copies of the Software, and to permit persons to whom the Software is
8+
// furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
// SOFTWARE.
20+
21+
#pragma once
22+
23+
#include <cxx/cxx_fwd.h>
24+
25+
#include <optional>
26+
#include <string>
27+
#include <variant>
28+
#include <vector>
29+
30+
namespace cxx {
31+
32+
class Preprocessor;
33+
class CommentHandler;
34+
35+
struct SystemInclude {
36+
std::string fileName;
37+
38+
SystemInclude() = default;
39+
40+
explicit SystemInclude(std::string fileName)
41+
: fileName(std::move(fileName)) {}
42+
};
43+
44+
struct QuoteInclude {
45+
std::string fileName;
46+
47+
QuoteInclude() = default;
48+
49+
explicit QuoteInclude(std::string fileName) : fileName(std::move(fileName)) {}
50+
};
51+
52+
using Include = std::variant<SystemInclude, QuoteInclude>;
53+
54+
struct PendingInclude {
55+
Preprocessor &preprocessor;
56+
Include include;
57+
bool isIncludeNext = false;
58+
void *loc = nullptr;
59+
60+
void resolveWith(std::optional<std::string> fileName) const;
61+
};
62+
63+
struct PendingHasIncludes {
64+
struct Request {
65+
Include include;
66+
bool isIncludeNext = false;
67+
bool &exists;
68+
69+
void setExists(bool value) const { exists = value; }
70+
};
71+
72+
Preprocessor &preprocessor;
73+
std::vector<Request> requests;
74+
};
75+
76+
struct CanContinuePreprocessing {};
77+
78+
struct ProcessingComplete {};
79+
80+
using PreprocessingState =
81+
std::variant<PendingInclude, PendingHasIncludes, CanContinuePreprocessing,
82+
ProcessingComplete>;
83+
84+
} // namespace cxx

src/parser/cxx/translation_unit.cc

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,27 @@ auto TranslationUnit::changeDiagnosticsClient(
7373
}
7474

7575
void TranslationUnit::setSource(std::string source, std::string fileName) {
76+
beginPreprocessing(std::move(source), std::move(fileName));
77+
DefaultPreprocessorState state{*preprocessor_};
78+
while (state) {
79+
std::visit(state, continuePreprocessing());
80+
}
81+
endPreprocessing();
82+
}
83+
84+
void TranslationUnit::beginPreprocessing(std::string source,
85+
std::string fileName) {
7686
fileName_ = std::move(fileName);
77-
preprocessor_->preprocess(std::move(source), fileName_, tokens_);
87+
preprocessor_->beginPreprocessing(std::move(source), fileName_, tokens_);
88+
}
89+
90+
auto TranslationUnit::continuePreprocessing() -> PreprocessingState {
91+
return preprocessor_->continuePreprocessing(tokens_);
92+
}
93+
94+
void TranslationUnit::endPreprocessing() {
95+
preprocessor_->endPreprocessing(tokens_);
96+
preprocessor_->squeeze();
7897
}
7998

8099
auto TranslationUnit::tokenLength(SourceLocation loc) const -> int {
@@ -125,6 +144,10 @@ auto TranslationUnit::tokenEndPosition(SourceLocation loc) const
125144
}
126145

127146
void TranslationUnit::parse(const ParserConfiguration& config) {
147+
if (ast_) {
148+
cxx_runtime_error("translation unit already parsed");
149+
}
150+
128151
Parser parse(this);
129152
parse.setConfig(config);
130153
parse(ast_);

src/parser/cxx/translation_unit.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <cxx/literals_fwd.h>
2727
#include <cxx/names_fwd.h>
2828
#include <cxx/parser_fwd.h>
29+
#include <cxx/preprocessor_fwd.h>
2930
#include <cxx/source_location.h>
3031
#include <cxx/symbols_fwd.h>
3132
#include <cxx/token.h>
@@ -67,8 +68,15 @@ class TranslationUnit {
6768
return preprocessor_.get();
6869
}
6970

71+
// set source and preprocess, deprecated.
7072
void setSource(std::string source, std::string fileName);
7173

74+
void beginPreprocessing(std::string source, std::string fileName);
75+
76+
[[nodiscard]] auto continuePreprocessing() -> PreprocessingState;
77+
78+
void endPreprocessing();
79+
7280
[[nodiscard]] auto fatalErrors() const -> bool {
7381
return diagnosticsClient_->fatalErrors();
7482
}

0 commit comments

Comments
 (0)