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_preprocessingOnly(
bool yes) {
52 preprocessingOnly_ = yes;
55 Prescanner &set_expandIncludeLines(
bool yes) {
56 expandIncludeLines_ = yes;
59 Prescanner &set_fixedForm(
bool yes) {
63 Prescanner &set_encoding(Encoding code) {
67 Prescanner &set_fixedFormColumnLimit(
int limit) {
68 fixedFormColumnLimit_ = limit;
72 Prescanner &AddCompilerDirectiveSentinel(
const std::string &);
74 void Prescan(ProvenanceRange);
79 bool IsAtEnd()
const {
return nextLine_ >= limit_; }
80 bool IsNextLinePreprocessorDirective()
const;
82 Provenance GetCurrentProvenance()
const {
return GetProvenance(at_); }
84 const char *IsCompilerDirectiveSentinel(
const char *, std::size_t)
const;
85 const char *IsCompilerDirectiveSentinel(
CharBlock)
const;
87 std::optional<std::pair<const char *, const char *>>
88 IsCompilerDirectiveSentinel(
const char *p)
const;
90 template <
typename... A>
Message &Say(A &&...a) {
91 return messages_.Say(std::forward<A>(a)...);
93 template <
typename... A>
94 Message *Warn(common::UsageWarning warning, A &&...a) {
95 return messages_.Warn(
false, features_, warning, std::forward<A>(a)...);
97 template <
typename... A>
98 Message *Warn(common::LanguageFeature feature, A &&...a) {
99 return messages_.Warn(
false, features_, feature, std::forward<A>(a)...);
103 struct LineClassification {
106 ConditionalCompilationDirective,
109 PreprocessorDirective,
114 LineClassification(Kind k, std::size_t po = 0,
const char *s =
nullptr)
115 : kind{k}, payloadOffset{po}, sentinel{s} {}
116 LineClassification(LineClassification &&) =
default;
117 LineClassification &operator=(LineClassification &&) =
default;
119 std::size_t payloadOffset;
120 const char *sentinel;
123 void BeginSourceLine(
const char *at) {
126 tabInCurrentLine_ =
false;
129 void BeginSourceLineAndAdvance() {
130 BeginSourceLine(nextLine_);
134 void BeginStatementAndAdvance() {
135 BeginSourceLineAndAdvance();
136 slashInCurrentStatement_ =
false;
137 preventHollerith_ =
false;
138 parenthesisNesting_ = 0;
139 continuationLines_ = 0;
140 isPossibleMacroCall_ =
false;
141 disableSourceContinuation_ =
false;
144 Provenance GetProvenance(
const char *sourceChar)
const {
145 return startProvenance_ + (sourceChar - start_);
148 ProvenanceRange GetProvenanceRange(
149 const char *first,
const char *afterLast)
const {
150 std::size_t bytes = afterLast - first;
151 return {startProvenance_ + (first - start_), bytes};
155 tokens.PutNextTokenChar(ch, GetCurrentProvenance());
159 Provenance provenance{allSources_.CompilerInsertionProvenance(ch)};
160 tokens.PutNextTokenChar(ch, provenance);
164 EmitChar(tokens, ch);
169 bool InCompilerDirective()
const {
return directiveSentinel_ !=
nullptr; }
170 bool InOpenMPConditionalLine()
const {
171 return directiveSentinel_ && directiveSentinel_[0] ==
'$' &&
172 !directiveSentinel_[1];
174 bool InOpenACCOrCUDAConditionalLine()
const {
175 return directiveSentinel_ && directiveSentinel_[0] ==
'@' &&
176 ((directiveSentinel_[1] ==
'a' && directiveSentinel_[2] ==
'c' &&
177 directiveSentinel_[3] ==
'c') ||
178 (directiveSentinel_[1] ==
'c' && directiveSentinel_[2] ==
'u' &&
179 directiveSentinel_[3] ==
'f')) &&
180 directiveSentinel_[4] ==
'\0';
182 bool InConditionalLine()
const {
183 return InOpenMPConditionalLine() || InOpenACCOrCUDAConditionalLine();
185 bool IsOpenMPDirective()
const {
186 return directiveSentinel_ && std::strcmp(directiveSentinel_,
"$omp") == 0;
188 bool InFixedFormSource()
const {
189 return inFixedForm_ && !inPreprocessorDirective_ && !InCompilerDirective();
192 bool IsCComment(
const char *p)
const {
193 return p[0] ==
'/' && p[1] ==
'*' &&
194 (inPreprocessorDirective_ ||
197 common::LanguageFeature::ClassicCComments)));
203 void SkipToEndOfLine();
204 bool MustSkipToEndOfLine()
const;
207 bool SkipToNextSignificantCharacter();
208 void SkipCComments();
210 static const char *SkipWhiteSpace(
const char *);
211 const char *SkipWhiteSpaceIncludingEmptyMacros(
const char *)
const;
212 const char *SkipWhiteSpaceAndCComments(
const char *)
const;
213 const char *SkipCComment(
const char *)
const;
218 void QuotedCharacterLiteral(
TokenSequence &,
const char *start);
219 void Hollerith(
TokenSequence &,
int count,
const char *start);
221 bool SkipCommentLine(
bool afterAmpersand);
222 bool IsFixedFormCommentLine(
const char *)
const;
223 const char *IsFreeFormComment(
const char *)
const;
224 std::optional<std::size_t> IsIncludeLine(
const char *)
const;
225 void FortranInclude(
const char *quote);
226 const char *IsPreprocessorDirectiveLine(
const char *)
const;
227 const char *FixedFormContinuationLine(
bool atNewline);
228 const char *FreeFormContinuationLine(
bool ampersand);
229 bool IsImplicitContinuation()
const;
230 bool FixedFormContinuation(
bool atNewline);
231 bool FreeFormContinuation();
232 bool Continuation(
bool mightNeedFixedFormSpace);
233 std::optional<LineClassification> IsFixedFormCompilerDirectiveLine(
235 std::optional<LineClassification> IsFreeFormCompilerDirectiveLine(
237 LineClassification ClassifyLine(
const char *)
const;
238 LineClassification ClassifyLine(
240 bool SourceFormChange(std::string &&);
241 bool CompilerDirectiveContinuation(
TokenSequence &,
const char *sentinel);
249 bool preprocessingOnly_{
false};
250 bool expandIncludeLines_{
true};
251 bool isNestedInIncludeDirective_{
false};
252 bool backslashFreeFormContinuation_{
false};
253 bool inFixedForm_{
false};
254 int fixedFormColumnLimit_{72};
255 Encoding encoding_{Encoding::UTF_8};
256 int parenthesisNesting_{0};
257 int prescannerNesting_{0};
258 int continuationLines_{0};
259 bool isPossibleMacroCall_{
false};
260 bool afterPreprocessingDirective_{
false};
261 bool disableSourceContinuation_{
false};
264 const char *start_{
nullptr};
265 const char *limit_{
nullptr};
266 const char *nextLine_{
nullptr};
267 const char *directiveSentinel_{
nullptr};
271 const char *at_{
nullptr};
273 bool tabInCurrentLine_{
false};
274 bool slashInCurrentStatement_{
false};
275 bool preventHollerith_{
false};
276 bool inCharLiteral_{
false};
277 bool continuationInCharLiteral_{
false};
278 bool inPreprocessorDirective_{
false};
288 bool brokenToken_{
false};
295 bool omitNewline_{
false};
296 bool skipLeadingAmpersand_{
false};
298 const std::size_t firstCookedCharacterOffset_{cooked_.BufferedBytes()};
301 allSources_.CompilerInsertionProvenance(
' ')};
303 allSources_.CompilerInsertionProvenance(
'\\')};
307 static const int prime1{1019}, prime2{1021};
308 std::bitset<prime2> compilerDirectiveBloomFilter_;
309 std::unordered_set<std::string> compilerDirectiveSentinels_;