if (result.has_value()) {
// preserve any new messages
messages.Annex(state->messages());
- state->messages().swap(messages);
+ state->messages() = std::move(messages);
} else {
- state->swap(backtrack);
- state->messages().swap(messages);
+ *state = std::move(backtrack);
+ state->messages() = std::move(messages);
state->set_context(std::move(context));
}
return result;
std::optional<Success> Parse(ParseState *state) const {
Messages messages{std::move(state->messages())};
ParseState forked{*state};
- state->messages().swap(messages);
+ state->messages() = std::move(messages);
if (parser_.Parse(&forked)) {
return {};
}
std::optional<Success> Parse(ParseState *state) const {
Messages messages{std::move(state->messages())};
ParseState forked{*state};
- state->messages().swap(messages);
+ state->messages() = std::move(messages);
if (parser_.Parse(&forked).has_value()) {
return {Success{}};
}
if (std::optional<resultType> ax{pa_.Parse(state)}) {
// preserve any new messages
messages.Annex(state->messages());
- state->messages().swap(messages);
+ state->messages() = std::move(messages);
return ax;
}
ParseState paState{std::move(*state)};
- state->swap(backtrack);
+ *state = std::move(backtrack);
state->set_context(std::move(context));
if (std::optional<resultType> bx{pb_.Parse(state)}) {
// preserve any new messages
messages.Annex(state->messages());
- state->messages().swap(messages);
+ state->messages() = std::move(messages);
return bx;
}
// Both alternatives failed. Retain the state (and messages) from the
auto pbEnd = state->GetLocation();
if (paEnd > pbEnd) {
messages.Annex(paState.messages());
- state->swap(paState);
+ *state = std::move(paState);
} else if (paEnd < pbEnd) {
messages.Annex(state->messages());
} else {
// It's a tie.
messages.Annex(paState.messages());
}
- state->messages().swap(messages);
+ state->messages() = std::move(messages);
return {};
}
Messages messages{std::move(state->messages())};
Message::Context context{state->context()};
ParseState backtrack{*state};
+ bool originallyDeferred{state->deferMessages()};
+#if 0
+ state->set_deferMessages(true);
+#endif
std::optional<resultType> ax{pa_.Parse(state)};
- messages.Annex(state->messages());
+#if 0
+ if (!originallyDeferred && state->anyDeferredMessages()) {
+ CHECK(state->messages().empty());
+ *state = backtrack;
+ state->set_context(context);
+ ax = pa_.Parse(state);
+ CHECK(!state->messages().empty());
+ }
+#endif
if (ax.has_value()) {
- state->messages().swap(messages);
+ messages.Annex(state->messages());
+ state->messages() = std::move(messages);
+ state->set_context(std::move(context));
+ state->set_deferMessages(originallyDeferred);
return ax;
}
- state->swap(backtrack);
- state->set_context(std::move(context));
+ Messages paMessages{std::move(state->messages())};
+ *state = std::move(backtrack);
+ state->set_deferMessages(true);
std::optional<resultType> bx{pb_.Parse(state)};
- state->messages().swap(messages);
+ CHECK(state->messages().empty());
+ state->messages() = std::move(messages);
+ state->set_context(std::move(context));
+ state->set_deferMessages(originallyDeferred);
if (bx.has_value()) {
+ state->messages().Annex(paMessages);
state->set_anyErrorRecovery();
}
return bx;
Provenance Emit(
std::ostream &, const CookedSource &, bool echoSourceLine = true) const;
- void TakeReference() { ++refCount_; }
- void DropReference() { if (--refCount_ == 0) { delete this; } }
-
private:
Provenance provenance_;
const char *cookedSourceLocation_{nullptr};
std::string string_;
Context context_;
bool isFatal_{false};
- int refCount_{0};
};
class Messages {
explicit Messages(const CookedSource &cooked) : cooked_{cooked} {}
Messages(Messages &&that)
- : cooked_{that.cooked_}, messages_{std::move(that.messages_)},
- last_{that.last_} {}
+ : cooked_{that.cooked_}, messages_{std::move(that.messages_)} {
+ if (!messages_.empty()) {
+ last_ = that.last_;
+ that.last_ = that.messages_.before_begin();
+ }
+ }
Messages &operator=(Messages &&that) {
- swap(that);
+ messages_ = std::move(that.messages_);
+ if (messages_.empty()) {
+ last_ = messages_.before_begin();
+ } else {
+ last_ = that.last_;
+ that.last_ = that.messages_.before_begin();
+ }
return *this;
}
- void swap(Messages &that) {
- messages_.swap(that.messages_);
- std::swap(last_, that.last_);
- }
-
bool empty() const { return messages_.empty(); }
iterator begin() { return messages_.begin(); }
iterator end() { return messages_.end(); }
}
void Put(Message &&m) {
-// CHECK(IsValidLocation(m));
+ CHECK(IsValidLocation(m));
last_ = messages_.emplace_after(last_, std::move(m));
}
if (!that.messages_.empty()) {
messages_.splice_after(last_, that.messages_);
last_ = that.last_;
+ that.last_ = that.messages_.before_begin();
}
}
warnOnNonstandardUsage_{that.warnOnNonstandardUsage_},
warnOnDeprecatedUsage_{that.warnOnDeprecatedUsage_},
anyErrorRecovery_{that.anyErrorRecovery_},
- anyConformanceViolation_{that.anyConformanceViolation_} {}
+ anyConformanceViolation_{that.anyConformanceViolation_},
+ deferMessages_{that.deferMessages_} {}
ParseState(ParseState &&that)
: p_{that.p_}, limit_{that.limit_}, messages_{std::move(that.messages_)},
context_{std::move(that.context_)}, userState_{that.userState_},
warnOnNonstandardUsage_{that.warnOnNonstandardUsage_},
warnOnDeprecatedUsage_{that.warnOnDeprecatedUsage_},
anyErrorRecovery_{that.anyErrorRecovery_},
- anyConformanceViolation_{that.anyConformanceViolation_} {}
- ParseState &operator=(ParseState &&that) {
- swap(that);
+ anyConformanceViolation_{that.anyConformanceViolation_},
+ deferMessages_{that.deferMessages_},
+ anyDeferredMessages_{that.anyDeferredMessages_} {}
+ ParseState &operator=(const ParseState &that) {
+ p_ = that.p_, limit_ = that.limit_;
+ userState_ = that.userState_, inFixedForm_ = that.inFixedForm_;
+ encoding_ = that.encoding_, strictConformance_ = that.strictConformance_;
+ warnOnNonstandardUsage_ = that.warnOnNonstandardUsage_;
+ warnOnDeprecatedUsage_ = that.warnOnDeprecatedUsage_;
+ anyErrorRecovery_ = that.anyErrorRecovery_;
+ anyConformanceViolation_ = that.anyConformanceViolation_;
+ deferMessages_ = that.deferMessages_;
+ anyDeferredMessages_ = that.anyDeferredMessages_;
return *this;
}
-
- void swap(ParseState &that) {
- constexpr std::size_t bytes{sizeof *this};
- char buffer[bytes];
- std::memcpy(buffer, this, bytes);
- std::memcpy(this, &that, bytes);
- std::memcpy(&that, buffer, bytes);
+ ParseState &operator=(ParseState &&that) {
+ p_ = that.p_, limit_ = that.limit_, messages_ = std::move(that.messages_);
+ userState_ = that.userState_, inFixedForm_ = that.inFixedForm_;
+ encoding_ = that.encoding_, strictConformance_ = that.strictConformance_;
+ warnOnNonstandardUsage_ = that.warnOnNonstandardUsage_;
+ warnOnDeprecatedUsage_ = that.warnOnDeprecatedUsage_;
+ anyErrorRecovery_ = that.anyErrorRecovery_;
+ anyConformanceViolation_ = that.anyConformanceViolation_;
+ deferMessages_ = that.deferMessages_;
+ anyDeferredMessages_ = that.anyDeferredMessages_;
+ return *this;
}
Messages &messages() { return messages_; }
return *this;
}
+ bool deferMessages() const { return deferMessages_; }
+ ParseState &set_deferMessages(bool yes) {
+ deferMessages_ = yes;
+ return *this;
+ }
+
+ bool anyDeferredMessages() const { return anyDeferredMessages_; }
+
const char *GetLocation() const { return p_; }
void PushContext(MessageFixedText text) {
void Say(MessageExpectedText &&t) { return Say(p_, std::move(t)); }
void Say(const char *at, MessageFixedText t) {
- messages_.Say(at, t, context_.get());
+ if (deferMessages_) {
+ anyDeferredMessages_ = true;
+ } else {
+ messages_.Say(at, t, context_.get());
+ }
}
void Say(const char *at, MessageFormattedText &&t) {
- messages_.Say(at, std::move(t), context_.get());
+ if (deferMessages_) {
+ anyDeferredMessages_ = true;
+ } else {
+ messages_.Say(at, std::move(t), context_.get());
+ }
}
void Say(const char *at, MessageExpectedText &&t) {
- messages_.Say(at, std::move(t), context_.get());
+ if (deferMessages_) {
+ anyDeferredMessages_ = true;
+ } else {
+ messages_.Say(at, std::move(t), context_.get());
+ }
}
bool IsAtEnd() const { return p_ >= limit_; }
bool warnOnDeprecatedUsage_{false};
bool anyErrorRecovery_{false};
bool anyConformanceViolation_{false};
+ bool deferMessages_{false};
+ bool anyDeferredMessages_{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!
.set_warnOnDeprecatedUsage(options_.isStrictlyStandard)
.set_userState(&userState);
parseTree_ = program.Parse(&parseState);
-#if 0 // pmk
CHECK(
!parseState.anyErrorRecovery() || parseState.messages().AnyFatalError());
-#endif
consumedWholeFile_ = parseState.IsAtEnd();
finalRestingPlace_ = parseState.GetLocation();
messages_.Annex(parseState.messages());