33
44#include < cstdint>
55#include < memory>
6+ #include < optional>
67#include < queue>
78#include < string>
89#include < unordered_map>
1112#include < vector>
1213
1314#include < fmt/core.h>
15+ #include < fmt/format.h>
1416
1517#include < log_surgeon/Constants.hpp>
16- #include < log_surgeon/finite_automata/NfaState.hpp>
18+ #include < log_surgeon/finite_automata/Capture.hpp>
19+ #include < log_surgeon/finite_automata/TagOperation.hpp>
20+ #include < log_surgeon/finite_automata/UnicodeIntervalTree.hpp>
1721#include < log_surgeon/LexicalRule.hpp>
1822#include < log_surgeon/types.hpp>
1923#include < log_surgeon/UniqueIdGenerator.hpp>
@@ -35,32 +39,31 @@ class Nfa {
3539 explicit Nfa (std::vector<LexicalRule<TypedNfaState>> const & rules);
3640
3741 /* *
38- * Creates a unique_ptr for an NFA state with no tagged transitions and adds it to `m_states`.
39- * @return TypedNfaState*
42+ * @return A pointer to the newly created NFA state with no spontaneous transitions.
4043 */
4144 [[nodiscard]] auto new_state () -> TypedNfaState*;
4245
4346 /* *
44- * Creates a unique_ptr for an NFA state with a negative tagged transition and adds it to
45- * `m_states`.
46- * @param captures
47- * @param dest_state
48- * @return TypedNfaState*
47+ * @param captures A vector containing the captures of all alternate paths.
48+ * @param dest_state The destination state to arrive at after negating the captures.
49+ * @return A pointer to the newly created NFA state with a spontaneous transition to
50+ * `dest_state`negating all the tags associated with `captures`.
4951 */
50- [[nodiscard]] auto new_state_with_negative_tagged_transition (
52+ [[nodiscard]] auto new_state_from_negative_captures (
5153 std::vector<Capture const *> const & captures,
5254 TypedNfaState const * dest_state
5355 ) -> TypedNfaState*;
5456
5557 /* *
56- * Creates the start and end states for a capture group.
57- * @param capture The capture associated with the capture group.
58- * @param dest_state
59- * @return A pair of states:
60- * - A new state with a positive tagged start transition from `m_root`.
61- * - A new state with a positive tagged end transition to `dest_state`.
58+ * @param capture The positive capture to be tracked.
59+ * @param dest_state The destination state to arrive at after tracking the capture.
60+ * @return A pair of pointers to the two newly created NFA states:
61+ * - A state arrived at from a spontaneous transition out of `m_root` that sets a tag to track
62+ * the capture's start position.
63+ * - A state with a spontaneous transition to `dest_state` that sets a tag to track the
64+ * capture's end position
6265 */
63- [[nodiscard]] auto new_start_and_end_states_with_positive_tagged_transitions (
66+ [[nodiscard]] auto new_start_and_end_states_from_positive_capture (
6467 Capture const * capture,
6568 TypedNfaState const * dest_state
6669 ) -> std::pair<TypedNfaState*, TypedNfaState*>;
@@ -72,9 +75,10 @@ class Nfa {
7275 [[nodiscard]] auto get_bfs_traversal_order () const -> std::vector<TypedNfaState const *>;
7376
7477 /* *
75- * @return A string representation of the NFA.
78+ * @return A string representation of the NFA on success.
79+ * @return Forwards `NfaState::serialize`'s return value (`std::nullopt`) on failure.
7680 */
77- [[nodiscard]] auto serialize () const -> std::string;
81+ [[nodiscard]] auto serialize () const -> std::optional<std:: string> ;
7882
7983 auto add_root_interval (Interval interval, TypedNfaState* dest_state) -> void {
8084 m_root->add_interval (interval, dest_state);
@@ -100,18 +104,6 @@ class Nfa {
100104 [[nodiscard]] auto get_or_create_capture_tag_pair (Capture const * capture
101105 ) -> std::pair<tag_id_t, tag_id_t>;
102106
103- /* *
104- * Creates a `unique_ptr` for an NFA state with a positive tagged end transition and adds it to
105- * `m_states`.
106- * @param tag_id
107- * @param dest_state
108- * @return A new state with a positive tagged end transition to `dest_state`.
109- */
110- [[nodiscard]] auto new_state_with_positive_tagged_end_transition (
111- tag_id_t tag_id,
112- TypedNfaState const * dest_state
113- ) -> TypedNfaState*;
114-
115107 std::vector<std::unique_ptr<TypedNfaState>> m_states;
116108 // TODO: Lexer currently enforces unique naming across capture groups. However, this limits use
117109 // cases. Possibly initialize this in the lexer and pass it in during construction.
@@ -146,39 +138,35 @@ auto Nfa<TypedNfaState>::new_state() -> TypedNfaState* {
146138}
147139
148140template <typename TypedNfaState>
149- auto Nfa<TypedNfaState>::new_state_with_positive_tagged_end_transition(
150- tag_id_t const tag_id,
151- TypedNfaState const * dest_state
152- ) -> TypedNfaState* {
153- m_states.emplace_back (std::make_unique<TypedNfaState>(tag_id, dest_state));
154- return m_states.back ().get ();
155- }
156-
157- template <typename TypedNfaState>
158- auto Nfa<TypedNfaState>::new_state_with_negative_tagged_transition(
141+ auto Nfa<TypedNfaState>::new_state_from_negative_captures(
159142 std::vector<Capture const *> const & captures,
160143 TypedNfaState const * dest_state
161144) -> TypedNfaState* {
162145 std::vector<tag_id_t > tags;
163- for (auto const capture : captures) {
146+ for (auto const * capture : captures) {
164147 auto const [start_tag, end_tag]{get_or_create_capture_tag_pair (capture)};
165148 tags.push_back (start_tag);
166149 tags.push_back (end_tag);
167150 }
168151
169- m_states.emplace_back (std::make_unique<TypedNfaState>(std::move (tags), dest_state));
152+ m_states.emplace_back (
153+ std::make_unique<TypedNfaState>(TagOperationType::Negate, std::move (tags), dest_state)
154+ );
170155 return m_states.back ().get ();
171156}
172157
173158template <typename TypedNfaState>
174- auto Nfa<TypedNfaState>::new_start_and_end_states_with_positive_tagged_transitions (
159+ auto Nfa<TypedNfaState>::new_start_and_end_states_from_positive_capture (
175160 Capture const * capture,
176161 TypedNfaState const * dest_state
177162) -> std::pair<TypedNfaState*, TypedNfaState*> {
178163 auto const [start_tag, end_tag]{get_or_create_capture_tag_pair (capture)};
179- auto * start_state = new_state ();
180- m_root->add_positive_tagged_start_transition (start_tag, start_state);
181- auto * end_state{new_state_with_positive_tagged_end_transition (end_tag, dest_state)};
164+ auto * start_state{new_state ()};
165+ m_root->add_spontaneous_transition (TagOperationType::Set, {start_tag}, start_state);
166+ m_states.emplace_back (
167+ std::make_unique<TypedNfaState>(TagOperationType::Set, std::vector{end_tag}, dest_state)
168+ );
169+ auto * end_state{m_states.back ().get ()};
182170 return {start_state, end_state};
183171}
184172
@@ -208,33 +196,15 @@ auto Nfa<TypedNfaState>::get_bfs_traversal_order() const -> std::vector<TypedNfa
208196 add_to_queue_and_visited (dest_state);
209197 }
210198 }
211- for (auto const * dest_state : current_state->get_epsilon_transitions ()) {
212- add_to_queue_and_visited (dest_state);
213- }
214- for (auto const & positive_tagged_start_transition :
215- current_state->get_positive_tagged_start_transitions ())
216- {
217- add_to_queue_and_visited (positive_tagged_start_transition.get_dest_state ());
218- }
219-
220- auto const & optional_positive_tagged_end_transition
221- = current_state->get_positive_tagged_end_transition ();
222- if (optional_positive_tagged_end_transition.has_value ()) {
223- add_to_queue_and_visited (optional_positive_tagged_end_transition.value ().get_dest_state (
224- ));
225- }
226-
227- auto const & optional_negative_tagged_transition
228- = current_state->get_negative_tagged_transition ();
229- if (optional_negative_tagged_transition.has_value ()) {
230- add_to_queue_and_visited (optional_negative_tagged_transition.value ().get_dest_state ());
199+ for (auto const & spontaneous_transition : current_state->get_spontaneous_transitions ()) {
200+ add_to_queue_and_visited (spontaneous_transition.get_dest_state ());
231201 }
232202 }
233203 return visited_order;
234204}
235205
236206template <typename TypedNfaState>
237- auto Nfa<TypedNfaState>::serialize() const -> std::string {
207+ auto Nfa<TypedNfaState>::serialize() const -> std::optional<std:: string> {
238208 auto const traversal_order = get_bfs_traversal_order ();
239209
240210 std::unordered_map<TypedNfaState const *, uint32_t > state_ids;
@@ -244,10 +214,11 @@ auto Nfa<TypedNfaState>::serialize() const -> std::string {
244214
245215 std::vector<std::string> serialized_states;
246216 for (auto const * state : traversal_order) {
247- // `state_ids` is well-formed as its generated from `get_bfs_traversal_order` so we can
248- // safely assume `state->serialize(state_ids)` will return a valid value.
249- // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
250- serialized_states.emplace_back (state->serialize (state_ids).value ());
217+ auto const optional_serialized_state{state->serialize (state_ids)};
218+ if (false == optional_serialized_state.has_value ()) {
219+ return std::nullopt ;
220+ }
221+ serialized_states.emplace_back (optional_serialized_state.value ());
251222 }
252223 return fmt::format (" {}\n " , fmt::join (serialized_states, " \n " ));
253224}
0 commit comments