MimIR
0.5-dev
MimIR is my Intermediate Representation
Toggle main menu visibility
Loading...
Searching...
No Matches
automaton.h
Go to the documentation of this file.
1
#pragma once
2
3
#include <concepts>
4
5
#include <algorithm>
6
#include <list>
7
#include <map>
8
#include <ostream>
9
#include <print>
10
#include <set>
11
#include <vector>
12
13
#include "
automaton/range_helper.h
"
14
15
namespace
automaton
{
16
17
class
DFANode
;
18
class
NFANode
;
19
20
template
<
class
NodeType>
21
class
AutomatonBase
{
22
public
:
23
AutomatonBase
() =
default
;
24
AutomatonBase
(
const
AutomatonBase
&) =
delete
;
25
AutomatonBase
&
operator=
(
const
AutomatonBase
&) =
delete
;
26
27
NodeType*
add_state
() {
28
nodes_.emplace_back(id_++);
29
return
&nodes_.back();
30
}
31
32
void
set_start
(
const
NodeType* start) { start_ = start; }
33
34
const
NodeType*
get_start
()
const
{
return
start_; }
35
size_t
num_states
()
const
{
return
nodes_.size(); }
36
37
/// Ordered by NodeType::Lt (i.e. by id) so that iteration is deterministic.
38
std::set<const NodeType*, typename NodeType::Lt>
get_reachable_states
()
const
{
39
std::set<const NodeType*, typename NodeType::Lt> reachableStates;
40
std::vector<const NodeType*> workList;
41
workList.push_back(
get_start
());
42
while
(!workList.empty()) {
43
auto
state = workList.back();
44
workList.pop_back();
45
reachableStates.insert(state);
46
state->for_transitions([&](
auto
,
auto
to) {
47
if
(!reachableStates.contains(to)) workList.push_back(to);
48
});
49
}
50
return
reachableStates;
51
}
52
53
void
print
(std::ostream& os)
const
{
54
if
constexpr
(std::is_same_v<NodeType, DFANode>)
55
std::println(os,
"digraph dfa {{"
);
56
else
if
constexpr
(std::is_same_v<NodeType, NFANode>)
57
std::println(os,
"digraph nfa {{"
);
58
else
59
std::println(os,
"digraph automaton {{"
);
60
std::println(os,
" start -> \"{}\";"
, start_->id());
61
62
for
(
const
auto
& node : nodes_)
63
node.print(os);
64
std::println(os,
"}}"
);
65
}
66
67
friend
std::ostream&
operator<<
(std::ostream& os,
const
AutomatonBase
&
automaton
) {
68
automaton
.print(os);
69
return
os;
70
}
71
72
private
:
73
std::list<NodeType> nodes_;
74
const
NodeType* start_ =
nullptr
;
75
int
id_ = 0;
76
};
77
78
template
<
class
NodeType>
79
void
print_node
(std::ostream& os,
const
NodeType& node, std::invocable<std::uint64_t>
auto
print_char) {
80
if
(node.is_accepting()) std::println(os,
" \"{}\" [shape=doublecircle];"
, node.id());
81
if
(node.is_erroring()) std::println(os,
" \"{}\" [shape=square];"
, node.id());
82
83
std::map<const NodeType*, std::vector<Range>,
typename
NodeType::Lt> node2transitions;
84
node.for_transitions([&](
auto
c,
auto
to) { node2transitions[to].push_back({c, c}); });
85
86
for
(
auto
& [to, ranges] : node2transitions) {
87
std::sort(ranges.begin(), ranges.end(),
RangeCompare
{});
88
ranges =
merge_ranges
(ranges);
89
for
(
auto
& [lo, hi] : ranges) {
90
auto
chars = lo == hi ? print_char(lo) : std::format(
"{}-{}"
, print_char(lo), print_char(hi));
91
auto
nums = lo == hi ? std::format(
"{}"
, lo) : std::format(
"{}-{}"
, lo, hi);
92
std::println(os,
" \"{}\" -> \"{}\" [label=\"{} ({})\"];"
, node.id(), to->id(), chars, nums);
93
}
94
}
95
}
96
97
}
// namespace automaton
automaton::AutomatonBase::num_states
size_t num_states() const
Definition
automaton.h:35
automaton::AutomatonBase::set_start
void set_start(const NodeType *start)
Definition
automaton.h:32
automaton::AutomatonBase::add_state
NodeType * add_state()
Definition
automaton.h:27
automaton::AutomatonBase::get_reachable_states
std::set< const NodeType *, typename NodeType::Lt > get_reachable_states() const
Ordered by NodeType::Lt (i.e. by id) so that iteration is deterministic.
Definition
automaton.h:38
automaton::AutomatonBase::AutomatonBase
AutomatonBase()=default
automaton::AutomatonBase::get_start
const NodeType * get_start() const
Definition
automaton.h:34
automaton::AutomatonBase::print
void print(std::ostream &os) const
Definition
automaton.h:53
automaton::AutomatonBase::operator<<
friend std::ostream & operator<<(std::ostream &os, const AutomatonBase &automaton)
Definition
automaton.h:67
automaton::AutomatonBase::AutomatonBase
AutomatonBase(const AutomatonBase &)=delete
automaton::AutomatonBase::operator=
AutomatonBase & operator=(const AutomatonBase &)=delete
automaton::DFANode
Definition
dfa.h:14
automaton::NFANode
Definition
nfa.h:14
automaton
Definition
automaton.h:15
automaton::print_node
void print_node(std::ostream &os, const NodeType &node, std::invocable< std::uint64_t > auto print_char)
Definition
automaton.h:79
automaton::merge_ranges
std::optional< Range > merge_ranges(Range a, Range b) noexcept
Definition
range_helper.h:19
range_helper.h
automaton::RangeCompare
Definition
range_helper.h:15
include
automaton
automaton.h
Generated by
1.18.0