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 std::optional<CharBlock> GetKeywordMacroName(
const char *)
const;
87 const char *IsCompilerDirectiveSentinel(
const char *, std::size_t)
const;
88 const char *IsCompilerDirectiveSentinel(
CharBlock)
const;
90 std::optional<std::pair<const char *, const char *>>
91 IsCompilerDirectiveSentinel(
const char *p)
const;
93 template <
typename... A>
Message &Say(A &&...a) {
94 return messages_.Say(std::forward<A>(a)...);
96 template <
typename... A>
97 Message *Warn(common::UsageWarning warning, A &&...a) {
98 return messages_.Warn(
false, features_, warning, std::forward<A>(a)...);
100 template <
typename... A>
101 Message *Warn(common::LanguageFeature feature, A &&...a) {
102 return messages_.Warn(
false, features_, feature, std::forward<A>(a)...);
106 struct LineClassification {
109 ConditionalCompilationDirective,
112 PreprocessorDirective,
115 CompilerDirectiveAfterMacroExpansion,
118 LineClassification(Kind k, std::size_t po = 0,
const char *s =
nullptr)
119 : kind{k}, payloadOffset{po}, sentinel{s} {}
120 LineClassification(LineClassification &&) =
default;
121 LineClassification &operator=(LineClassification &&) =
default;
123 std::size_t payloadOffset;
124 const char *sentinel;
127 void BeginSourceLine(
const char *at) {
130 tabInCurrentLine_ =
false;
133 void BeginSourceLineAndAdvance() {
134 BeginSourceLine(nextLine_);
138 void BeginStatementAndAdvance() {
139 BeginSourceLineAndAdvance();
140 slashInCurrentStatement_ =
false;
141 preventHollerith_ =
false;
142 parenthesisNesting_ = 0;
143 continuationLines_ = 0;
144 isPossibleMacroCall_ =
false;
145 disableSourceContinuation_ =
false;
148 Provenance GetProvenance(
const char *sourceChar)
const {
149 return startProvenance_ + (sourceChar - start_);
152 ProvenanceRange GetProvenanceRange(
153 const char *first,
const char *afterLast)
const {
154 std::size_t bytes = afterLast - first;
155 return {startProvenance_ + (first - start_), bytes};
159 tokens.PutNextTokenChar(ch, GetCurrentProvenance());
163 Provenance provenance{allSources().CompilerInsertionProvenance(ch)};
164 tokens.PutNextTokenChar(ch, provenance);
168 EmitChar(tokens, ch);
173 bool IsOpenMPConditionalLine(
const char *sentinel)
const {
174 return sentinel && sentinel[0] ==
'$' && !sentinel[1];
176 bool IsOpenACCConditionalLine(
const char *sentinel)
const {
177 return sentinel && sentinel[0] ==
'@' && sentinel[1] ==
'a' &&
178 sentinel[2] ==
'c' && sentinel[3] ==
'c' && sentinel[4] ==
'\0';
180 bool IsCUDAConditionalLine(
const char *sentinel)
const {
181 return sentinel && sentinel[0] ==
'@' && sentinel[1] ==
'c' &&
182 sentinel[2] ==
'u' && sentinel[3] ==
'f' && sentinel[4] ==
'\0';
184 bool InCompilerDirective()
const {
return directiveSentinel_ !=
nullptr; }
185 bool InOpenMPConditionalLine()
const {
186 return IsOpenMPConditionalLine(directiveSentinel_);
188 bool InOpenACCConditionalLine()
const {
189 return IsOpenACCConditionalLine(directiveSentinel_);
191 bool InCUDAConditionalLine()
const {
192 return IsCUDAConditionalLine(directiveSentinel_);
194 bool InOpenACCOrCUDAConditionalLine()
const {
195 return InOpenACCConditionalLine() || InCUDAConditionalLine();
197 bool InConditionalLine()
const {
198 return InOpenMPConditionalLine() || InOpenACCOrCUDAConditionalLine();
200 bool IsOpenMPDirective()
const {
201 return directiveSentinel_ && std::strcmp(directiveSentinel_,
"$omp") == 0;
203 bool InFixedFormSource()
const {
204 return inFixedForm_ && !inPreprocessorDirective_ && !InCompilerDirective();
207 bool IsCComment(
const char *p)
const {
208 return p[0] ==
'/' && p[1] ==
'*' &&
209 (inPreprocessorDirective_ ||
212 common::LanguageFeature::ClassicCComments)));
218 void SkipToEndOfLine();
219 bool MustSkipToEndOfLine()
const;
222 bool SkipToNextSignificantCharacter();
223 void SkipCComments();
225 static const char *SkipWhiteSpace(
const char *);
226 const char *SkipWhiteSpaceIncludingEmptyMacros(
const char *)
const;
227 const char *SkipWhiteSpaceAndCComments(
const char *)
const;
228 const char *SkipCComment(
const char *)
const;
233 void QuotedCharacterLiteral(
TokenSequence &,
const char *start);
234 void Hollerith(
TokenSequence &,
int count,
const char *start);
236 bool SkipCommentLine(
bool afterAmpersand);
237 bool IsFixedFormCommentLine(
const char *)
const;
238 const char *IsFreeFormComment(
const char *)
const;
239 std::optional<std::size_t> IsIncludeLine(
const char *)
const;
240 void FortranInclude(
const char *quote);
241 const char *IsPreprocessorDirectiveLine(
const char *)
const;
242 const char *FixedFormContinuationLine(
bool atNewline);
243 const char *FreeFormContinuationLine(
bool ampersand);
244 bool IsImplicitContinuation()
const;
245 bool FixedFormContinuation(
bool atNewline);
246 bool FreeFormContinuation();
247 bool Continuation(
bool mightNeedFixedFormSpace);
248 std::optional<LineClassification> IsFixedFormCompilerDirectiveLine(
250 std::optional<LineClassification> IsFreeFormCompilerDirectiveLine(
252 LineClassification ClassifyLine(
const char *)
const;
253 LineClassification ClassifyLine(
255 bool SourceFormChange(std::string &&);
256 bool CompilerDirectiveContinuation(
TokenSequence &,
const char *sentinel);
258 std::optional<LineClassification>
259 IsCompilerDirectiveSentinelAfterKeywordMacro(
const char *p)
const;
266 bool preprocessingOnly_{
false};
267 bool expandIncludeLines_{
true};
268 bool isNestedInIncludeDirective_{
false};
269 bool backslashFreeFormContinuation_{
false};
270 bool inFixedForm_{
false};
271 int fixedFormColumnLimit_{72};
272 Encoding encoding_{Encoding::UTF_8};
273 int parenthesisNesting_{0};
274 int prescannerNesting_{0};
275 int continuationLines_{0};
276 bool isPossibleMacroCall_{
false};
277 bool afterPreprocessingDirective_{
false};
278 bool disableSourceContinuation_{
false};
281 const char *start_{
nullptr};
282 const char *limit_{
nullptr};
283 const char *nextLine_{
nullptr};
284 const char *directiveSentinel_{
nullptr};
288 const char *at_{
nullptr};
290 bool tabInCurrentLine_{
false};
291 bool slashInCurrentStatement_{
false};
292 bool preventHollerith_{
false};
293 bool inCharLiteral_{
false};
294 bool continuationInCharLiteral_{
false};
295 bool inPreprocessorDirective_{
false};
305 bool brokenToken_{
false};
312 bool omitNewline_{
false};
313 bool skipLeadingAmpersand_{
false};
315 const std::size_t firstCookedCharacterOffset_{cooked_.BufferedBytes()};
318 allSources().CompilerInsertionProvenance(
' ')};
320 allSources().CompilerInsertionProvenance(
'\\')};
324 static const int prime1{1019}, prime2{1021};
325 std::bitset<prime2> compilerDirectiveBloomFilter_;
326 std::unordered_set<std::string> compilerDirectiveSentinels_;