Warning: This file is not a C or C++ file. It does not have highlighting.

1//===-- include/flang/Parser/parse-state.h ----------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef FORTRAN_PARSER_PARSE_STATE_H_
10#define FORTRAN_PARSER_PARSE_STATE_H_
11
12// Defines the ParseState type used as the argument for every parser's
13// Parse member or static function. Tracks source provenance, context,
14// accumulated messages, and an arbitrary UserState instance for parsing
15// attempts. Must be efficient to duplicate and assign for backtracking
16// and recovery during parsing!
17
18#include "user-state.h"
19#include "flang/Common/Fortran-features.h"
20#include "flang/Common/idioms.h"
21#include "flang/Parser/characters.h"
22#include "flang/Parser/message.h"
23#include "flang/Parser/provenance.h"
24#include <cstddef>
25#include <cstring>
26#include <list>
27#include <memory>
28#include <optional>
29#include <utility>
30
31namespace Fortran::parser {
32
33using common::LanguageFeature;
34
35class ParseState {
36public:
37 ParseState(const CookedSource &cooked)
38 : p_{cooked.AsCharBlock().begin()}, limit_{cooked.AsCharBlock().end()} {}
39 ParseState(const ParseState &that)
40 : p_{that.p_}, limit_{that.limit_}, context_{that.context_},
41 userState_{that.userState_}, inFixedForm_{that.inFixedForm_},
42 anyErrorRecovery_{that.anyErrorRecovery_},
43 anyConformanceViolation_{that.anyConformanceViolation_},
44 deferMessages_{that.deferMessages_},
45 anyDeferredMessages_{that.anyDeferredMessages_},
46 anyTokenMatched_{that.anyTokenMatched_} {}
47 ParseState(ParseState &&that)
48 : p_{that.p_}, limit_{that.limit_}, messages_{std::move(that.messages_)},
49 context_{std::move(that.context_)}, userState_{that.userState_},
50 inFixedForm_{that.inFixedForm_},
51 anyErrorRecovery_{that.anyErrorRecovery_},
52 anyConformanceViolation_{that.anyConformanceViolation_},
53 deferMessages_{that.deferMessages_},
54 anyDeferredMessages_{that.anyDeferredMessages_},
55 anyTokenMatched_{that.anyTokenMatched_} {}
56 ParseState &operator=(const ParseState &that) {
57 p_ = that.p_, limit_ = that.limit_, context_ = that.context_;
58 userState_ = that.userState_, inFixedForm_ = that.inFixedForm_;
59 anyErrorRecovery_ = that.anyErrorRecovery_;
60 anyConformanceViolation_ = that.anyConformanceViolation_;
61 deferMessages_ = that.deferMessages_;
62 anyDeferredMessages_ = that.anyDeferredMessages_;
63 anyTokenMatched_ = that.anyTokenMatched_;
64 return *this;
65 }
66 ParseState &operator=(ParseState &&that) {
67 p_ = that.p_, limit_ = that.limit_, messages_ = std::move(that.messages_);
68 context_ = std::move(that.context_);
69 userState_ = that.userState_, inFixedForm_ = that.inFixedForm_;
70 anyErrorRecovery_ = that.anyErrorRecovery_;
71 anyConformanceViolation_ = that.anyConformanceViolation_;
72 deferMessages_ = that.deferMessages_;
73 anyDeferredMessages_ = that.anyDeferredMessages_;
74 anyTokenMatched_ = that.anyTokenMatched_;
75 return *this;
76 }
77
78 const Messages &messages() const { return messages_; }
79 Messages &messages() { return messages_; }
80
81 const Message::Reference &context() const { return context_; }
82 Message::Reference &context() { return context_; }
83
84 bool anyErrorRecovery() const { return anyErrorRecovery_; }
85 void set_anyErrorRecovery() { anyErrorRecovery_ = true; }
86
87 bool anyConformanceViolation() const { return anyConformanceViolation_; }
88 void set_anyConformanceViolation() { anyConformanceViolation_ = true; }
89
90 UserState *userState() const { return userState_; }
91 ParseState &set_userState(UserState *u) {
92 userState_ = u;
93 return *this;
94 }
95
96 bool inFixedForm() const { return inFixedForm_; }
97 ParseState &set_inFixedForm(bool yes = true) {
98 inFixedForm_ = yes;
99 return *this;
100 }
101
102 bool deferMessages() const { return deferMessages_; }
103 ParseState &set_deferMessages(bool yes = true) {
104 deferMessages_ = yes;
105 return *this;
106 }
107
108 bool anyDeferredMessages() const { return anyDeferredMessages_; }
109 ParseState &set_anyDeferredMessages(bool yes = true) {
110 anyDeferredMessages_ = yes;
111 return *this;
112 }
113
114 bool anyTokenMatched() const { return anyTokenMatched_; }
115 ParseState &set_anyTokenMatched(bool yes = true) {
116 anyTokenMatched_ = yes;
117 return *this;
118 }
119
120 const char *GetLocation() const { return p_; }
121
122 void PushContext(MessageFixedText text) {
123 auto m{new Message{p_, text}}; // reference-counted
124 m->SetContext(context_.get());
125 context_ = Message::Reference{m};
126 }
127
128 void PopContext() {
129 CHECK(context_);
130 context_ = context_->attachment();
131 }
132
133 template <typename... A> void Say(CharBlock range, A &&...args) {
134 if (deferMessages_) {
135 anyDeferredMessages_ = true;
136 } else {
137 messages_.Say(range, std::forward<A>(args)...).SetContext(context_.get());
138 }
139 }
140 template <typename... A> void Say(const MessageFixedText &text, A &&...args) {
141 Say(p_, text, std::forward<A>(args)...);
142 }
143 template <typename... A>
144 void Say(const MessageExpectedText &text, A &&...args) {
145 Say(p_, text, std::forward<A>(args)...);
146 }
147
148 void Nonstandard(LanguageFeature lf, const MessageFixedText &msg) {
149 Nonstandard(p_, lf, msg);
150 }
151 void Nonstandard(
152 CharBlock range, LanguageFeature lf, const MessageFixedText &msg) {
153 anyConformanceViolation_ = true;
154 if (userState_ && userState_->features().ShouldWarn(lf)) {
155 Say(range, msg);
156 }
157 }
158 bool IsNonstandardOk(LanguageFeature lf, const MessageFixedText &msg) {
159 if (userState_ && !userState_->features().IsEnabled(lf)) {
160 return false;
161 }
162 Nonstandard(lf, msg);
163 return true;
164 }
165
166 bool IsAtEnd() const { return p_ >= limit_; }
167
168 const char *UncheckedAdvance(std::size_t n = 1) {
169 const char *result{p_};
170 p_ += n;
171 return result;
172 }
173
174 std::optional<const char *> GetNextChar() {
175 if (p_ < limit_) {
176 return UncheckedAdvance();
177 } else {
178 return std::nullopt;
179 }
180 }
181
182 std::optional<const char *> PeekAtNextChar() const {
183 if (p_ < limit_) {
184 return p_;
185 } else {
186 return std::nullopt;
187 }
188 }
189
190 std::size_t BytesRemaining() const {
191 std::size_t remain = limit_ - p_;
192 return remain;
193 }
194
195 void CombineFailedParses(ParseState &&prev) {
196 if (prev.anyTokenMatched_) {
197 if (!anyTokenMatched_ || prev.p_ > p_) {
198 anyTokenMatched_ = true;
199 p_ = prev.p_;
200 messages_ = std::move(prev.messages_);
201 } else if (prev.p_ == p_) {
202 messages_.Merge(std::move(prev.messages_));
203 }
204 }
205 anyDeferredMessages_ |= prev.anyDeferredMessages_;
206 anyConformanceViolation_ |= prev.anyConformanceViolation_;
207 anyErrorRecovery_ |= prev.anyErrorRecovery_;
208 }
209
210private:
211 // Text remaining to be parsed
212 const char *p_{nullptr}, *limit_{nullptr};
213
214 // Accumulated messages and current nested context.
215 Messages messages_;
216 Message::Reference context_;
217
218 UserState *userState_{nullptr};
219
220 bool inFixedForm_{false};
221 bool anyErrorRecovery_{false};
222 bool anyConformanceViolation_{false};
223 bool deferMessages_{false};
224 bool anyDeferredMessages_{false};
225 bool anyTokenMatched_{false};
226 // NOTE: Any additions or modifications to these data members must also be
227 // reflected in the copy and move constructors defined at the top of this
228 // class definition!
229};
230} // namespace Fortran::parser
231#endif // FORTRAN_PARSER_PARSE_STATE_H_
232

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of flang/include/flang/Parser/parse-state.h