Calculator
Extensible stack-based calculator primarily in library form
Stack.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2013, Komodo Does Inc
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6 
7 - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 - Neither the name of the Komodo Does Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10 
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 */
13 
14 #include <memory>
15 #include <vector>
16 #include <set>
17 #include <string>
18 #include <sstream>
19 
20 #include "Stack.h"
21 #include "Variable.h"
22 #include "VariableSet.h"
23 #include "Error.h"
24 
25 namespace Calculator {
26 
27  /*
28  * StackIterator
29  */
30 
32  public:
33  typedef std::shared_ptr<StackIteratorPimpl> Ptr;
34  typedef std::vector<StackItem::Ptr>::iterator Iterator;
35 
39  unsigned int position = 0;
41 
42  StackIteratorPimpl(Stack& theStack, const Iterator& theIter)
43  : stack(theStack), iter(theIter)
44  {
45  }
46 
47  void addError(unsigned int position, const std::string& error);
49  };
50 
51  void StackIteratorPimpl::addError(unsigned int position, const std::string& error) {
53  }
54 
56  Variable::Ptr asVariable = std::dynamic_pointer_cast<Variable, StackItem>(in);
57  if(!asVariable) {
58  return in;
59  }
60 
61  std::set<std::string> varNames;
62 
63  StackItem::Ptr item = in;
64  while(item) {
65  Variable::Ptr itemAsVar = std::dynamic_pointer_cast<Variable, StackItem>(item);
66  if(!itemAsVar) {
67  return item;
68  }
69 
70  // Add the current name to the list we've been through, unless already
71  // present. If already present, we have a circle and cannot dereference
72  auto result = varNames.insert(itemAsVar->getName());
73  if(!result.second) {
75  return StackItem::Ptr();
76  }
77 
78  // Dereference curr. An unset reference will be caught by the while loop
79  item = stack.getVariables().get(itemAsVar->getName());
80  }
81 
83  return StackItem::Ptr();
84  }
85 
86  StackIterator::StackIterator(std::shared_ptr<StackIteratorPimpl> thePimpl)
87  : pimpl(thePimpl)
88  {
89  }
90 
92  : pimpl(PimplPtr(new StackIteratorPimpl(rhs.pimpl->stack, rhs.pimpl->iter)))
93  {
94  pimpl->hint = rhs.pimpl->hint;
95  }
96 
98  pimpl.reset(new StackIteratorPimpl(rhs.pimpl->stack, rhs.pimpl->iter));
99  pimpl->hint = rhs.pimpl->hint;
100  return *this;
101  }
102 
104  if(pimpl->stack.end() != *this) {
105  --pimpl->iter;
106  }
107  ++pimpl->position;
108  return *this;
109  }
110 
112  StackIterator copy = *this;
113  ++*this;
114  return copy;
115  }
116 
117  bool StackIterator::operator==(const StackIterator& rhs) const {
118  return rhs.pimpl->iter == pimpl->iter;
119  }
120 
121  bool StackIterator::operator!=(const StackIterator& rhs) const {
122  return rhs.pimpl->iter != pimpl->iter;
123  }
124 
125  StackIterator::operator bool() const {
126  return 0 == pimpl->result.getPositionMessages().size();
127  }
128 
130  if(pimpl->stack.end() == *this) {
132  return StackItem::Ptr();
133  } else if(Hint::DEREFERENCE_NEXT == pimpl->hint) {
134  return pimpl->dereference(*pimpl->iter);
135  } else {
136  pimpl->hint = Hint::DEREFERENCE_NEXT;
137  return *pimpl->iter;
138  }
139  }
140 
142  return *pimpl->iter;
143  }
144 
146  pimpl->hint = theHint;
147  return *this;
148  }
149 
151  return pimpl->result;
152  }
153 
154  void StackIterator::addError(unsigned int position, const std::string& message) {
155  pimpl->addError(position, message);
156  }
157 
158  void StackIterator::addError(const std::string& message) {
159  addError(pimpl->position, message);
160  }
161 
162  StackIterator::PimplPtr StackIterator::getPimpl() {
163  return pimpl;
164  }
165 
167  iter.setHint(hint);
168  return iter;
169  }
170 
172  t = *iter;
173  ++iter;
174  return iter;
175  }
176 
177  /*
178  * Stack
179  */
180 
181  class StackPimpl {
182  public:
183  typedef std::vector<StackItem::Ptr> StackType;
184  typedef StackType::iterator Iter;
185  typedef StackType::const_iterator CIter;
186 
187  /** Implementation of the Stack */
189 
190  /** Variables used in the Stack
191  *
192  * This could be isolated into a derived class to provide both types; however,
193  * this would require a cast for the Variable suppor classes to get/set the
194  * variables... We will just add it to the only Stack class for now.
195  */
197  };
198 
200  : pimpl(PimplPtr(new StackPimpl()))
201  {
202  }
203 
205  return pimpl->stack.size();
206  }
207 
209  return pimpl->variables;
210  }
211 
212  void Stack::reset() {
213  popAll();
214  pimpl->variables.clear();
215  }
216 
217  void Stack::popAll() {
218  pimpl->stack.clear();
219  }
220 
222  StackPimpl::Iter iter = pimpl->stack.end();
223  --iter;
224  return StackIterator(StackIteratorPimpl::Ptr(new StackIteratorPimpl(*this, iter)));
225  }
226 
228  StackPimpl::Iter myRbegin = pimpl->stack.begin();
229  --myRbegin;
230  return StackIterator(StackIteratorPimpl::Ptr(new StackIteratorPimpl(*this, myRbegin)));
231  }
232 
234  // Get the iterator and move one step closer to top to erase from it to the
235  // end since we are popping after the given
236  StackPimpl::Iter from = iter.getPimpl()->iter;
237  ++from;
238  pimpl->stack.erase(from, pimpl->stack.end());
239  }
240 
242  pimpl->stack.push_back(item);
243  }
244 
245  std::string Stack::toString() const {
246  std::ostringstream os;
247 
248  os << "[";
249  for(StackPimpl::CIter iter = pimpl->stack.begin(); pimpl->stack.end() != iter; ++iter) {
250  os << " " << (*iter)->toString();
251  }
252  os << " ]";
253 
254  return os.str();
255  }
256 
257 } // namespace Calculator
Collection of Result information for an operation.
Definition: Result.h:30
void addPositionMessage(const unsigned int position, const std::string &message)
Add the positional message.
Definition: Result.cpp:61
Stack of values to process from.
Definition: Stack.h:208
StackIterator begin()
Definition: Stack.cpp:221
VariableSet & getVariables()
Definition: Stack.cpp:208
void push(StackItemPtr item)
Push item onto the stack.
Definition: Stack.cpp:241
std::string toString() const
Create string representation of the current contents of the Stack.
Definition: Stack.cpp:245
StackIterator end()
Definition: Stack.cpp:227
void popAfter(StackIterator &iter)
Pop all items after iter on the Stack.
Definition: Stack.cpp:233
void popAll()
Pop all items from the stack.
Definition: Stack.cpp:217
void reset()
Reset the stack including pop all variables and reset the variables.
Definition: Stack.cpp:212
Count getDepth() const
Definition: Stack.cpp:204
unsigned int Count
Count of StackItems.
Definition: Stack.h:215
std::shared_ptr< StackItem > Ptr
Definition: StackItem.h:30
Iterator over a Stack from top to bottom.
Definition: Stack.h:35
Hint
Hint for accessing the value at an iterator.
Definition: Stack.h:44
@ DEREFERENCE_NEXT
Dereference the next read.
bool operator!=(const StackIterator &rhs) const
Return true if this iterator is not the same position as rhs.
Definition: Stack.cpp:121
StackIterator & operator=(const StackIterator &)
Definition: Stack.cpp:97
const Result & getResult() const
Definition: Stack.cpp:150
StackIterator & operator++()
Pre-increment: Move to the next position away from the top.
Definition: Stack.cpp:103
StackItemPtr noDereference()
Definition: Stack.cpp:141
StackItemPtr operator*()
Definition: Stack.cpp:129
bool operator==(const StackIterator &rhs) const
Return true if this iterator is the same position as rhs.
Definition: Stack.cpp:117
StackIterator & setHint(Hint theHint)
Set the current hint for reading the value to theHint.
Definition: Stack.cpp:145
void addError(unsigned int position, const std::string &message)
Add error message at position.
Definition: Stack.cpp:154
std::shared_ptr< StackIteratorPimpl > Ptr
Definition: Stack.cpp:33
void addError(unsigned int position, const std::string &error)
Definition: Stack.cpp:51
StackIteratorPimpl(Stack &theStack, const Iterator &theIter)
Definition: Stack.cpp:42
StackIterator::Hint hint
Definition: Stack.cpp:36
std::vector< StackItem::Ptr >::iterator Iterator
Definition: Stack.cpp:34
StackItem::Ptr dereference(StackItem::Ptr in)
Definition: Stack.cpp:55
StackType::iterator Iter
Definition: Stack.cpp:184
StackType::const_iterator CIter
Definition: Stack.cpp:185
VariableSet variables
Variables used in the Stack.
Definition: Stack.cpp:196
std::vector< StackItem::Ptr > StackType
Definition: Stack.cpp:183
StackType stack
Implementation of the Stack.
Definition: Stack.cpp:188
std::shared_ptr< Variable > Ptr
Definition: Variable.h:31
All variables belonging to a Stack.
Definition: VariableSet.h:28
std::shared_ptr< StackItem > get(const std::string &name) const
Get the value of name, if any.
Definition: VariableSet.cpp:40
const std::string VariableReferencesSelf
Variable dereferences to itself directly or indirectly and cannot be read.
Definition: Error.h:32
const std::string StackUnderflow
Operation required more items than the Stack had available.
Definition: Error.h:26
const std::string VariableNotSet
Operation required a variable.
Definition: Error.h:29
Container of Calculator resources.
StackIterator & operator>>(StackIterator &iter, StackIterator::Hint hint)
Set the iter's hint and return the iter.
Definition: Stack.cpp:166