summaryrefslogtreecommitdiffhomepage
path: root/bnf.cpp
blob: 04a6be9a2f60040685ce44afa1a30e0e79f407fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "bnf.h"

std::unordered_map<std::string, std::unordered_set<std::string>> Reverse(const BNF& bnf)
{
 std::unordered_map<std::string, std::unordered_set<std::string>> result;

 for (const auto& [from, to] : bnf) {
  for (const auto& list : to) {
   for (const auto& element : list) {
    auto i{result.find(element)};
    if (i != result.end()) // already present
     i->second.insert(from);
    else // new element
     result.emplace(element, std::unordered_set{from});
   }
  }
 }

 return result;
}

std::unordered_map<std::string, std::unordered_set<std::string>> reverseFirst(const BNF& bnf)
{
 std::unordered_map<std::string, std::unordered_set<std::string>> result;

 for (const auto& [from, to] : bnf) {
  for (const auto& list : to) {
   if (list.size() > 0) {
    const auto& element{list[0]};
    auto i{result.find(element)};
    if (i != result.end()) // already present
     i->second.insert(from);
    else // new element
     result.emplace(element, std::unordered_set{from});
   }
  }
 }

 return result;
}

BNF SubBNF(const BNF& bnf, const std::string& top)
{
 BNF result;

 std::vector<std::string> todo{top};

 while (!todo.empty()) {
  std::string current{todo.back()};
  todo.pop_back();

  auto it = bnf.find(current);
  if (it != bnf.end()) {
   // add current value
   result[it->first] = it->second;

   // add sub-tree values if not present yet, but available in original bnf
   for (auto& variant: it->second) {
    for (auto& child: variant) {
     if (result.find(child) == result.end() && bnf.find(child) != bnf.end()) {
      todo.push_back(child);
     }
    }
   }
  }
 }

 return result;
}

bool isTerminal(const BNF& bnf, const std::string& symbol)
{
 return bnf.find(symbol) == bnf.end();
}

std::unordered_set<std::string> getTerminals(const BNF& bnf)
{
 std::unordered_set<std::string> result;

 for (const auto& [from, to] : bnf) {
  for (const auto& list : to) {
   for (const auto& element : list) {
    if (isTerminal(bnf, element))
     result.insert(element);
   }
  }
 }

 return result;
}

std::unordered_set<std::pair<std::string, size_t>, PairHash> getEmptyPositions(const BNF& bnf)
{
 std::unordered_set<std::pair<std::string, size_t>, PairHash> result;

 for (const auto& [from, to] : bnf) {
  for (size_t i = 0; i < to.size(); i++) {
   const auto& list{to[i]};
   if (list.size() == 0)
    result.insert({from, i});
  }
 }

 return result;
}

std::unordered_map<std::string, std::unordered_set<std::pair<std::string, index_t>, PairHash>> reversePosFirst(const BNF& bnf)
{
 std::unordered_map<std::string, std::unordered_set<std::pair<std::string, index_t>, PairHash>> result;

 for (const auto& [from, to] : bnf) {
  for (size_t i = 0; i < to.size(); i++) {
   const auto& list{to[i]};
   if (list.size() > 0) {
    const auto& element{list[0]};
    auto it{result.find(element)};
    if (it != result.end()) // already present
     it->second.insert({from, i});
    else // new element
     result.emplace(element, std::unordered_set<std::pair<std::string, index_t>, PairHash>{{from, i}});
   }
  }
 }

 return result;
}