fipa_acl  1.4
grammar_common.h
Go to the documentation of this file.
1 #ifndef FIPA_ACL_GRAMMAR_COMMON_H
2 #define FIPA_ACL_GRAMMAR_COMMON_H
3 
4 //#define BOOST_SPIRIT_DEBUG
5 
6 #include <boost/config/warning_disable.hpp>
7 #include <boost/spirit/include/qi.hpp>
8 
9 #ifndef BOOST_SPIRIT_USE_PHOENIX_V3
10 #include <boost/spirit/home/support/context.hpp>
11 #include <boost/spirit/include/phoenix_core.hpp>
12 #include <boost/spirit/include/phoenix_operator.hpp>
13 #include <boost/spirit/include/phoenix_object.hpp>
14 #include <boost/spirit/include/phoenix_fusion.hpp>
15 #include <boost/spirit/include/phoenix_stl.hpp>
16 #include <boost/fusion/include/adapt_struct.hpp>
17 #else
18 #include <boost/phoenix/phoenix.hpp>
19 #include <boost/phoenix/fusion/at.hpp>
20 #include <boost/fusion/adapted/std_pair.hpp>
21 #endif
22 
23 #include <boost/foreach.hpp>
24 #include <boost/lexical_cast.hpp>
25 #include <arpa/inet.h>
26 #include <ctime>
27 
28 #include <base-logging/Logging.hpp>
29 
30 #include <fipa_acl/message_generator/acl_message.h>
31 
32 #include <fipa_acl/message_parser/types.h>
33 #ifdef BOOST_SPIRIT_DEBUG
34 // include stream operators
35 #include <fipa_acl/message_parser/debug.h>
36 
37 #define FIPA_DEBUG_RULE(X) BOOST_SPIRIT_DEBUG_NODE(X); qi::on_error<qi::fail> ( X, std::cout << phoenix::val("Error: expecting ") << label::_4 /* what failed? */ << phoenix::val(" here: \"") << phoenix::construct<std::string>(label::_3,label::_2) << phoenix::val("\"") << std::endl);
38 #else
39 #define FIPA_DEBUG_RULE(X)
40 #endif
41 
42 // BOOST_FUSION_ADAPT_CLASS has been renamed to BOOST_FUSION_ADAPT_ADT for boost version > 104500
43 #if BOOST_VERSION < 104500
44 #include <boost/fusion/include/adapt_class.hpp>
45 #else
46 #include <boost/fusion/adapted/adt/adapt_adt.hpp>
47 #include <boost/fusion/include/adapt_adt.hpp>
48 #endif
49 
50 #if BOOST_VERSION < 104500
51 #define FIPA_ACL_FUSION_ADAPT BOOST_FUSION_ADAPT_CLASS
52 #else
53 #define FIPA_ACL_FUSION_ADAPT BOOST_FUSION_ADAPT_ADT
54 #endif
55 
58  (const std::string&, const std::string&, obj.getName(), obj.setName(val))
59  (const std::vector<std::string>&, const std::vector<std::string>&, obj.getAddresses(), obj.setAddresses(val))
60  (const std::vector<fipa::acl::AgentID>&, const std::vector<fipa::acl::AgentID>&, obj.getResolvers(), obj.setResolvers(val))
61  (const std::vector<fipa::acl::UserdefParam>&, const std::vector<fipa::acl::UserdefParam>&, obj.getUserdefParams(), obj.setUserdefParams(val))
62  );
63 
66  (const std::string&, const std::string&, obj.getName(), obj.setName(val))
67  (const std::string&, const std::string&, obj.getValue(), obj.setValue(val))
68  );
69 
72  /* 0 */ (std::string, std::string, obj.getPerformative(), obj.setPerformative(val))
73  /* 1 */ (fipa::acl::AgentID, fipa::acl::AgentID, obj.getSender(), obj.setSender(val))
74  /* 2 */ (fipa::acl::AgentIDList, fipa::acl::AgentIDList, obj.getAllReceivers(), obj.setAllReceivers(val))
75  /* 3 */ (std::string, std::string, obj.getContent(), obj.setContent(val))
76  /* 4 */ (std::string, std::string, obj.getReplyWith(), obj.setReplyWith(val))
77  /* 5 */ (base::Time, base::Time, obj.getReplyBy(), obj.setReplyBy(val))
78  /* 6 */ (std::string, std::string, obj.getInReplyTo(), obj.setInReplyTo(val))
79  /* 7 */ (fipa::acl::AgentIDList, fipa::acl::AgentIDList, obj.getAllReplyTo(), obj.setAllReplyTo(val))
80  /* 8 */ (std::string, std::string, obj.getLanguage(), obj.setLanguage(val))
81  /* 9 */ (std::string, std::string, obj.getEncoding(), obj.setEncoding(val))
82  /*10 */ (std::string, std::string, obj.getOntology(), obj.setOntology(val))
83  /*11 */ (std::string, std::string, obj.getProtocol(), obj.setProtocol(val))
84  /*12 */ (std::string, std::string, obj.getConversationID(), obj.setConversationID(val))
85  /*13 */ (void, void, /*no getter used*/, obj.addUserdefParam(val))
86 );
87 
88 namespace fusion = boost::fusion;
89 namespace phoenix = boost::phoenix;
90 namespace spirit = boost::spirit;
91 namespace qi = boost::spirit::qi;
92 
93 // Using ascii encoding
94 namespace encoding = boost::spirit::ascii;
95 //namespace encoding = boost::spirit::standard;
96 
99  (std::string, encoding)
100  (fipa::acl::LengthValue, length)
101  (fipa::acl::ByteString, bytes)
102 )
103 
104 // We only need additional access to the millisecond element
107  (int, tm_msec)
108 )
109 
112  (char, relative)
113  (fipa::acl::Time, dateTime)
114  (char, timezone)
115 )
116 
117 namespace fipa {
118 
119 //#####################################################
120 // Utility functions
121 //#####################################################
122  // In order to use functions as semantic actions
123  // lazy evaluation is required
124  struct extractFromCodetableImpl
125  {
126  typedef std::string result_type;
127 
128  template <typename T>
129  struct result
130  {
131  typedef result_type type;
132  };
133 
134  template <typename T>
135  result_type operator()(T arg) const
136  {
137  if(typeid(T) == typeid(unsigned short))
138  {
139  //unsigned short index;
141  //index = arg;
142 
143  // TODO: search codetable and extract data
144  }
145 
146  throw std::runtime_error("Codetable currently unsupported");
147  }
148 
149  };
150 
151  extern phoenix::function<extractFromCodetableImpl> extractFromCodetable;
152 
154  struct buildStringImpl
155  {
156  typedef std::string result_type;
157 
158  template <typename T, typename U, typename V>
159  struct result
160  {
161  typedef result_type type;
162  };
163 
164  template <typename T, typename U, typename V>
165  result_type operator()(T arg0, U arg1, V arg2) const
166  {
167  arg0 += arg1;
168  arg0 += arg2;
169  return arg0;
170  }
171 
172 
173  };
174  extern phoenix::function<buildStringImpl> buildString;
175 
177  struct concatStringsWithSeparatorImpl
178  {
179  typedef std::string result_type;
180 
181  template <typename T, typename U, typename V>
182  struct result
183  {
184  typedef result_type type;
185  };
186 
187  template <typename T, typename U, typename V>
188  result_type operator()(T arg0, U arg1, V arg2) const
189  {
190  if(arg0.empty())
191  {
192  return arg1;
193  } else {
194  arg0 += arg2;
195  arg0 += arg1;
196  return arg0;
197  }
198  }
199  };
200  extern phoenix::function<concatStringsWithSeparatorImpl> concatStringsWithSeparator;
201 
203  struct printImpl
204  {
205  typedef void result_type;
206 
207  template <typename T, typename U>
208  struct result
209  {
210  typedef result_type type;
211  };
212 
213  template <typename T, typename U>
214  result_type operator()(T arg0, U arg1) const
215  {
216  printf("%s %s\n", arg0, arg1.c_str());
217  }
218 
219  };
220 
221  extern phoenix::function<printImpl> print;
222 
223  struct digitPaddingBytesImpl
224  {
225  typedef uint32_t result_type;
226 
227  template <typename T>
228  struct result
229  {
230  typedef result_type type;
231  };
232 
233  template <typename T>
234  result_type operator()(T digit /* std::string */) const
235  {
236  char lastbyte = digit[0];
237  // odd number of characters
238  // check if last byte is properly padded
239  if( (lastbyte & 0x0F) == 0)
240  {
241  // properly padded
242  LOG_DEBUG("CodedNumber properly padded byte detected: %x", lastbyte);
243  return 0;
244  } else {
245  LOG_DEBUG("CodedNumber with unpadded byte detected: %x", lastbyte);
246  return 1;
247  }
248  }
249  };
250 
251  extern phoenix::function<digitPaddingBytesImpl> digitPaddingBytes;
252 
254  struct convertToNumberTokenImpl
255  {
256  typedef std::string result_type;
257 
258  template <typename T>
259  struct result
260  {
261  typedef result_type type;
262  };
263 
264  template <typename T>
265  result_type operator()(T arg) const
266  {
267 
268  // Each bytes contains two numbers:
269  // one in the highbytes and one in the lowerbytes
270  char highbytes = arg;
271  char lowerbytes = arg;
272 
273  // Shift to lowerbytes so that we can use the convert
274  // function here as well
275  highbytes >>= 4;
276 
277  std::string tmp = convert(highbytes);
278  tmp += convert(lowerbytes);
279 
280  return std::string(tmp);
281  }
282 
283  std::string convert(char lowerbyte) const
284  {
285  // make sure high order bytes are set to 0
286  lowerbyte &= 0x0F;
287 
288  // There will be more efficient ways to do that, but for clarity
289  switch(lowerbyte)
290  {
291  case 0x00: return "";
292  case 0x01: return "0";
293  case 0x02: return "1";
294  case 0x03: return "2";
295  case 0x04: return "3";
296  case 0x05: return "4";
297  case 0x06: return "5";
298  case 0x07: return "6";
299  case 0x08: return "7";
300  case 0x09: return "8";
301  case 0x0a: return "9";
302  case 0x0c: return "+";
303  case 0x0d: return "E";
304  case 0x0e: return "-";
305  case 0x0f: return ".";
306  default: return "";
307  }
308  }
309  };
310 
311  extern phoenix::function<convertToNumberTokenImpl> convertToNumberToken;
312 
316  struct convertDigitsToHexImpl
317  {
318  typedef std::string result_type;
319 
320  template <typename T>
321  struct result
322  {
323  typedef result_type type;
324  };
325 
326  template <typename T>
327  result_type operator()(T arg) const
328  {
329  return "";
330  }
331 
332  result_type operator()(std::string arg) const
333  {
334  unsigned int hexNumber = atoi(arg.c_str());
335 
336  char buffer[512];
337  snprintf(buffer,512,"%#x",hexNumber);
338 
339  return std::string(buffer);
340  }
341  };
342 
343  extern phoenix::function<convertDigitsToHexImpl> convertDigitsToHex;
344 
345  struct convertToNativeShortImpl
346  {
347  typedef uint16_t result_type;
348 
349  template <typename T>
350  struct result
351  {
352  typedef result_type type;
353  };
354 
355  // for std::vector<char>
356  template <typename T>
357  result_type operator()(T arg) const
358  {
359  return ntohs(arg);
360  }
361  };
362 
363  extern phoenix::function<convertToNativeShortImpl> lazy_ntohs;
364 
365  struct convertToNativeLongImpl
366  {
367  typedef uint32_t result_type;
368 
369  template <typename T>
370  struct result
371  {
372  typedef result_type type;
373  };
374 
375  // for std::vector<char>
376  template <typename T>
377  result_type operator()(T arg) const
378  {
379  return ntohl(arg);
380  }
381  };
382 
383  extern phoenix::function<convertToNativeLongImpl> lazy_ntohl;
384 
385 
387  struct convertToStringImpl
388  {
389  typedef std::string result_type;
390 
391  template <typename T>
392  struct result
393  {
394  typedef result_type type;
395  };
396 
397  // for std::vector<char>
398  template <typename T>
399  result_type operator()(T arg) const
400  {
401  return std::string(arg.begin(), arg.end());
402  }
403 
404  result_type operator()(fipa::acl::ByteSequence arg) const
405  {
406  // TODO: (optional) perform some encoding stuff here
407  // using arg.encoding
408  return arg.toRawDataString();
409  }
410 
411 
412  };
413 
414  extern phoenix::function<convertToStringImpl> convertToString;
415 
417  struct convertToCharVectorImpl
418  {
419  typedef std::vector<unsigned char> result_type;
420 
421  template <typename T>
422  struct result
423  {
424  typedef result_type type;
425  };
426 
427  template<typename T>
428  result_type operator()(T arg) const
429  {
430  int length = arg.size();
431  std::vector<unsigned char> tmp;
432 
433  for(int i = 0; i < length; i++)
434  {
435  tmp.push_back((unsigned char) arg[i]);
436 
437  }
438  return tmp;
439  }
440 
441  };
442 
443  extern phoenix::function<convertToCharVectorImpl> convertToCharVector;
444 
445  struct createAgentIDImpl
446  {
447  typedef fipa::acl::AgentID result_type;
448 
449  template <typename T>
450  struct result
451  {
452  typedef result_type type;
453  };
454 
455  template<typename T>
456  fipa::acl::AgentID operator()(T arg) const
457  {
458  return fipa::acl::AgentID(arg);
459  }
460 
461  };
462 
463  extern phoenix::function<createAgentIDImpl> createAgentID;
464 
465  struct convertStringToNumberImpl
466  {
467  typedef boost::uint32_t result_type;
468  template <typename T>
469  struct result
470  {
471  typedef result_type type;
472  };
473 
474  template<typename T>
475  boost::uint32_t operator()(T arg) const
476  {
477  std::string number(arg.begin(),arg.begin() + strlen(arg.c_str()));
478  try {
479  return boost::lexical_cast<boost::uint32_t>(number);
480  } catch(const std::bad_cast& e)
481  {
482  LOG_ERROR("ConvertString failed: '%s'", arg.c_str());
483  LOG_ERROR("String_size: '%d'", arg.size());
484  LOG_ERROR("String_length: '%d'", strlen(arg.c_str()));
485  std::string msg = "ConvertStringToNumber failed for '" + number + "' " + std::string(e.what());
486  throw std::runtime_error(msg);
487  }
488  }
489  };
490 
491  extern phoenix::function<convertStringToNumberImpl> convertStringToNumber;
492 
493 
495  struct convertToTimeImpl
496  {
497  typedef fipa::acl::Time result_type;
498 
499  template <typename T, typename U>
500  struct result
501  {
502  typedef result_type type;
503  };
504 
505  result_type operator()(const std::string& arg, const std::string& msecs) const
506  {
507  fipa::acl::Time convertedTime;
508 #ifdef BOOST_SPIRIT_DEBUG
509  printf("convertToTimeImpl: %s:%s\n", arg.c_str(), msecs.c_str());
510 #endif
511  // TODO: windows portage
512  strptime(arg.c_str(),"%Y-%m-%dT%H:%M:%S",&convertedTime);
513  convertedTime.tm_msec = atoi(msecs.c_str());
514 
515  return convertedTime;
516  }
517  };
518 
519  extern phoenix::function<convertToTimeImpl> convertToTime;
520 
522  struct convertToBaseTimeImpl
523  {
524  typedef base::Time result_type;
525 
526  template <typename T>
527  struct result
528  {
529  typedef result_type type;
530  };
531 
532  template <typename T>
533  result_type operator()(T arg) const
534  {
535  return arg.toTime();
536  }
537 
538  result_type operator()(fipa::acl::DateTime arg) const
539  {
540  return arg.toTime();
541  }
542 
543  result_type operator()(std::string arg) const
544  {
545  std::string time = arg;
546  if ( arg.data()[0] == '-' || arg.data()[0] == '+')
547  {
548  time.erase(0,1);
549  }
550  std::string format = "%Y%m%dT%H%M%S";
551 
552  size_t end = time.find_last_of("0123456789", time.size() -1);
553  if( end < time.size() - 1)
554  {
555  // the type designator is present
556  format += "%Z";
557  }
558 
559  // Shift millisecond so that base::Time understands
560  // the format
561  std::string milliseconds = time.substr(end-2,3);
562  time.erase(end-2,3);
563  time += ":" + milliseconds;
564 
565  return base::Time::fromString(time, base::Time::Milliseconds, format);
566 
567  }
568  };
569 
570  extern phoenix::function<convertToBaseTimeImpl> convertToBaseTime;
571 
572 
573 
574 namespace acl {
575 namespace grammar {
576 // To avoid namespace clashes with boost::bind
577 namespace label = qi::labels;
578 
579 template<typename Iterator>
580 struct Index : qi::grammar<Iterator, uint_least16_t()>
581 {
582  Index() : Index::base_type(index_rule, "Index-bitefficient_grammar")
583  {
584  // Index is a pointer to code table entry and its size (in bits) depends on the code table size.
585  // If the code table size is 256 entries, the size of the index is one byte;
586  // otherwise its size is two bytes (represented in network byte order).
587  index_rule = qi::word [ label::_val = lazy_ntohs(label::_1)]
588  | qi::byte_ [ label::_val = label::_1 ]
589  ;
590 
591  FIPA_DEBUG_RULE(index_rule);
592  }
593 
594  qi::rule<Iterator, uint_least16_t() > index_rule;
595 };
596 
597 template<typename Iterator>
598 struct Len8 : qi::grammar<Iterator, boost::uint_least8_t()>
599 {
600  Len8(): Len8::base_type(len8_rule, "Len8-bitefficient_grammar")
601  {
602  len8_rule = qi::byte_;
603 
604  FIPA_DEBUG_RULE(len8_rule);
605  }
606 
607  qi::rule<Iterator, boost::uint_least8_t() > len8_rule;
608 };
609 
610 template<typename Iterator>
611 struct Len16 : qi::grammar<Iterator, boost::uint_least16_t()>
612 {
613  Len16(): Len16::base_type(len16_rule, "Len16-bitefficient_grammar")
614  {
615  // boost::uint_least16_t
616  len16_rule = qi::word [ label::_val = lazy_ntohs(label::_1) ];
617 
618  FIPA_DEBUG_RULE(len16_rule);
619  }
620 
621  qi::rule<Iterator, boost::uint_least16_t() > len16_rule;
622 };
623 
624 template<typename Iterator>
625 struct Len32 : qi::grammar<Iterator, boost::uint_least32_t()>
626 {
627  Len32(): Len32::base_type(len32_rule, "Len32-bitefficient_grammar")
628  {
629  // boost::uint_least32_t
630  len32_rule = qi::dword [ label::_val = lazy_ntohl(label::_1) ];
631 
632  FIPA_DEBUG_RULE(len32_rule);
633  }
634 
635  qi::rule<Iterator, boost::uint_least32_t() > len32_rule;
636 };
637 
638 template <typename Iterator>
639 struct StringLiteral : qi::grammar<Iterator, fipa::acl::ByteSequence(), qi::locals<std::string> >
640 {
641  StringLiteral() : StringLiteral::base_type(string_literal_rule, "StringLiteral-bitefficient_grammar")
642  {
643  using qi::byte_;
644  using encoding::char_;
645  using encoding::digit;
646 
647  // Order of statement is relevant here, since the character \ needs to be matched
648  // first -- matching is greedy with char_ otherwise
649  string_literal_rule = ( char_('"')
650  >> * (( char_("\\") >> char_('"') ) [ label::_a += "\"" ]
651  | (byte_ - char_('"') ) [ label::_a += label::_1 ]
652  )
653  >> char_('"')
654  ) [ phoenix::at_c<2>(label::_val) = label::_a ]
655  ;
656 
657  FIPA_DEBUG_RULE(string_literal_rule);
658  }
659 
660  qi::rule<Iterator, fipa::acl::ByteSequence(), qi::locals<std::string> > string_literal_rule;
661 };
662 
663 template<typename Iterator>
664 struct StringLiteralTerminated : qi::grammar<Iterator, fipa::acl::ByteSequence() >
665 {
666  StringLiteralTerminated() : StringLiteralTerminated::base_type(string_literal_terminated_rule, "StringLiteralTerminated-bitefficient_grammar")
667  {
668  string_literal_terminated_rule = stringLiteral [ label::_val = label::_1 ]
669  >> qi::byte_(0x00)
670  ;
671 
672  FIPA_DEBUG_RULE(string_literal_terminated_rule);
673  }
674 
675  qi::rule<Iterator, fipa::acl::ByteSequence()> string_literal_terminated_rule;
676  StringLiteral<Iterator> stringLiteral;
677 };
678 
679 template<typename Iterator>
680 struct ByteLengthEncodedString : qi::grammar<Iterator, fipa::acl::ByteSequence(), qi::locals<uint32_t> >
681 {
682  ByteLengthEncodedString() : ByteLengthEncodedString::base_type(byte_length_encoded_string_rule, "ByteLengthEncodedString-common_grammar")
683  {
684  using qi::byte_;
685  using encoding::char_;
686  using encoding::digit;
687 
688  byte_length_encoded_string_rule = byteLengthEncodedStringHeader [ label::_a = convertStringToNumber(label::_1) ]
689  >> qi::repeat(label::_a)[byte_] [ phoenix::at_c<2>(label::_val) = convertToCharVector(label::_1) ]
690  ;
691 
692  byteLengthEncodedStringHeader = char_('#')
693  >> + digit [ label::_val += label::_1 ]
694  >> char_('"')
695  ;
696 
697  FIPA_DEBUG_RULE(byte_length_encoded_string_rule);
698  }
699 
700  qi::rule<Iterator, std::string() > byteLengthEncodedStringHeader;
701  qi::rule<Iterator, fipa::acl::ByteSequence(), qi::locals<uint32_t> > byte_length_encoded_string_rule;
702 };
703 
704 template<typename Iterator>
705 struct ByteLengthEncodedStringTerminated : qi::grammar<Iterator, fipa::acl::ByteSequence(), qi::locals<std::string> >
706 {
707  ByteLengthEncodedStringTerminated() : ByteLengthEncodedStringTerminated::base_type(byte_length_encoded_string_terminated_rule, "ByteLengthEncodedStringTerminated-bitefficient_grammar")
708  {
709  using qi::byte_;
710  using encoding::char_;
711  using encoding::digit;
712 
713  byte_length_encoded_string_terminated_rule = ( byteLengthEncodedStringHeader [ phoenix::at_c<0>(label::_val) += label::_1 ]
714  >> * (byte_ - byte_(0x00)) [ label::_a += label::_1 ]
715  >> byte_(0x00)
716  ) [ phoenix::at_c<2>(label::_val) = label::_a ]
717  ;
718 
719  byteLengthEncodedStringHeader = char_('#')
720  >> + digit [ label::_val += label::_1 ]
721  >> char_('"')
722  ;
723 
724  FIPA_DEBUG_RULE(byte_length_encoded_string_terminated_rule);
725  }
726 
727  qi::rule<Iterator, std::string() > byteLengthEncodedStringHeader;
728  qi::rule<Iterator, fipa::acl::ByteSequence(), qi::locals<std::string> > byte_length_encoded_string_terminated_rule;
729 };
730 
731 template<typename Iterator>
732 struct NullTerminatedString : qi::grammar<Iterator, fipa::acl::ByteSequence()>
733 {
734  NullTerminatedString() : NullTerminatedString::base_type(null_terminated_string_rule, "NullTerminatedString-bitefficient_grammar")
735  {
736 
737  null_terminated_string_rule = stringLiteralTerminated
738  | byteLengthEncodedStringTerminated
739  ;
740 
741  FIPA_DEBUG_RULE(null_terminated_string_rule);
742  }
743 
744  qi::rule<Iterator, fipa::acl::ByteSequence()> null_terminated_string_rule;
745  StringLiteralTerminated<Iterator> stringLiteralTerminated;
746  ByteLengthEncodedStringTerminated<Iterator> byteLengthEncodedStringTerminated;
747 };
748 
749 template <typename Iterator>
750 struct Word : qi::grammar<Iterator, std::string()>
751 {
752  Word() : Word::base_type(word_rule, "Word-bitefficient_grammar")
753  {
754  using encoding::char_;
755 
756  word_rule = (char_ - wordExceptionsStart ) [ label::_val += label::_1 ]
757  >> *(char_ - wordExceptionsGeneral) [ label::_val += label::_1 ]
758  ;
759 
760  wordExceptionsStart %= wordExceptionsGeneral
761  | char_('#')
762  | char_('0','9')
763  | char_('-')
764  | char_('@')
765  ;
766  wordExceptionsGeneral %= char_(0x00,0x20)
767  | char_('(')
768  | char_(')')
769  ;
770  #ifdef BOOST_SPIRIT_DEBUG
771  BOOST_SPIRIT_DEBUG_NODE(wordExceptionsStart);
772  BOOST_SPIRIT_DEBUG_NODE(wordExceptionsGeneral);
773 
774  FIPA_DEBUG_RULE(word_rule);
775  #endif
776  }
777 
778  qi::rule<Iterator, std::string()> word_rule;
779  qi::rule<Iterator> wordExceptionsStart;
780  qi::rule<Iterator> wordExceptionsGeneral;
781 };
782 
783 template<typename Iterator>
784 struct Digits : qi::grammar<Iterator, std::string(), qi::locals<boost::uint_least8_t> >
785 {
786  Digits() : Digits::base_type(digits_rule, "Digits-bitefficient_grammar")
787  {
788  using encoding::char_;
789  digits_rule = lower_bits_padding [ label::_val += convertToNumberToken(label::_1) ]
790  | (+(qi::byte_ - end_padding_marker) [ label::_val += convertToNumberToken(label::_1) ]
791  >> end_padding_marker [ label::_val += convertToNumberToken(label::_1) ]
792  )
793  ;
794 
795  // padding bytes should only apply if the last codedNumber does not have 00 in the lowerbyte
796  end_padding_marker = char_(0x00) | lower_bits_padding;
797  lower_bits_padding = qi::byte_ [ label::_val = label::_1 ]
798  >> qi::eps( !(label::_val & 0x0f) )
799  ;
800 
801  FIPA_DEBUG_RULE(digits_rule);
802  FIPA_DEBUG_RULE(end_padding_marker);
803  FIPA_DEBUG_RULE(lower_bits_padding);
804 
805  }
806 
807  qi::rule<Iterator, std::string(), qi::locals<boost::uint_least8_t> > digits_rule;
808  qi::rule<Iterator, boost::uint_least8_t()> end_padding_marker;
809  qi::rule<Iterator, boost::uint_least8_t()> lower_bits_padding;
810 };
811 
812 
813 template<typename Iterator>
814 struct CodedNumber : qi::grammar<Iterator, std::string()>
815 {
816  CodedNumber() : CodedNumber::base_type(coded_number_rule, "CodedNumber-bitefficient_grammar")
817  {
818  // two numbers in one byte - padding 00 if coding only one number
819  coded_number_rule = (qi::byte_ - qi::byte_(0x00))[ label::_val = convertToNumberToken(label::_1)]
820  ;
821 
822  FIPA_DEBUG_RULE(coded_number_rule);
823  }
824 
825  qi::rule<Iterator, std::string()> coded_number_rule;
826 };
827 
828 template <typename Iterator>
829 struct DateTime : qi::grammar<Iterator, fipa::acl::Time(), qi::locals<std::string> >
830 {
831  DateTime() : DateTime::base_type(date_time_rule, "DateTime-bitefficient_grammar")
832  {
833 
834  // Construct/Fill Time()
835  // First read the standard input for struct tm
836  // then fill the extended millisecond field
837 
838  // Fixme: label::_a = string, label::_a += "-" will return only label::_a as "-"
839  // Currently using a workaround with 'buildString'
840  date_time_rule = (( ( year [ label::_a = buildString(label::_1,"-","") ]) //, label::_a = label::_1, label::_a += "-" ])//, print("yearinBinDate:", label::_1) ]*/ )
841  >> ( month [ label::_a = buildString(label::_a, label::_1,"-") ])
842  >> ( day [ label::_a = buildString(label::_a, label::_1,"T") ])
843  >> ( hour [ label::_a = buildString(label::_a, label::_1,":") ])
844  >> ( minute [ label::_a = buildString(label::_a, label::_1,":") ])
845  >> ( second [ label::_a = buildString(label::_a, label::_1,"") ])
846  )
847  >> ( millisecond [ label::_val = convertToTime(label::_a, label::_1) ])
848  )
849  ;
850 
851  year = ( codedNumber [ label::_val = label::_1] )
852  >> ( codedNumber [ label::_val += label::_1 ])
853  ;
854  // same format as year
855  millisecond = year.alias();
856 
857  #ifdef BOOST_SPIRIT_DEBUG
858  BOOST_SPIRIT_DEBUG_NODE(year);
859  BOOST_SPIRIT_DEBUG_NODE(millisecond);
860  #endif // BOOST_SPIRIT_DEBUG
861 
862  FIPA_DEBUG_RULE(date_time_rule);
863  }
864 
865  CodedNumber<Iterator> codedNumber;
866 
867  qi::rule<Iterator, fipa::acl::Time(), qi::locals<std::string> > date_time_rule;
868  qi::rule<Iterator, std::string() > year;
869  CodedNumber<Iterator> month;
870  CodedNumber<Iterator> day;
871  CodedNumber<Iterator> hour;
872  CodedNumber<Iterator> minute;
873  CodedNumber<Iterator> second;
874  qi::rule<Iterator, std::string() > millisecond;
875 
876 };
877 
878 template<typename Iterator>
879 struct String : qi::grammar<Iterator, std::string()>
880 {
881  String() : String::base_type(string_rule, "String-common_grammar")
882  {
883  string_rule = stringLiteral [ label::_val = convertToString(label::_1) ]
884  | byteLengthEncodedString [ label::_val = convertToString(label::_1) ]
885  ;
886 
887  FIPA_DEBUG_RULE(string_rule);
888  }
889 
890  StringLiteral<Iterator> stringLiteral;
891  ByteLengthEncodedString<Iterator> byteLengthEncodedString;
892  qi::rule<Iterator, std::string()> string_rule;
893 };
894 
895 } // end namespace grammar
896 } // end namespace acl
897 } // end namespace fipa
898 
899 
900 
901 #endif // FIPA_ACL_GRAMMAR_COMMON_H
phoenix::function< concatStringsWithSeparatorImpl > concatStringsWithSeparator
phoenix::function< convertToCharVectorImpl > convertToCharVector
phoenix::function< digitPaddingBytesImpl > digitPaddingBytes
phoenix::function< convertToNativeShortImpl > lazy_ntohs
phoenix::function< printImpl > print
phoenix::function< convertStringToNumberImpl > convertStringToNumber
phoenix::function< convertToStringImpl > convertToString
Representation of a byte sequence. We also embed information about the encoding.
boost::variant< std::string, std::vector< unsigned char > > ByteString
Definition of a ByteString.
Definition: byte_sequence.h:20
std::vector< AgentID > AgentIDList
Definition: agent_id.h:20
std::string toRawDataString() const
phoenix::function< createAgentIDImpl > createAgentID
BOOST_FUSION_ADAPT_STRUCT(fipa::acl::envelope::Parameter,(std::string, name)(fipa::acl::envelope::ParameterValue, data))
phoenix::function< convertToTimeImpl > convertToTime
boost::variant< boost::uint_least8_t, boost::uint_least16_t, boost::uint_least32_t > LengthValue
Definition of a length - internally used by the parser.
Definition: byte_sequence.h:15
phoenix::function< convertDigitsToHexImpl > convertDigitsToHex
phoenix::function< convertToBaseTimeImpl > convertToBaseTime
This class provides a representation of a message conforming to the FIPA specification SC00061...
Definition: acl_message.h:55
#define FIPA_ACL_FUSION_ADAPT
overloaded equality operator for UserdefParam class objects
Definition: userdef_param.h:25
#define FIPA_DEBUG_RULE(X)
phoenix::function< convertToNativeLongImpl > lazy_ntohl
base::Time toTime() const
Definition: date_time.cpp:28
phoenix::function< buildStringImpl > buildString
phoenix::function< convertToNumberTokenImpl > convertToNumberToken
Implements the general AgentID functionality, which is present throughout the fipa specifications(FIP...
Definition: agent_id.h:37
Foundation of Physical Intelligent Agents.
Definition: conversation.cpp:6
phoenix::function< extractFromCodetableImpl > extractFromCodetable