Om
literal.cpp
Go to the documentation of this file.
1 
15 #ifndef Om_Language_Literal_
16 
17  #include "om/language/literal.hpp"
18 
19  #ifdef Om_Macro_Test_
20 
21  #include "om/language/system.hpp"
22 
23  #ifndef Om_Macro_Precompilation_
24 
25  #include "boost/test/unit_test.hpp"
26 
27  #endif
28 
29 namespace Om {
30 
31  namespace Language {
32 
33  BOOST_AUTO_TEST_SUITE(LiteralTest)
34 
35  BOOST_AUTO_TEST_CASE(EqualityTest) {
36  // Positive match
37  BOOST_CHECK_EQUAL(
38  "{{a{b}{c}\nd{e}}}",
39  System::Get().Evaluate("= {a{b}{c}\nd{e}} {a{b}{c}\nd{e}}")
40  );
41 
42  // Negative match
43  BOOST_CHECK_EQUAL(
44  "{}",
45  System::Get().Evaluate("= {a{b}{c}} {a{b}{d}}")
46  );
47 
48  // Empty match
49  BOOST_CHECK_EQUAL(
50  "{}",
51  System::Get().Evaluate("= {} {a{b}{c}}")
52  );
53 
54  // Empty match
55  BOOST_CHECK_EQUAL(
56  "{{}}",
57  System::Get().Evaluate("= {} {}")
58  );
59  }
60 
61  BOOST_AUTO_TEST_CASE(RecursionTest) {
62  size_t const theDepth = 50000;
63 
64  std::string theString;
65  for (
66  size_t theLevel = theDepth;
67  theLevel;
68  --theLevel
69  ) {
70  theString = "{" + theString + "}";
71  }
72 
74  theString.begin(),
75  theString.end()
76  );
77  Reader theReader(theCodePointSource);
78  Literal theLiteral;
79  theLiteral.ParseElements(theReader);
80 
81  Literal theCopy;
82  theCopy = theLiteral;
83 
84  theCopy.Clear();
85  BOOST_CHECK(
86  theCopy.IsEmpty()
87  );
88  }
89 
90  BOOST_AUTO_TEST_SUITE_END()
91 
92  }
93 
94 }
95 
96  #endif
97 
98 #else
99 
100  #include "om/language/operator.hpp"
101  #include "om/language/separator.hpp"
102 
103  #ifndef Om_Macro_Precompilation_
104 
105  #include <stack>
106 
107  #endif
108 
109 // MARK: - Om::Language::Literal
110 
111  #define Type_ \
112  Om::Language::Literal
113 
114 // MARK: public (static)
115 
116 inline char const * Type_::GetName() {
118 }
119 
120 // MARK: public (non-static)
121 
122 inline Type_::~Literal() {
123  // Flatten the ElementDeque to avoid recursive destructor calls.
124  try {
125  while (
126  !this->thisElementDeque.empty()
127  ) {
128  std::auto_ptr<Element> theElement(
129  this->thisElementDeque.pop_front().release()
130  );
131  assert(
132  theElement.get()
133  );
134  (*theElement)->GiveElements(*this);
135  }
136  } catch (...) {}
137 }
138 
139 inline Type_::Literal():
140 thisElementDeque() {}
141 
142 inline Type_ & Type_::operator =(Literal theLiteral) {
143  this->Swap(theLiteral);
144  return *this;
145 }
146 
147 template <typename TheElement>
148 inline void Type_::BackGive(Consumer & theConsumer) {
149  if (
150  !this->thisElementDeque.empty() &&
151  dynamic_cast<TheElement const *>(
152  &this->thisElementDeque.back()
153  )
154  ) {
155  this->thisElementDeque.pop_back()->GiveElements(theConsumer);
156  }
157 }
158 
159 inline void Type_::BackGiveElement(Consumer & theConsumer) {
160  if (
161  !this->thisElementDeque.empty()
162  ) {
163  this->thisElementDeque.pop_back()->GiveElements(theConsumer);
164  }
165 }
166 
167 inline void Type_::Clear() {
168  this->thisElementDeque.clear();
169 }
170 
171 template <typename TheElement>
172 inline void Type_::FrontGive(Consumer & theConsumer) {
173  if (
174  !this->thisElementDeque.empty() &&
175  dynamic_cast<TheElement const *>(
176  &this->thisElementDeque.front()
177  )
178  ) {
179  this->thisElementDeque.pop_front()->GiveElements(theConsumer);
180  }
181 }
182 
183 inline void Type_::FrontGiveElement(Consumer & theConsumer) {
184  if (
185  !this->thisElementDeque.empty()
186  ) {
187  this->thisElementDeque.pop_front()->GiveElements(theConsumer);
188  }
189 }
190 
191 inline std::auto_ptr<
193 > Type_::GetElementRange() {
194  return std::auto_ptr<
196  >(
197  new ElementRange<Literal>(*this)
198  );
199 }
200 
201 inline std::auto_ptr<
203 > Type_::GetElementRange() const {
204  return std::auto_ptr<
206  >(
207  new ElementRange<Literal const>(*this)
208  );
209 }
210 
211 inline void Type_::GiveElements(Consumer & theConsumer) {
212  this->GiveElements(
213  theConsumer,
214  this->thisElementDeque.begin(),
215  this->thisElementDeque.end()
216  );
217  this->thisElementDeque.clear();
218 }
219 
220 inline void Type_::GiveElements(Consumer & theConsumer) const {
221  this->GiveElements(
222  theConsumer,
223  this->thisElementDeque.begin(),
224  this->thisElementDeque.end()
225  );
226 }
227 
228 inline bool Type_::IsEmpty() const {
229  return this->thisElementDeque.empty();
230 }
231 
232 inline void Type_::ParseElements(Reader & theReader) {
233  std::stack<Literal *> theStack;
234  theStack.push(this);
235 
236  while (theReader) {
237  switch (*theReader) {
239  assert(
240  !theStack.empty() &&
241  this != theStack.top()
242  );
243  theStack.pop();
244  break;
246  {
247  std::auto_ptr<Literal> theLiteral(new Literal);
248  Literal * theLiteralPointer = theLiteral.get();
249  {
250  Operand theOperand(theLiteral);
251  theStack.top()->TakeOperand(theOperand);
252  }
253  theStack.push(theLiteralPointer);
254  }
255  break;
257  assert(
258  !theStack.empty() &&
259  theStack.top()
260  );
261  {
262  Separator theSeparator(theReader);
263  theStack.top()->TakeSeparator(theSeparator);
264  }
265  continue;
266  default:
267  assert(
268  !theStack.empty() &&
269  theStack.top()
270  );
271  {
272  Operator theOperator(theReader);
273  theStack.top()->TakeOperator(theOperator);
274  }
275  continue;
276  }
277  theReader.Pop();
278  }
279 }
280 
281 inline void Type_::ParseQuotedElements(Reader & theReader) {
282  Literal theLiteral;
283  theLiteral.ParseElements(theReader);
284  this->TakeQuotedProducer(theLiteral);
285 }
286 
287 inline void Type_::Swap(Literal & theLiteral) {
288  this->thisElementDeque.swap(theLiteral.thisElementDeque);
289 }
290 
291 template <typename TheOperand>
292 inline void Type_::TakeOperand(TheOperand & theOperand) {
293  assert(
294  !theOperand.IsEmpty()
295  );
296  this->thisElementDeque.push_back(
297  Give(theOperand)
298  );
299 }
300 
301 template <typename TheOperator>
302 inline void Type_::TakeOperator(TheOperator & theOperator) {
303  assert(
304  !theOperator.IsEmpty()
305  );
306  this->TakeAtom(theOperator);
307 }
308 
309 template <typename TheProducer>
310 inline void Type_::TakeQuotedProducer(TheProducer & theProducer) {
311  this->thisElementDeque.push_back(
312  new Operand(
313  theProducer.GiveProgram()
314  )
315  );
316 }
317 
318 template <typename TheSeparator>
319 inline void Type_::TakeSeparator(TheSeparator & theSeparator) {
320  assert(
321  !theSeparator.IsEmpty()
322  );
323  this->TakeAtom(theSeparator);
324 }
325 
326 // MARK: private (static)
327 
328 template <typename TheElementIterator>
329 inline void Type_::GiveElements(
330  Consumer & theConsumer,
331  TheElementIterator theCurrent,
332  TheElementIterator const theEnd
333 ) {
334  for (
335  ;
336  theEnd != theCurrent;
337  ++theCurrent
338  ) {
339  theCurrent->GiveElements(theConsumer);
340  }
341 }
342 
343 // MARK: private (non-static)
344 
345 template <typename TheAtom>
346 inline void Type_::TakeAtom(TheAtom & theAtom) {
347  assert(
348  !theAtom.IsEmpty()
349  );
350  if (
351  this->thisElementDeque.empty() ||
352  !this->thisElementDeque.back().Merge(theAtom)
353  ) {
354  this->thisElementDeque.push_back(
355  Give(theAtom)
356  );
357  }
358 }
359 
360  #undef Type_
361 
362 // MARK: - Om::Language::Literal::ElementRange
363 
364  #define Type_ \
365  Om::Language::Literal::ElementRange
366 
367 // MARK: public (non-static)
368 
369 inline Type_<Om::Language::Literal>::ElementRange(Literal & theLiteral):
370 Om::Source::CollectionFrontSource<
371  Element,
372  ElementDeque::iterator
373 >(theLiteral.thisElementDeque) {}
374 
375 inline Type_<Om::Language::Literal const>::ElementRange(Literal const & theLiteral):
376 Om::Source::CollectionFrontSource<
377  Element const,
378  ElementDeque::const_iterator
379 >(theLiteral.thisElementDeque) {}
380 
381  #undef Type_
382 
383 // MARK: - boost::
384 
385 template <>
386 inline void boost::swap(
387  Om::Language::Literal & theFirst,
388  Om::Language::Literal & theSecond
389 ) {
390  theFirst.Swap(theSecond);
391 }
392 
393 #endif
The Literal Program implementation.
Definition: literal.hpp:55
void Swap(Literal &)
static System & Get()
A CodePoint Source that reads each code unit from the iterator.
Any object that items can be pulled from.
Definition: source.hpp:31
Om header file.
#define Om_Language_Literal_GetName_()
Definition: literal.hpp:41
The Om library.
Definition: code_point.hpp:26
std::auto_ptr< TheGiveable > Give(TheGiveable &)
Calls Move on the object.
void swap(Om::Language::Expression &, Om::Language::Expression &)
Om header file.
Om header file.
#define Om_Language_Symbol_SeparatorSymbol_GetCases_()
Generates switch cases for each Om::Language::Symbol::SeparatorSymbol.
Om header file.