ICG 2
Electric Boogaloo
MutableVariableName.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <deque>
4 #include <string>
5 #include <sstream>
6 #include <iostream>
7 #include <vector>
8 
10  public:
12  MutableVariableName(std::string name) {
13  try {
14  parse_str(name);
15  } catch (std::exception& e) {
16  // re-throw with better message
17  std::string message = "Parsing " + name + " failed with error: " + e.what();
18  throw std::logic_error(message);
19  }
20  }
21 
22  void pushName(std::string name) {
23  nameElements.push_back(name);
24  }
25  void pushIndex(int i) {
26  nameElements.push_back(std::string("[" + std::to_string(i) + "]"));
27  }
28 
29  std::string pop_back() {
30  std::string ret = nameElements.back();
31  nameElements.pop_back();
32  return ret;
33  }
34 
35  std::string pop_front() {
36  std::string ret = nameElements.front();
37  nameElements.pop_front();
38  return ret;
39  }
40 
41  std::string front() {
42  return nameElements.front();
43  }
44 
45  int size() {
46  return nameElements.size();
47  }
48 
49  bool empty () {
50  return nameElements.empty();
51  }
52 
53  std::vector<std::string> getElements() const {
54  return std::vector<std::string>(nameElements.begin(), nameElements.end());
55  }
56 
57  std::string toString() const {
58  if (nameElements.empty()) {
59  return "";
60  }
61 
62  std::stringstream ss;
63 
64  ss << nameElements[0];
65  for (unsigned int i = 1; i < nameElements.size(); i++) {
66  if (nameElements[i].at(0) != '[') {
67  ss << ".";
68  }
69 
70  ss << nameElements[i];
71  }
72 
73  return ss.str();
74  }
75 
76  private:
77  std::deque<std::string> nameElements;
78 
79  // Tail recursion to parse
80  void parse_str(std::string name) {
81 
82  // Nothing left - we're done!
83  if (name.size() == 0) {
84  return;
85  }
86 
87  size_t dot_pos = name.find(".", 0);
88  size_t index_pos = name.find("[", 0);
89 
90  std::string rest_of_name;
91 
92  if (dot_pos == std::string::npos && index_pos == std::string::npos) {
93  // There are no more . or [ chars, so everything left is a single name.
94  pushName(name);
95 
96  // We could return here really, but we want to preserve the tail recursive structure
97  rest_of_name = "";
98 
99  } else if (index_pos == 0) {
100  // Index operator is next thing
101  size_t end_index_pos = name.find("]", 0);
102  if (end_index_pos == std::string::npos) {
103  // uh oh
104  throw std::logic_error("Missing end bracket");
105  }
106 
107  size_t number_length = end_index_pos - (index_pos+1);
108  std::string number = name.substr(index_pos+1, number_length);
109  long int index;
110 
111  try {
112  index = stoi(number);
113  } catch (std::exception& e) {
114  // Re-throw with a more relavent error message
115  std::string message = "Index brackets contain \"" + number + "\", which cannot be parsed as an unsigned integer.";
116  throw std::logic_error(message);
117  }
118 
119  if (index < 0) {
120  std::string message = "Index brackets contain a negative number (" + number + ").";
121  throw std::logic_error(message);
122  }
123 
124  pushIndex(index);
125 
126  rest_of_name = name.substr(end_index_pos+1);
127  } else if (dot_pos == 0) {
128  // If the pos is 0 just slice if off and don't push anything
129  // for example var[0].a
130  rest_of_name = name.substr(1);
131  } else {
132  // Get the name until dot or bracket
133 
134  // Woo use a lambda as an assignment
135  // We already know that both cannot be npos and neither can be 0
136  size_t name_end_index = [=]() -> size_t {
137  if (index_pos == std::string::npos) return dot_pos;
138  if (dot_pos == std::string::npos) return index_pos;
139  return std::min(dot_pos, index_pos);
140  }();
141 
142  std::string subname = name.substr(0, name_end_index);
143  pushName(subname);
144 
145  rest_of_name = name.substr(name_end_index);
146  }
147 
148  // Tail recursion!
149  parse_str(rest_of_name);
150  }
151 };
Definition: MutableVariableName.hpp:9
void pushIndex(int i)
Definition: MutableVariableName.hpp:25
std::string pop_front()
Definition: MutableVariableName.hpp:35
bool empty()
Definition: MutableVariableName.hpp:49
std::string pop_back()
Definition: MutableVariableName.hpp:29
MutableVariableName()
Definition: MutableVariableName.hpp:11
void pushName(std::string name)
Definition: MutableVariableName.hpp:22
std::string front()
Definition: MutableVariableName.hpp:41
int size()
Definition: MutableVariableName.hpp:45
std::string toString() const
Definition: MutableVariableName.hpp:57
MutableVariableName(std::string name)
Definition: MutableVariableName.hpp:12
std::vector< std::string > getElements() const
Definition: MutableVariableName.hpp:53
e
Definition: AllocInfo.hpp:23