Om
expression.cpp
Go to the documentation of this file.
1 
15 #ifndef Om_Language_Expression_
16 
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(ExpressionTest)
34 
35  BOOST_AUTO_TEST_CASE(GeneralTest) {
36  BOOST_CHECK_EQUAL(
37  (
38  "{{a}{b}\n"
39  "c{d}}"
40  ),
41  System::Get().Evaluate("evaluate {{a}{b}c{d}}")
42  );
43 
44  BOOST_CHECK_EQUAL(
45  "{c{d}{a}{b}}",
46  System::Get().Evaluate("evaluate {c{d}{a}{b}}")
47  );
48 
49  BOOST_CHECK_EQUAL(
50  (
51  "{a{b}{c}\n"
52  "d{e}{f}}"
53  ),
54  System::Get().Evaluate("evaluate {a{b}{c}d{e}{f}}")
55  );
56 
57  BOOST_CHECK_EQUAL(
58  "{c}",
59  System::Get().Evaluate("evaluate {c}")
60  );
61 
62  BOOST_CHECK_EQUAL(
63  "{{d}}",
64  System::Get().Evaluate("evaluate {{d}}")
65  );
66 
67  BOOST_CHECK_EQUAL(
68  "{}",
69  System::Get().Evaluate("evaluate {}")
70  );
71  }
72 
73  BOOST_AUTO_TEST_CASE(EqualityTest) {
74  // Positive match
75  BOOST_CHECK_EQUAL(
76  (
77  "{{a{b}{c}\n"
78  "d{e}}}"
79  ),
80  System::Get().Evaluate(
81  "= expression{a{b}{c}d{e}} {"
82  "a{b}{c}\n"
83  "d{e}"
84  "}"
85  )
86  );
87 
88  // Positive match
89  BOOST_CHECK_EQUAL(
90  "{{a{b}{c}}}",
91  System::Get().Evaluate("= expression{a{b}{c}} {a{b}{c}}")
92  );
93 
94  // Positive match
95  BOOST_CHECK_EQUAL(
96  "{{a{b}}}",
97  System::Get().Evaluate("= expression{a{b}} {a{b}}")
98  );
99 
100  // Positive match
101  BOOST_CHECK_EQUAL(
102  "{{a}}",
103  System::Get().Evaluate("= expression{a} {a}")
104  );
105 
106  // Positive match
107  BOOST_CHECK_EQUAL(
108  "{{{a}}}",
109  System::Get().Evaluate("= expression{{a}}{{a}}")
110  );
111 
112  // Negative match
113  BOOST_CHECK_EQUAL(
114  "{}",
115  System::Get().Evaluate("= expression{a{b}{c}} {A{B}{C}}")
116  );
117 
118  // Negative match
119  BOOST_CHECK_EQUAL(
120  "{}",
121  System::Get().Evaluate("= expression{} {a{b}{c}}")
122  );
123 
124  // Positive empty match
125  BOOST_CHECK_EQUAL(
126  "{{}}",
127  System::Get().Evaluate("= expression{} {}")
128  );
129  }
130 
131  BOOST_AUTO_TEST_CASE(ReadTest) {
132  char const theCode[] = (
133  "0\n"
134  "\t {1\n"
135  "\t {2\n"
136  "\t } 3\n"
137  "\t } {4\n"
138  "\t} 5\n"
139  );
140  std::string theResult;
141  {
143  std::back_insert_iterator<std::string>
144  > theCodePointSink(
145  std::back_inserter(theResult)
146  );
147  Writer theWriter(theCodePointSink);
148 
149  Om::Source::CodePointSource<> theCodePointSource(theCode);
150  Reader theReader(theCodePointSource);
151  Expression theExpression;
152  theExpression.ParseElements(theReader);
153  theExpression.GiveElements(theWriter);
154  }
155  BOOST_CHECK_EQUAL(
156  std::string(
157  "0{1\n"
158  "\t {2\n"
159  "\t } 3\n"
160  "\t }{4\n"
161  "\t}\n"
162  "5"
163  ),
164  std::string(theResult)
165  );
166  }
167 
168  BOOST_AUTO_TEST_SUITE_END()
169 
170  }
171 
172 }
173 
174  #endif
175 
176 #else
177 
178  #include "om/language/literal.hpp"
179 
180  #ifndef Om_Macro_Precompilation_
181 
182  #include "boost/ref.hpp"
183  #include "boost/utility/in_place_factory.hpp"
184 
185  #endif
186 
187 // MARK: - Om::Language::Expression
188 
189  #define Type_ \
190  Om::Language::Expression
191 
192 // MARK: public (static)
193 
194 inline char const * Type_::GetName() {
196 }
197 
198 // MARK: public (non-static)
199 
200 inline Type_::Expression():
201 thisFormDeque() {}
202 
203 inline Type_ & Type_::operator =(Expression theExpression) {
204  this->Swap(theExpression);
205  return *this;
206 }
207 
208 inline void Type_::BackGiveForm(Consumer & theConsumer) {
209  if (
210  !this->thisFormDeque.empty()
211  ) {
212  this->thisFormDeque.back().GiveElements(theConsumer);
213  this->thisFormDeque.pop_back();
214  }
215 }
216 
217 inline void Type_::BackGiveTerm(Consumer & theConsumer) {
218  if (
219  !this->thisFormDeque.empty()
220  ) {
221  Form & theForm = this->thisFormDeque.back();
222  if (
223  theForm.BackGiveTerm(theConsumer)
224  ) {
225  assert(
226  theForm.IsEmpty()
227  );
228  this->thisFormDeque.pop_back();
229  }
230  }
231 }
232 
233 inline void Type_::BackPopTerm() {
234  assert(
235  !this->thisFormDeque.empty()
236  );
237  Form & theForm = this->thisFormDeque.back();
238  if (
239  theForm.BackPopTerm()
240  ) {
241  assert(
242  theForm.IsEmpty()
243  );
244  this->thisFormDeque.pop_back();
245  }
246 }
247 
248 template <typename TheOperand>
249 inline void Type_::BackTakeOperand(TheOperand & theOperand) {
250  this->GetBackTaker().BackTakeOperand(theOperand);
251 }
252 
253 template <typename TheOperator>
254 inline void Type_::BackTakeOperator(TheOperator & theOperator) {
255  assert(
256  !theOperator.IsEmpty()
257  );
258  this->thisFormDeque.push_back(
259  Form()
260  );
261  this->thisFormDeque.back().TakeOperator(theOperator);
262 }
263 
264 template <typename TheProducer>
265 inline void Type_::BackTakeQuotedProducer(TheProducer & theProducer) {
266  this->GetBackTaker().BackTakeQuotedProducer(theProducer);
267 }
268 
269 inline void Type_::Clear() {
270  this->thisFormDeque.clear();
271 }
272 
273 inline void Type_::FrontGiveForm(Consumer & theConsumer) {
274  if (
275  !this->thisFormDeque.empty()
276  ) {
277  this->thisFormDeque.front().GiveElements(theConsumer);
278  this->thisFormDeque.pop_front();
279  }
280 }
281 
282 inline void Type_::FrontGiveTerm(Consumer & theConsumer) {
283  if (
284  !this->thisFormDeque.empty()
285  ) {
286  Form & theForm = this->thisFormDeque.front();
287  if (
288  theForm.FrontGiveTerm(theConsumer)
289  ) {
290  assert(
291  theForm.IsEmpty()
292  );
293  this->thisFormDeque.pop_front();
294  }
295  }
296 }
297 
298 inline void Type_::FrontPopTerm() {
299  assert(
300  !this->thisFormDeque.empty()
301  );
302  Form & theForm = this->thisFormDeque.front();
303  if (
304  theForm.FrontPopTerm()
305  ) {
306  assert(
307  theForm.IsEmpty()
308  );
309  this->thisFormDeque.pop_front();
310  }
311 }
312 
313 template <typename TheOperand>
314 inline void Type_::FrontTakeOperand(TheOperand & theOperand) {
315  this->GetFrontTaker().FrontTakeOperand(theOperand);
316 }
317 
318 template <typename TheOperator>
319 inline void Type_::FrontTakeOperator(TheOperator & theOperator) {
320  assert(
321  !theOperator.IsEmpty()
322  );
323  this->GetFrontTaker().TakeOperator(theOperator);
324 }
325 
326 template <typename TheProducer>
327 inline void Type_::FrontTakeQuotedProducer(TheProducer & theProducer) {
328  this->GetFrontTaker().FrontTakeQuotedProducer(theProducer);
329 }
330 
331 inline std::auto_ptr<
333 > Type_::GetElementRange() const {
334  return std::auto_ptr<
336  >(
337  new ElementRange(*this)
338  );
339 }
340 
341 inline void Type_::GiveElements(Consumer & theConsumer) {
342  this->GiveElements(
343  theConsumer,
344  this->thisFormDeque.begin(),
345  this->thisFormDeque.end()
346  );
347  this->Clear();
348 }
349 
350 inline void Type_::GiveElements(Consumer & theConsumer) const {
351  this->GiveElements(
352  theConsumer,
353  this->thisFormDeque.begin(),
354  this->thisFormDeque.end()
355  );
356 }
357 
358 inline bool Type_::IsEmpty() const {
359  return this->thisFormDeque.empty();
360 }
361 
362 inline void Type_::ParseElements(Reader & theReader) {
363  this->Parse<
364  Operator,
365  Null
366  >(theReader);
367 }
368 
369 inline void Type_::ParseQuotedElements(Reader & theReader) {
370  Literal theLiteral;
371  theLiteral.ParseElements(theReader);
372  this->TakeQuotedProducer(theLiteral);
373 }
374 
375 inline void Type_::Swap(Expression & theExpression) {
376  this->thisFormDeque.swap(theExpression.thisFormDeque);
377 }
378 
379 inline void Type_::TakeElements(Expression & theExpression) {
380  if (
381  !theExpression.IsEmpty()
382  ) {
383  if (
384  this->IsEmpty()
385  ) {
386  this->Take(theExpression);
387  } else {
388  FormDeque & theFormDeque = theExpression.thisFormDeque;
389  assert(
390  !theFormDeque.empty()
391  );
392 
393  FormDeque::iterator theCurrent = theFormDeque.begin();
394  if (
395  theCurrent->GetOperator().IsEmpty()
396  ) {
397  theFormDeque.front().GiveElements(*this);
398  theFormDeque.pop_front();
399  if (
400  theFormDeque.empty()
401  ) {
402  return;
403  }
404  theCurrent = theFormDeque.begin();
405  }
406 
407  FormDeque::iterator const theEnd = theFormDeque.end();
408  assert(theEnd != theCurrent);
409  do {
410  assert(
411  !theCurrent->GetOperator().IsEmpty()
412  );
413  this->thisFormDeque.push_back(
414  Form()
415  );
416  this->thisFormDeque.back().Swap(*theCurrent);
417  } while (theEnd != ++theCurrent);
418 
419  Expression().Swap(theExpression);
420  }
421  }
422 }
423 
424 inline void Type_::TakeElements(Expression const & theExpression) {
425  if (
426  !theExpression.IsEmpty()
427  ) {
428  if (
429  this->IsEmpty()
430  ) {
431  this->Take(theExpression);
432  } else {
433  FormDeque const & theFormDeque = theExpression.thisFormDeque;
434  assert(
435  !theFormDeque.empty()
436  );
437 
438  FormDeque::const_iterator const theEnd = theFormDeque.end();
439  FormDeque::const_iterator theCurrent = theFormDeque.begin();
440  assert(theEnd != theCurrent);
441  if (
442  theCurrent->GetOperator().IsEmpty()
443  ) {
444  theFormDeque.front().GiveElements(*this);
445  ++theCurrent;
446  }
447  this->thisFormDeque.insert(
448  this->thisFormDeque.end(),
449  theCurrent,
450  theEnd
451  );
452  }
453  }
454 }
455 
456 inline void Type_::TakeElements(Producer & theProducer) {
457  if (
458  typeid(theProducer) == typeid(Expression)
459  ) {
460  this->TakeElements(
461  static_cast<Expression &>(theProducer)
462  );
463  } else {
464  theProducer.GiveElements(*this);
465  }
466 }
467 
468 inline void Type_::TakeElements(Producer const & theProducer) {
469  if (
470  typeid(theProducer) == typeid(Expression const)
471  ) {
472  this->TakeElements(
473  static_cast<Expression const &>(theProducer)
474  );
475  } else {
476  theProducer.GiveElements(*this);
477  }
478 }
479 
480 template <typename TheOperand>
481 inline void Type_::TakeOperand(TheOperand & theOperand) {
482  assert(
483  !theOperand.IsEmpty()
484  );
485  this->BackTakeOperand(theOperand);
486 }
487 
488 template <typename TheOperator>
489 inline void Type_::TakeOperator(TheOperator & theOperator) {
490  assert(
491  !theOperator.IsEmpty()
492  );
493  this->BackTakeOperator(theOperator);
494 }
495 
496 template <typename TheProducer>
497 inline void Type_::TakeQuotedProducer(TheProducer & theProducer) {
498  this->BackTakeQuotedProducer(theProducer);
499 }
500 
501 template <typename TheSeparator>
502 inline void Type_::TakeSeparator(TheSeparator &) {}
503 
504 // MARK: private (static)
505 
506 template <typename TheFormIterator>
507 inline void Type_::GiveElements(
508  Consumer & theConsumer,
509  TheFormIterator theCurrent,
510  TheFormIterator const theEnd
511 ) {
512  if (theEnd != theCurrent) {
513  for (
514  ;
515  ;
516  theConsumer.TakeElement(
517  Separator::GetLineSeparator()
518  )
519  ) {
520  assert(
521  !theCurrent->IsEmpty()
522  );
523  theCurrent->GiveElements(theConsumer);
524  if (theEnd == ++theCurrent) {
525  return;
526  }
527  }
528  }
529 }
530 
531 // MARK: private (non-static)
532 
533 inline Om::Language::Form & Type_::GetBackTaker() {
534  if (
535  this->thisFormDeque.empty()
536  ) {
537  this->thisFormDeque.push_back(
538  Form()
539  );
540  }
541  return this->thisFormDeque.back();
542 }
543 
544 inline Om::Language::Form & Type_::GetFrontTaker() {
545  if (
546  this->thisFormDeque.empty() ||
547  !this->thisFormDeque.front().GetOperator().IsEmpty()
548  ) {
549  this->thisFormDeque.push_front(
550  Form()
551  );
552  }
553  return this->thisFormDeque.front();
554 }
555 
556  #undef Type_
557 
558 // MARK: - Om::Language::Expression::FormRange
559 
560  #define Type_ \
561  Om::Language::Expression::FormRange
562 
563 // MARK: public (non-static)
564 
565 inline Type_<Om::Language::Form>::FormRange(Expression & theExpression):
566 Om::Source::CollectionFrontSource<
567  Form,
568  FormDeque::iterator
569 >(theExpression.thisFormDeque) {}
570 
571 inline Type_<Om::Language::Form const>::FormRange(Expression const & theExpression):
572 Om::Source::CollectionFrontSource<
573  Form const,
574  FormDeque::const_iterator
575 >(theExpression.thisFormDeque) {}
576 
577  #undef Type_
578 
579 // MARK: - Om::Language::Expression::ElementRange
580 
581  #define Type_ \
582  Om::Language::Expression::ElementRange
583 
584 // MARK: public (non-static)
585 
586 inline Type_::ElementRange(Expression const & theExpression):
587 thisFormIterator(
588  theExpression.thisFormDeque.begin()
589 ),
590 thisFormEnd(
591  theExpression.thisFormDeque.end()
592 ),
593 thisFormElementRange() {
594  if (this->thisFormEnd != this->thisFormIterator) {
595  this->thisFormElementRange = boost::in_place(
596  boost::ref(*this->thisFormIterator)
597  );
598  assert(*this->thisFormElementRange);
599  }
600 }
601 
602 inline bool Type_::operator !() const {
603  return !this->thisFormElementRange;
604 }
605 
606 inline Om::Language::Element const & Type_::operator *() const {
607  assert(this->thisFormElementRange);
608  return (
609  *this->thisFormElementRange ?
610  **this->thisFormElementRange :
611  Separator::GetLineSeparator()
612  );
613 }
614 
615 inline bool Type_::Equals(ElementRange const & theElementRange) const {
616  return (
617  this->thisFormElementRange == theElementRange.thisFormElementRange &&
618  this->thisFormIterator == theElementRange.thisFormIterator
619  );
620 }
621 
622 inline void Type_::End() {
623  this->thisFormElementRange = boost::none;
624 }
625 
626 inline void Type_::Pop() {
627  assert(this->thisFormElementRange);
628  assert(this->thisFormEnd != this->thisFormIterator);
629  if (*this->thisFormElementRange) {
630  this->thisFormElementRange->Pop();
631  if (!*this->thisFormElementRange) {
632  if (this->thisFormEnd == ++this->thisFormIterator) {
633  this->End();
634  }
635  }
636  } else {
637  this->thisFormElementRange = boost::in_place(
638  boost::ref(*this->thisFormIterator)
639  );
640  assert(*this->thisFormElementRange);
641  }
642 }
643 
644 // MARK: - Om::Language::
645 
646 inline bool Om::Language::operator ==(
647  Type_ const & theFirst,
648  Type_ const & theSecond
649 ) {
650  return theFirst.Equals(theSecond);
651 }
652 
653 inline bool Om::Language::operator !=(
654  Type_ const & theFirst,
655  Type_ const & theSecond
656 ) {
657  return !theFirst.Equals(theSecond);
658 }
659 
660  #undef Type_
661 
662 // MARK: - boost::
663 
664 template <>
665 inline void boost::swap(
666  Om::Language::Expression & theFirst,
667  Om::Language::Expression & theSecond
668 ) {
669  theFirst.Swap(theSecond);
670 }
671 
672 #endif
A Program that contains a single elemental item (or none, when IsEmpty() returns true).
Definition: element.hpp:33
The Expression Program implementation.
Definition: expression.hpp:56
void Swap(Expression &)
An Operator (which may be empty), followed by zero or more Operand instances.
Definition: form.hpp:33
static System & Get()
A CodePoint Sink that pushes each code unit to the iterator.
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_Expression_GetName_()
Definition: expression.hpp:42
Om header file.
bool operator!=(DefaultAtom< TheImplementation > const &, DefaultAtom< TheImplementation > const &)
bool operator==(DefaultAtom< TheImplementation > const &, DefaultAtom< TheImplementation > const &)
The Om library.
Definition: code_point.hpp:26
void swap(Om::Language::Expression &, Om::Language::Expression &)
Om header file.