15 #ifndef Om_Language_Operator_
23 #ifndef Om_Macro_Precompilation_
25 #include "boost/test/unit_test.hpp"
33 BOOST_AUTO_TEST_SUITE(OperatorTest)
35 BOOST_AUTO_TEST_CASE(BasicTest) {
42 BOOST_AUTO_TEST_CASE(DereferenceTest) {
44 Operator theMutableOperator;
45 Atom & theMutableAtom = theMutableOperator;
46 Program & theMutableDereference = *theMutableAtom;
48 typeid(theMutableDereference) ==
typeid(Null)
53 Operator
const theImmutableOperator;
54 Atom
const & theImmutableAtom = theImmutableOperator;
55 Program
const & theImmutableDereference = *theImmutableAtom;
57 typeid(theImmutableDereference) ==
typeid(Null)
62 BOOST_AUTO_TEST_CASE(EqualityTest) {
66 System::Get().Evaluate(
"= operator{test {ing}} {test` `{ing`}}")
71 "{{a`{b`}`{c`}`\nd`{e`}}}",
72 System::Get().Evaluate(
"= operator{a{b}{c}\nd{e}} {a`{b`}`{c`}`\nd`{e`}}")
78 System::Get().Evaluate(
"= operator{a{b}{c}} {a`{b`}`{d`}}")
94 BOOST_AUTO_TEST_CASE(TakeQuotedElementsTest) {
100 Reader theReader(theCodePointSource);
101 theLiteral.ParseElements(theReader);
103 theOperator.TakeQuotedProducer(theLiteral);
110 theOperator.GetString()
114 BOOST_AUTO_TEST_CASE(NormalizationTest) {
116 Operator theFirst(
"s\xCC\x87");
117 Operator theSecond(
"\xCC\xA3");
118 theFirst.TakeElement(theSecond);
125 BOOST_AUTO_TEST_CASE(ReadTest) {
126 char const theCode[] =
"0\n\t {1\n\t {2\n\t } 3\n\t } {4\n\t} 5\n";
127 std::string theResult;
130 std::back_insert_iterator<std::string>
132 std::back_inserter(theResult)
134 Writer theWriter(theCodePointSink);
137 Reader theReader(theCodePointSource);
138 Operator theOperator;
139 theOperator.ParseElements(theReader);
140 theOperator.GiveElements(theWriter);
155 BOOST_AUTO_TEST_SUITE_END()
176 Om::Language::Operator
180 inline char const * Type_::GetName() {
186 inline Type_::Operator() {}
188 inline Type_::Operator(std::string
const & theString) {
189 boost::locale::normalize(
191 boost::locale::norm_nfd
192 ).swap(this->thisString);
195 inline Type_::Operator(
196 char const theCodeUnitIterator[]
198 boost::locale::normalize(
200 boost::locale::norm_nfd
201 ).swap(this->thisString);
204 inline Type_::Operator(
207 std::string theString;
209 std::back_insert_iterator<std::string> theInserter(theString);
211 theCodePointSource.
Pop()
213 switch (*theCodePointSource) {
219 theCodePointSource.
Pop();
220 if (!theCodePointSource) {
234 boost::locale::normalize(
236 boost::locale::norm_nfd
237 ).swap(this->thisString);
241 DefaultAtom<Operator>(
242 static_cast<char>(theOperandSymbol)
246 DefaultAtom<Operator>(
247 static_cast<char>(theOperatorSymbol)
251 DefaultAtom<Operator>(
252 static_cast<char>(theSeparatorSymbol)
255 inline Type_ & Type_::operator =(Operator theOperator) {
256 this->Swap(theOperator);
260 inline void Type_::BackGiveCodePoint(Consumer & theConsumer) {
262 !this->thisString.empty()
264 Operator theOperator;
266 std::string & theString = theOperator.thisString;
269 this->thisString.begin(),
270 this->thisString.end()
272 assert(theCodePointStringRange);
273 theCodePointStringRange->swap(theString);
278 this->thisString.erase(
279 this->thisString.size() - theString.size()
282 theConsumer.TakeElement(theOperator);
286 template <boost::locale::boundary::boundary_type theSegment>
287 inline void Type_::BackGiveSegment(Consumer & theConsumer) {
289 !this->thisString.empty()
291 Operator theOperator;
293 std::string & theString = theOperator.thisString;
295 typedef boost::locale::boundary::segment_index<std::string::const_iterator> SegmentCollection;
297 typedef SegmentCollection::const_iterator SegmentIterator;
299 SegmentCollection
const theSegmentCollection(
300 static_cast<boost::locale::boundary::boundary_type
>(theSegment),
301 this->thisString.begin(),
302 this->thisString.end()
305 SegmentIterator theSegmentIterator(
306 theSegmentCollection.end()
309 theSegmentCollection.begin() != theSegmentIterator
311 --theSegmentIterator;
312 theSegmentIterator->str().swap(theString);
317 this->thisString.erase(
318 this->thisString.size() - theString.size()
321 theConsumer.TakeElement(theOperator);
325 template <
typename TheConsumer>
326 inline void Type_::Decode(TheConsumer & theConsumer)
const {
328 this->thisString.begin(),
329 this->thisString.end()
331 Reader theReader(theCodePointSource);
332 theConsumer.ParseElements(theReader);
335 template <
typename TheProducer>
336 inline void Type_::Encode(TheProducer & theProducer) {
337 this->thisString.clear();
339 std::back_insert_iterator<std::string>
341 std::back_inserter(this->thisString)
343 Writer theWriter(theCodePointSink);
344 theProducer.GiveElements(theWriter);
347 inline void Type_::FrontGiveCodePoint(Consumer & theConsumer) {
349 !this->thisString.empty()
351 Operator theOperator;
353 std::string & theString = theOperator.thisString;
356 this->thisString.begin(),
357 this->thisString.end()
359 assert(theCodePointStringRange);
360 theCodePointStringRange->swap(theString);
365 this->thisString.erase(
370 theConsumer.TakeElement(theOperator);
374 template <boost::locale::boundary::boundary_type theSegment>
375 inline void Type_::FrontGiveSegment(Consumer & theConsumer) {
377 !this->thisString.empty()
379 Operator theOperator;
381 std::string & theString = theOperator.thisString;
383 typedef boost::locale::boundary::segment_index<std::string::const_iterator> SegmentCollection;
385 SegmentCollection
const theSegmentCollection(
386 static_cast<boost::locale::boundary::boundary_type
>(theSegment),
387 this->thisString.begin(),
388 this->thisString.end()
391 SegmentCollection::const_iterator
const theSegmentIterator(
392 theSegmentCollection.begin()
395 theSegmentCollection.end() != theSegmentIterator
397 theSegmentIterator->str().swap(theString);
402 this->thisString.erase(
407 theConsumer.TakeElement(theOperator);
411 inline void Type_::Normalize() {
412 boost::locale::normalize(
414 boost::locale::norm_nfkd
415 ).swap(this->thisString);
418 inline void Type_::ParseElements(Reader & theReader) {
420 switch (*theReader) {
426 this->thisString.push_back(
427 static_cast<char>(*theReader)
432 Operator theOperator(theReader);
433 this->TakeOperator(theOperator);
437 inline void Type_::ParseQuotedElements(Reader & theReader) {
439 this->ParseElements(theReader);
443 template <
typename TheOperand>
444 inline void Type_::TakeOperand(TheOperand & theOperand) {
446 !theOperand.IsEmpty()
448 this->TakeQuotedProducer(
449 *theOperand.GetProgram()
453 template <
typename TheOperator>
454 inline void Type_::TakeOperator(TheOperator & theOperator) {
456 typeid(theOperator) ==
typeid(*
this)
459 !theOperator.IsEmpty()
462 boost::locale::normalize(
463 theOperator.thisString,
464 boost::locale::norm_nfd
465 ) == theOperator.thisString &&
466 "Operator strings must be NFC normalized."
472 this->Take(theOperator);
476 this->thisString.append(theOperator.thisString);
480 boost::locale::normalize(
482 boost::locale::norm_nfd
483 ).swap(this->thisString);
486 template <
typename TheProducer>
487 inline void Type_::TakeQuotedProducer(TheProducer & theProducer) {
489 theProducer.GiveElements(*
this);
493 template <
typename TheSeparator>
494 inline void Type_::TakeSeparator(TheSeparator & theSeparator) {
496 !theSeparator.IsEmpty()
498 this->thisString.append(
499 theSeparator.GetString()
512 theFirst.
Swap(theSecond);
void Swap(ThisImplementation &)
The Operator implementation.
A CodePoint Sink that pushes each code unit to the iterator.
A CodePoint Source that reads each code unit from the iterator.
A Source of CodePoint strings from the back of a string.
A Source of CodePoint strings from the front of a string.
Any object that items can be pulled from.
virtual void Pop()=0
Pops the current item.
SeparatorSymbol
A Separator symbol.
OperatorSymbol
An Operator symbol.
@ theEncodeOperatorSymbol
OperandSymbol
An Operand symbol.
void swap(Om::Language::Expression &, Om::Language::Expression &)
#define Om_Language_Symbol_OperandSymbol_GetCases_()
Generates switch cases for each Om::Language::Symbol::OperandSymbol.
#define Om_Language_Operator_GetName_()
#define Om_Language_Symbol_SeparatorSymbol_GetCases_()
Generates switch cases for each Om::Language::Symbol::SeparatorSymbol.