mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 12:16:06 +00:00

an intermediate "parser" namespace. Original-commit: flang-compiler/f18@690b6f0d1e Reviewed-on: https://github.com/flang-compiler/f18/pull/4 Tree-same-pre-rewrite: false
235 lines
7.0 KiB
C++
235 lines
7.0 KiB
C++
#ifndef FORTRAN_PARSE_STATE_H_
|
|
#define FORTRAN_PARSE_STATE_H_
|
|
|
|
// Defines the ParseState type used as the argument for every parser's
|
|
// Parse member or static function. Tracks position, context, accumulated
|
|
// messages, and an arbitrary UserState instance for parsing attempts.
|
|
// Must be efficient to duplicate and assign for backtracking and recovery
|
|
// during parsing!
|
|
|
|
#include "idioms.h"
|
|
#include "message.h"
|
|
#include "position.h"
|
|
#include <cstring>
|
|
#include <list>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <utility>
|
|
|
|
namespace Fortran {
|
|
namespace parser {
|
|
|
|
class UserState;
|
|
|
|
class ParseState {
|
|
public:
|
|
ParseState() {}
|
|
ParseState(const char *str) : p_{str}, remaining_{std::strlen(str)} {}
|
|
ParseState(const char *str, size_t bytes) : p_{str}, remaining_{bytes} {}
|
|
ParseState(const ParseState &that)
|
|
: p_{that.p_}, remaining_{that.remaining_}, position_{that.position_},
|
|
userState_{that.userState_}, inCharLiteral_{that.inCharLiteral_},
|
|
inFortran_{that.inFortran_}, inFixedForm_{that.inFixedForm_},
|
|
enableOldDebugLines_{that.enableOldDebugLines_}, columns_{that.columns_},
|
|
enableBackslashEscapesInCharLiterals_{
|
|
that.enableBackslashEscapesInCharLiterals_},
|
|
strictConformance_{that.strictConformance_},
|
|
warnOnNonstandardUsage_{that.warnOnNonstandardUsage_},
|
|
warnOnDeprecatedUsage_{that.warnOnDeprecatedUsage_},
|
|
skippedNewLines_{that.skippedNewLines_},
|
|
tabInCurrentLine_{that.tabInCurrentLine_},
|
|
anyErrorRecovery_{that.anyErrorRecovery_}, prescanned_{that.prescanned_} {
|
|
}
|
|
ParseState(ParseState &&that)
|
|
: p_{that.p_}, remaining_{that.remaining_}, position_{that.position_},
|
|
messages_{std::move(that.messages_)}, context_{std::move(that.context_)},
|
|
userState_{that.userState_}, inCharLiteral_{that.inCharLiteral_},
|
|
inFortran_{that.inFortran_}, inFixedForm_{that.inFixedForm_},
|
|
enableOldDebugLines_{that.enableOldDebugLines_}, columns_{that.columns_},
|
|
enableBackslashEscapesInCharLiterals_{
|
|
that.enableBackslashEscapesInCharLiterals_},
|
|
strictConformance_{that.strictConformance_},
|
|
warnOnNonstandardUsage_{that.warnOnNonstandardUsage_},
|
|
warnOnDeprecatedUsage_{that.warnOnDeprecatedUsage_},
|
|
skippedNewLines_{that.skippedNewLines_},
|
|
tabInCurrentLine_{that.tabInCurrentLine_},
|
|
anyErrorRecovery_{that.anyErrorRecovery_}, prescanned_{that.prescanned_} {
|
|
}
|
|
ParseState &operator=(ParseState &&that) {
|
|
swap(that);
|
|
return *this;
|
|
}
|
|
|
|
void swap(ParseState &that) {
|
|
constexpr size_t bytes{sizeof *this};
|
|
char buffer[bytes];
|
|
std::memcpy(buffer, this, bytes);
|
|
std::memcpy(this, &that, bytes);
|
|
std::memcpy(&that, buffer, bytes);
|
|
}
|
|
|
|
Position position() const { return position_; }
|
|
|
|
bool anyErrorRecovery() const { return anyErrorRecovery_; }
|
|
void set_anyErrorRecovery() { anyErrorRecovery_ = true; }
|
|
|
|
UserState *userState() const { return userState_; }
|
|
void set_userState(UserState *u) { userState_ = u; }
|
|
|
|
Messages *messages() { return &messages_; }
|
|
|
|
MessageContext context() const { return context_; }
|
|
MessageContext set_context(MessageContext c) {
|
|
MessageContext was{context_};
|
|
context_ = c;
|
|
return was;
|
|
}
|
|
|
|
void PushContext(const std::string &str) {
|
|
context_ = std::make_shared<Message>(position_, str, context_);
|
|
}
|
|
void PushContext(std::string &&str) {
|
|
context_ = std::make_shared<Message>(position_, std::move(str), context_);
|
|
}
|
|
void PushContext(const char *str) {
|
|
context_ = std::make_shared<Message>(position_, str, context_);
|
|
}
|
|
|
|
void PopContext() {
|
|
if (context_) {
|
|
context_ = context_->context();
|
|
}
|
|
}
|
|
|
|
bool inCharLiteral() const { return inCharLiteral_; }
|
|
bool set_inCharLiteral(bool yes) {
|
|
bool was{inCharLiteral_};
|
|
inCharLiteral_ = yes;
|
|
return was;
|
|
}
|
|
|
|
bool inFortran() const { return inFortran_; }
|
|
bool set_inFortran(bool yes) {
|
|
bool was{inFortran_};
|
|
inFortran_ = yes;
|
|
return was;
|
|
}
|
|
|
|
bool inFixedForm() const { return inFixedForm_; }
|
|
bool set_inFixedForm(bool yes) {
|
|
bool was{inFixedForm_};
|
|
inFixedForm_ = yes;
|
|
return was;
|
|
}
|
|
|
|
bool enableOldDebugLines() const { return enableOldDebugLines_; }
|
|
bool set_enableOldDebugLines(bool yes) {
|
|
bool was{enableOldDebugLines_};
|
|
enableOldDebugLines_ = yes;
|
|
return was;
|
|
}
|
|
|
|
int columns() const { return columns_; }
|
|
int set_columns(int cols) {
|
|
int was{columns_};
|
|
columns_ = cols;
|
|
return was;
|
|
}
|
|
|
|
bool enableBackslashEscapesInCharLiterals() const {
|
|
return enableBackslashEscapesInCharLiterals_;
|
|
}
|
|
bool set_enableBackslashEscapesInCharLiterals(bool yes) {
|
|
bool was{enableBackslashEscapesInCharLiterals_};
|
|
enableBackslashEscapesInCharLiterals_ = yes;
|
|
return was;
|
|
}
|
|
|
|
bool strictConformance() const { return strictConformance_; }
|
|
bool set_strictConformance(bool yes) {
|
|
bool was{strictConformance_};
|
|
strictConformance_ = yes;
|
|
return was;
|
|
}
|
|
|
|
bool warnOnNonstandardUsage() const { return warnOnNonstandardUsage_; }
|
|
bool set_warnOnNonstandardUsage(bool yes) {
|
|
bool was{warnOnNonstandardUsage_};
|
|
warnOnNonstandardUsage_ = yes;
|
|
return was;
|
|
}
|
|
|
|
bool warnOnDeprecatedUsage() const { return warnOnDeprecatedUsage_; }
|
|
bool set_warnOnDeprecatedUsage(bool yes) {
|
|
bool was{warnOnDeprecatedUsage_};
|
|
warnOnDeprecatedUsage_ = yes;
|
|
return was;
|
|
}
|
|
|
|
int skippedNewLines() const { return skippedNewLines_; }
|
|
void set_skippedNewLines(int n) { skippedNewLines_ = n; }
|
|
|
|
bool prescanned() const { return prescanned_; }
|
|
void set_prescanned(bool yes) { prescanned_ = yes; }
|
|
|
|
bool tabInCurrentLine() const { return tabInCurrentLine_; }
|
|
|
|
bool IsAtEnd() const { return remaining_ == 0; }
|
|
|
|
std::optional<char> GetNextRawChar() const {
|
|
if (remaining_ > 0) {
|
|
return {*p_};
|
|
}
|
|
return {};
|
|
}
|
|
|
|
void Advance() {
|
|
CHECK(remaining_ > 0);
|
|
--remaining_;
|
|
if (*p_ == '\n') {
|
|
position_.AdvanceLine();
|
|
tabInCurrentLine_ = false;
|
|
} else if (*p_ == '\t') {
|
|
position_.TabAdvanceColumn();
|
|
tabInCurrentLine_ = true;
|
|
} else {
|
|
position_.AdvanceColumn();
|
|
}
|
|
++p_;
|
|
}
|
|
|
|
void AdvancePositionForPadding() { position_.AdvanceColumn(); }
|
|
|
|
private:
|
|
// Text remaining to be parsed
|
|
const char *p_{nullptr};
|
|
size_t remaining_{0};
|
|
Position position_;
|
|
|
|
// Accumulated messages and current nested context.
|
|
Messages messages_;
|
|
MessageContext context_;
|
|
|
|
UserState *userState_{nullptr};
|
|
|
|
bool inCharLiteral_{false};
|
|
bool inFortran_{true};
|
|
bool inFixedForm_{false};
|
|
bool enableOldDebugLines_{false};
|
|
int columns_{72};
|
|
bool enableBackslashEscapesInCharLiterals_{true};
|
|
bool strictConformance_{false};
|
|
bool warnOnNonstandardUsage_{false};
|
|
bool warnOnDeprecatedUsage_{false};
|
|
int skippedNewLines_{0};
|
|
bool tabInCurrentLine_{false};
|
|
bool anyErrorRecovery_{false};
|
|
bool prescanned_{false};
|
|
// NOTE: Any additions or modifications to these data members must also be
|
|
// reflected in the copy and move constructors defined at the top of this
|
|
// class definition!
|
|
};
|
|
} // namespace parser
|
|
} // namespace Fortran
|
|
#endif // FORTRAN_PARSE_STATE_H_
|