39 const Prescanner &,
Preprocessor &,
bool isNestedInIncludeDirective);
40 Prescanner(
const Prescanner &) =
delete;
41 Prescanner(Prescanner &&) =
delete;
43 const AllSources &allSources()
const {
return allSources_; }
44 AllSources &allSources() {
return allSources_; }
45 const Messages &messages()
const {
return messages_; }
46 Messages &messages() {
return messages_; }
47 const Preprocessor &preprocessor()
const {
return preprocessor_; }
51 Prescanner &set_preprocessingEnabled(
bool yes) {
52 preprocessingEnabled_ = yes;
55 Prescanner &set_preprocessingOnly(
bool yes) {
56 preprocessingOnly_ = yes;
59 Prescanner &set_expandIncludeLines(
bool yes) {
60 expandIncludeLines_ = yes;
63 Prescanner &set_fixedForm(
bool yes) {
67 Prescanner &set_encoding(Encoding code) {
71 Prescanner &set_fixedFormColumnLimit(
int limit) {
72 fixedFormColumnLimit_ = limit;
76 Prescanner &AddCompilerDirectiveSentinel(
const std::string &);
78 void Prescan(ProvenanceRange);
83 bool IsAtEnd()
const {
return nextLine_ >= limit_; }
84 bool IsNextLinePreprocessorDirective()
const;
86 Provenance GetCurrentProvenance()
const {
return GetProvenance(at_); }
88 std::optional<CharBlock> GetKeywordMacroName(
const char *)
const;
91 const char *IsCompilerDirectiveSentinel(
const char *, std::size_t)
const;
92 const char *IsCompilerDirectiveSentinel(
CharBlock)
const;
94 std::optional<std::pair<const char *, const char *>>
95 IsCompilerDirectiveSentinel(
const char *p)
const;
97 template <
typename... A>
Message &Say(A &&...a) {
98 return messages_.Say(std::forward<A>(a)...);
100 template <
typename... A>
101 Message *Warn(common::UsageWarning warning, A &&...a) {
102 return messages_.Warn(
false, features_, warning, std::forward<A>(a)...);
104 template <
typename... A>
105 Message *Warn(common::LanguageFeature feature, A &&...a) {
106 return messages_.Warn(
false, features_, feature, std::forward<A>(a)...);
110 struct LineClassification {
113 ConditionalCompilationDirective,
116 PreprocessorDirective,
119 CompilerDirectiveAfterMacroExpansion,
122 LineClassification(Kind k, std::size_t po = 0,
const char *s =
nullptr)
123 : kind{k}, payloadOffset{po}, sentinel{s} {}
124 LineClassification(LineClassification &&) =
default;
125 LineClassification &operator=(LineClassification &&) =
default;
127 std::size_t payloadOffset;
128 const char *sentinel;
131 void BeginSourceLine(
const char *at) {
134 tabInCurrentLine_ =
false;
137 void BeginSourceLineAndAdvance() {
138 BeginSourceLine(nextLine_);
142 void BeginStatementAndAdvance() {
143 BeginSourceLineAndAdvance();
144 slashInCurrentStatement_ =
false;
145 preventHollerith_ =
false;
146 parenthesisNesting_ = 0;
147 continuationLines_ = 0;
148 isPossibleMacroCall_ =
false;
149 disableSourceContinuation_ =
false;
152 Provenance GetProvenance(
const char *sourceChar)
const {
153 return startProvenance_ + (sourceChar - start_);
156 ProvenanceRange GetProvenanceRange(
157 const char *first,
const char *afterLast)
const {
158 std::size_t bytes = afterLast - first;
159 return {startProvenance_ + (first - start_), bytes};
163 tokens.PutNextTokenChar(ch, GetCurrentProvenance());
167 Provenance provenance{allSources().CompilerInsertionProvenance(ch)};
168 tokens.PutNextTokenChar(ch, provenance);
172 EmitChar(tokens, ch);
177 bool IsOpenMPConditionalLine(
const char *sentinel)
const {
178 return sentinel && sentinel[0] ==
'$' && !sentinel[1];
180 bool IsOpenACCConditionalLine(
const char *sentinel)
const {
181 return sentinel && sentinel[0] ==
'@' && sentinel[1] ==
'a' &&
182 sentinel[2] ==
'c' && sentinel[3] ==
'c' && sentinel[4] ==
'\0';
184 bool IsCUDAConditionalLine(
const char *sentinel)
const {
185 return sentinel && sentinel[0] ==
'@' && sentinel[1] ==
'c' &&
186 sentinel[2] ==
'u' && sentinel[3] ==
'f' && sentinel[4] ==
'\0';
188 bool InCompilerDirective()
const {
return directiveSentinel_ !=
nullptr; }
189 bool InOpenMPConditionalLine()
const {
190 return IsOpenMPConditionalLine(directiveSentinel_);
192 bool InOpenACCConditionalLine()
const {
193 return IsOpenACCConditionalLine(directiveSentinel_);
195 bool InCUDAConditionalLine()
const {
196 return IsCUDAConditionalLine(directiveSentinel_);
198 bool InOpenACCOrCUDAConditionalLine()
const {
199 return InOpenACCConditionalLine() || InCUDAConditionalLine();
201 bool InConditionalLine()
const {
202 return InOpenMPConditionalLine() || InOpenACCOrCUDAConditionalLine();
204 bool IsOpenMPDirective()
const {
205 return directiveSentinel_ &&
206 (std::strcmp(directiveSentinel_,
"$omp") == 0 ||
212 std::strcmp(directiveSentinel_,
"$omx") == 0 ||
213 std::strcmp(directiveSentinel_,
"$ompx") == 0);
215 bool InFixedFormSource()
const {
216 return inFixedForm_ && !inPreprocessorDirective_ && !InCompilerDirective();
219 bool IsCComment(
const char *p)
const {
220 return p[0] ==
'/' && p[1] ==
'*' &&
221 (inPreprocessorDirective_ ||
224 common::LanguageFeature::ClassicCComments)));
230 void SkipToEndOfLine();
231 bool MustSkipToEndOfLine()
const;
234 bool SkipToNextSignificantCharacter();
235 void SkipCComments(
bool reportUnterminated);
236 void WarnCComment(
const char *at);
238 static const char *SkipWhiteSpace(
const char *);
239 const char *SkipWhiteSpaceIncludingEmptyMacros(
240 const char *,
const char **)
const;
241 const char *SkipWhiteSpaceAndCComments(
const char *)
const;
242 const char *SkipCComment(
const char *)
const;
243 void UpdateSourcePositionAfterSkip(
const char *);
248 void QuotedCharacterLiteral(
TokenSequence &,
const char *start);
249 void Hollerith(
TokenSequence &,
int count,
const char *start);
251 bool SkipCommentLine(
bool afterAmpersand);
252 bool IsFixedFormCommentLine(
const char *)
const;
253 const char *IsFreeFormComment(
const char *)
const;
254 std::optional<std::size_t> IsIncludeLine(
const char *)
const;
255 void FortranInclude(
const char *quote);
256 const char *IsPreprocessorDirectiveLine(
const char *)
const;
257 const char *FixedFormContinuationLine(
258 bool atNewline,
const char *&cComment,
const char *&unterminatedCComment);
259 const char *GetFreeFormContinuationLine(
bool ampersand,
const char *p);
260 const char *FreeFormContinuationLine(
bool ampersand);
261 bool IsImplicitContinuation()
const;
262 bool FixedFormContinuation(
bool atNewline);
263 bool FreeFormContinuation();
264 bool Continuation(
bool mightNeedFixedFormSpace);
265 std::optional<LineClassification> IsFixedFormCompilerDirectiveLine(
267 std::optional<LineClassification> IsFreeFormCompilerDirectiveLine(
269 LineClassification ClassifyLine(
const char *)
const;
270 LineClassification ClassifyLine(
272 bool SourceFormChange(std::string &&);
273 bool CompilerDirectiveContinuation(
TokenSequence &,
const char *sentinel);
275 std::optional<LineClassification>
276 IsCompilerDirectiveSentinelAfterKeywordMacro(
const char *p)
const;
283 bool preprocessingEnabled_{
false};
284 bool preprocessingOnly_{
false};
285 bool expandIncludeLines_{
true};
286 bool isNestedInIncludeDirective_{
false};
287 bool backslashFreeFormContinuation_{
false};
288 bool inFixedForm_{
false};
289 int fixedFormColumnLimit_{72};
290 Encoding encoding_{Encoding::UTF_8};
291 int parenthesisNesting_{0};
292 int prescannerNesting_{0};
293 int continuationLines_{0};
294 bool isPossibleMacroCall_{
false};
295 bool afterPreprocessingDirective_{
false};
296 bool disableSourceContinuation_{
false};
299 const char *start_{
nullptr};
300 const char *limit_{
nullptr};
301 const char *nextLine_{
nullptr};
302 const char *directiveSentinel_{
nullptr};
306 const char *at_{
nullptr};
308 bool tabInCurrentLine_{
false};
309 bool slashInCurrentStatement_{
false};
310 bool preventHollerith_{
false};
311 bool inCharLiteral_{
false};
312 bool continuationInCharLiteral_{
false};
313 bool inPreprocessorDirective_{
false};
323 bool brokenToken_{
false};
330 bool omitNewline_{
false};
331 bool skipLeadingAmpersand_{
false};
333 const std::size_t firstCookedCharacterOffset_{cooked_.BufferedBytes()};
336 allSources().CompilerInsertionProvenance(
' ')};
338 allSources().CompilerInsertionProvenance(
'\\')};
342 static const int prime1{1019}, prime2{1021};
343 std::bitset<prime2> compilerDirectiveBloomFilter_;
344 std::unordered_set<std::string> compilerDirectiveSentinels_;