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