2018-02-16 11:42:17 -08:00
|
|
|
#ifndef FORTRAN_PARSER_PRESCAN_H_
|
|
|
|
#define FORTRAN_PARSER_PRESCAN_H_
|
2018-01-30 11:54:47 -08:00
|
|
|
|
|
|
|
// Defines a fast Fortran source prescanning phase that implements some
|
|
|
|
// character-level features of the language that can be inefficient to
|
|
|
|
// support directly in a backtracking parser. This phase handles Fortran
|
|
|
|
// line continuation, comment removal, card image margins, padding out
|
2018-02-13 12:24:54 -08:00
|
|
|
// fixed form character literals on truncated card images, file
|
|
|
|
// inclusion, and driving the Fortran source preprocessor.
|
2018-01-30 11:54:47 -08:00
|
|
|
|
2018-02-28 16:56:10 -08:00
|
|
|
#include "characters.h"
|
2018-02-16 16:57:40 -08:00
|
|
|
#include "message.h"
|
2018-02-09 14:04:11 -08:00
|
|
|
#include "provenance.h"
|
2018-02-13 12:50:47 -08:00
|
|
|
#include "token-sequence.h"
|
2018-01-30 11:54:47 -08:00
|
|
|
#include <optional>
|
2018-02-09 14:04:11 -08:00
|
|
|
#include <string>
|
2018-01-30 11:54:47 -08:00
|
|
|
|
|
|
|
namespace Fortran {
|
2018-02-07 12:04:42 -08:00
|
|
|
namespace parser {
|
2018-01-30 11:54:47 -08:00
|
|
|
|
2018-02-13 12:50:47 -08:00
|
|
|
class Messages;
|
|
|
|
class Preprocessor;
|
|
|
|
|
2018-01-30 11:54:47 -08:00
|
|
|
class Prescanner {
|
2018-02-05 12:54:36 -08:00
|
|
|
public:
|
2018-02-13 12:24:54 -08:00
|
|
|
Prescanner(Messages *, CookedSource *, Preprocessor *);
|
2018-02-13 14:22:08 -08:00
|
|
|
Prescanner(const Prescanner &);
|
2018-02-01 15:01:23 -08:00
|
|
|
|
2018-02-12 14:43:16 -08:00
|
|
|
Messages *messages() const { return messages_; }
|
2018-01-30 11:54:47 -08:00
|
|
|
|
|
|
|
Prescanner &set_fixedForm(bool yes) {
|
|
|
|
inFixedForm_ = yes;
|
|
|
|
return *this;
|
|
|
|
}
|
2018-02-28 16:56:10 -08:00
|
|
|
Prescanner &set_encoding(Encoding code) {
|
|
|
|
encoding_ = code;
|
|
|
|
return *this;
|
|
|
|
}
|
2018-01-30 11:54:47 -08:00
|
|
|
Prescanner &set_enableOldDebugLines(bool yes) {
|
|
|
|
enableOldDebugLines_ = yes;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
Prescanner &set_enableBackslashEscapesInCharLiterals(bool yes) {
|
|
|
|
enableBackslashEscapesInCharLiterals_ = yes;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
Prescanner &set_fixedFormColumnLimit(int limit) {
|
|
|
|
fixedFormColumnLimit_ = limit;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2018-02-13 12:24:54 -08:00
|
|
|
bool Prescan(ProvenanceRange);
|
2018-02-13 14:22:08 -08:00
|
|
|
|
|
|
|
// Callbacks for use by Preprocessor.
|
2018-01-30 11:54:47 -08:00
|
|
|
std::optional<TokenSequence> NextTokenizedLine();
|
2018-02-09 14:04:11 -08:00
|
|
|
Provenance GetCurrentProvenance() const { return GetProvenance(at_); }
|
2018-02-20 09:57:30 -08:00
|
|
|
Message &Complain(MessageFixedText);
|
2018-02-21 12:12:52 -08:00
|
|
|
Message &Complain(MessageFormattedText &&);
|
2018-01-30 11:54:47 -08:00
|
|
|
|
2018-02-05 12:54:36 -08:00
|
|
|
private:
|
2018-02-01 12:08:02 -08:00
|
|
|
void BeginSourceLine(const char *at) {
|
2018-01-30 11:54:47 -08:00
|
|
|
at_ = at;
|
2018-02-12 11:56:42 -08:00
|
|
|
column_ = 1;
|
2018-01-30 11:54:47 -08:00
|
|
|
tabInCurrentLine_ = false;
|
|
|
|
preventHollerith_ = false;
|
2018-01-30 15:22:26 -08:00
|
|
|
delimiterNesting_ = 0;
|
2018-01-30 11:54:47 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void BeginSourceLineAndAdvance() {
|
|
|
|
BeginSourceLine(lineStart_);
|
|
|
|
NextLine();
|
|
|
|
}
|
|
|
|
|
2018-02-09 14:04:11 -08:00
|
|
|
Provenance GetProvenance(const char *sourceChar) const {
|
2018-02-15 10:42:36 -08:00
|
|
|
return startProvenance_ + (sourceChar - start_);
|
2018-02-09 14:04:11 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void EmitChar(TokenSequence *tokens, char ch) {
|
|
|
|
tokens->PutNextTokenChar(ch, GetCurrentProvenance());
|
|
|
|
}
|
|
|
|
|
2018-02-16 11:14:11 -08:00
|
|
|
void EmitInsertedChar(TokenSequence *tokens, char ch) {
|
|
|
|
Provenance provenance{
|
|
|
|
cooked_->allSources()->CompilerInsertionProvenance(ch)};
|
|
|
|
tokens->PutNextTokenChar(ch, provenance);
|
|
|
|
}
|
|
|
|
|
2018-01-30 11:54:47 -08:00
|
|
|
char EmitCharAndAdvance(TokenSequence *tokens, char ch) {
|
2018-02-09 14:04:11 -08:00
|
|
|
EmitChar(tokens, ch);
|
2018-01-30 11:54:47 -08:00
|
|
|
NextChar();
|
|
|
|
return *at_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void NextLine();
|
2018-01-30 15:22:26 -08:00
|
|
|
void LabelField(TokenSequence *);
|
2018-01-30 11:54:47 -08:00
|
|
|
void NextChar();
|
|
|
|
void SkipSpaces();
|
|
|
|
bool NextToken(TokenSequence *);
|
|
|
|
bool ExponentAndKind(TokenSequence *);
|
|
|
|
void QuotedCharacterLiteral(TokenSequence *);
|
2018-02-28 16:56:10 -08:00
|
|
|
void Hollerith(TokenSequence *, int);
|
2018-02-16 11:14:11 -08:00
|
|
|
bool PadOutCharacterLiteral(TokenSequence *);
|
2018-01-30 15:22:26 -08:00
|
|
|
bool CommentLines();
|
|
|
|
bool CommentLinesAndPreprocessorDirectives();
|
2018-01-30 11:54:47 -08:00
|
|
|
bool IsFixedFormCommentLine(const char *);
|
|
|
|
bool IsFreeFormComment(const char *);
|
2018-02-13 14:22:08 -08:00
|
|
|
bool IncludeLine(const char *);
|
2018-01-30 11:54:47 -08:00
|
|
|
bool IsPreprocessorDirectiveLine(const char *);
|
|
|
|
const char *FixedFormContinuationLine();
|
|
|
|
bool FixedFormContinuation();
|
|
|
|
bool FreeFormContinuation();
|
2018-02-15 10:42:36 -08:00
|
|
|
void PayNewlineDebt(Provenance);
|
2018-01-30 11:54:47 -08:00
|
|
|
|
2018-02-12 14:43:16 -08:00
|
|
|
Messages *messages_;
|
2018-02-13 12:24:54 -08:00
|
|
|
CookedSource *cooked_;
|
|
|
|
Preprocessor *preprocessor_;
|
2018-02-09 14:04:11 -08:00
|
|
|
|
2018-02-15 10:42:36 -08:00
|
|
|
Provenance startProvenance_;
|
2018-02-13 12:24:54 -08:00
|
|
|
const char *start_{nullptr}; // beginning of current source file content
|
|
|
|
const char *limit_{nullptr}; // first address after end of current source
|
2018-01-30 11:54:47 -08:00
|
|
|
const char *at_{nullptr}; // next character to process; < lineStart_
|
|
|
|
int column_{1}; // card image column position of next character
|
2018-02-09 14:04:11 -08:00
|
|
|
const char *lineStart_{nullptr}; // next line to process; <= limit_
|
|
|
|
bool tabInCurrentLine_{false};
|
|
|
|
bool preventHollerith_{false};
|
|
|
|
|
|
|
|
bool anyFatalErrors_{false};
|
2018-01-30 11:54:47 -08:00
|
|
|
int newlineDebt_{0}; // newline characters consumed but not yet emitted
|
|
|
|
bool inCharLiteral_{false};
|
|
|
|
bool inPreprocessorDirective_{false};
|
2018-02-15 15:56:50 -08:00
|
|
|
bool inFixedForm_{false};
|
2018-01-30 11:54:47 -08:00
|
|
|
int fixedFormColumnLimit_{72};
|
2018-02-28 16:56:10 -08:00
|
|
|
Encoding encoding_{Encoding::UTF8};
|
2018-01-30 11:54:47 -08:00
|
|
|
bool enableOldDebugLines_{false};
|
|
|
|
bool enableBackslashEscapesInCharLiterals_{true};
|
2018-01-30 15:22:26 -08:00
|
|
|
int delimiterNesting_{0};
|
2018-02-13 12:24:54 -08:00
|
|
|
Provenance spaceProvenance_{
|
|
|
|
cooked_->allSources()->CompilerInsertionProvenance(' ')};
|
2018-02-16 11:14:11 -08:00
|
|
|
Provenance backslashProvenance_{
|
|
|
|
cooked_->allSources()->CompilerInsertionProvenance('\\')};
|
2018-02-28 16:56:10 -08:00
|
|
|
ProvenanceRange sixSpaceProvenance_{
|
|
|
|
cooked_->allSources()->AddCompilerInsertion(" "s)};
|
2018-01-30 11:54:47 -08:00
|
|
|
};
|
2018-02-07 12:04:42 -08:00
|
|
|
} // namespace parser
|
2018-01-30 11:54:47 -08:00
|
|
|
} // namespace Fortran
|
2018-02-16 11:42:17 -08:00
|
|
|
#endif // FORTRAN_PARSER_PRESCAN_H_
|