fipa_acl  1.4
grammar_string_message.h
Go to the documentation of this file.
1 #ifndef FIPA_ACL_GRAMMAR_STRING_MESSAGE_H
2 #define FIPA_ACL_GRAMMAR_STRING_MESSAGE_H
3 
4 #include <fipa_acl/message_parser/grammar/grammar_common.h>
5 #include <fipa_acl/message_generator/message_format.h>
6 
7 namespace fipa {
8 namespace acl {
9 namespace grammar {
10 namespace string {
11 
12 template<typename Iterator>
13 struct Keyword : qi::grammar<Iterator, std::string()>
14 {
15  Keyword() : Keyword::base_type(keyword, "keyword-string_grammar")
16  {
17  using namespace fipa::acl::MessageField;
18 
19  keyword = qi::no_case[
20  qi::lit(":" + MessageFieldTxt[SENDER])
21  | qi::lit(":" + MessageFieldTxt[RECEIVER])
22  | qi::lit(":" + MessageFieldTxt[CONTENT])
23  | qi::lit(":" + MessageFieldTxt[REPLY_WITH])
24  | qi::lit(":" + MessageFieldTxt[REPLY_BY])
25  | qi::lit(":" + MessageFieldTxt[IN_REPLY_TO])
26  | qi::lit(":" + MessageFieldTxt[REPLY_TO])
27  | qi::lit(":" + MessageFieldTxt[LANGUAGE])
28  | qi::lit(":" + MessageFieldTxt[ENCODING])
29  | qi::lit(":" + MessageFieldTxt[ONTOLOGY])
30  | qi::lit(":" + MessageFieldTxt[PROTOCOL])
31  | qi::lit(":" + MessageFieldTxt[CONVERSATION_ID])
32  // These are possible inside an agent-identifier
33  | qi::lit(":resolvers")
34  | qi::lit(":addresses")
35  ];
36 
37  //FIPA_DEBUG_RULE(keyword);
38  }
39 
40  qi::rule<Iterator, std::string()> keyword;
41 };
42 
43 template<typename Iterator>
44 struct WordWithoutKeyword : qi::grammar<Iterator, std::string()>
45 {
46  WordWithoutKeyword() : WordWithoutKeyword::base_type(word_rule, "word_without_keyword-string_grammar")
47  {
48  using encoding::char_;
49 
50  word_rule = (char_ - wordExceptionsStart ) [ label::_val += label::_1 ]
51  >> *(!keyword >> (char_ - wordExceptionsGeneral) [ label::_val += label::_1 ]
52  );
53 
54  wordExceptionsStart %= wordExceptionsGeneral
55  | char_('#')
56  | char_('0','9')
57  | char_('-')
58  | char_('@')
59  ;
60  wordExceptionsGeneral %= char_(0x00,0x20)
61  | char_('(')
62  | char_(')')
63  ;
64  }
65 
67 
68  qi::rule<Iterator, std::string()> word_rule;
69  qi::rule<Iterator> wordExceptionsStart;
70  qi::rule<Iterator> wordExceptionsGeneral;
71 };
72 
73 template<typename Iterator>
74 struct Url : qi::grammar<Iterator, std::string()>
75 {
76  Url() : Url::base_type(url, "url-string_grammar")
77  {
78  using encoding::char_;
79 
80  // TODO: proper URI parsing.
81  // At the moment just a word without keyword
82  url = wordWithoutKeyword [ label::_val += label::_1 ]
83  ;
84 
85  // FIPA_DEBUG_RULE(url);
86  }
87 
89  qi::rule<Iterator, std::string()> url;
90 };
91 
92 template<typename Iterator, typename Skipper = qi::unused_type>
93 struct UrlSequence : qi::grammar<Iterator, std::vector<std::string>(), Skipper>
94 {
95  UrlSequence() : UrlSequence::base_type(urlSequence, "url_sequence-string_grammar")
96  {
97 
98  urlSequence = qi::lit("(")
99  >> qi::no_case[qi::lit("sequence")]
100  >> * url [ phoenix::push_back(label::_val, label::_1) ]
101  >> ")";
102 
103  // FIPA_DEBUG_RULE(urlSequence);
104  }
105 
107  qi::rule<Iterator, std::vector<std::string>(), Skipper> urlSequence;
108 
109 };
110 
111 template<typename Iterator>
112 struct Number : qi::grammar<Iterator, std::string() >
113 {
114  Number() : Number::base_type(number, "number-string_grammar")
115  {
116  using encoding::char_;
117 
118  number = float_number [ label::_val = label::_1 ]
119  | integer_number [ label::_val = label::_1 ]
120  ;
121 
122  integer_number = - sign [ label::_val = label::_1 ]
123  >> +digit [ label::_val += label::_1 ]
124  ;
125 
126  sign = encoding::string("+")
127  | encoding::string("-");
128 
129  digit = char_('0','9');
130 
131  float_number = (-sign [ label::_val = label::_1 ]
132  >> float_mantissa [ label::_val += label::_1 ]
133  >> - float_exponent [ label::_val += label::_1 ]
134  )
135  | ( -sign [ label::_val = label::_1 ]
136  >> +digit [ label::_val += label::_1 ]
137  >> float_exponent [ label::_val += label::_1 ]
138  );
139 
140  float_mantissa = ( +digit [ label::_val = label::_1 ]
141  >> char_('.') [ label::_val += label::_1 ]
142  >> *digit [ label::_val += label::_1 ]
143  )
144  | ( *digit [ label::_val = label::_1 ]
145  >> char_('.') [ label::_val += label::_1 ]
146  >> +digit [ label::_val += label::_1 ]
147  );
148 
149  float_exponent = exponent [ label::_val = label::_1 ]
150  >> - sign [ label::_val += label::_1 ]
151  >> +digit [ label::_val += label::_1 ]
152  ;
153 
154  exponent = encoding::string("e")
155  | encoding::string("E");
156 
157  FIPA_DEBUG_RULE(integer_number);
158  FIPA_DEBUG_RULE(float_number);
159  }
160 
161  qi::rule<Iterator, std::string()> integer_number;
162  qi::rule<Iterator, std::string()> float_number;
163 
164  qi::rule<Iterator, std::string()> sign;
165  qi::rule<Iterator, char()> digit;
166  qi::rule<Iterator, std::string()> float_mantissa;
167  qi::rule<Iterator, std::string()> float_exponent;
168  qi::rule<Iterator, std::string()> exponent;
169 
170  qi::rule<Iterator, std::string()> number;
171 };
172 
173 template<typename Iterator>
174 struct DateTimeToken : qi::grammar<Iterator, std::string() >
175 {
176  DateTimeToken() : DateTimeToken::base_type(date_time, "date_time_token-string_grammar")
177  {
178  using encoding::char_;
179 
180  date_time = - sign [ label::_val = label::_1 ]
181  >> year [ label::_val += label::_1 ]
182  >> month [ label::_val += label::_1 ]
183  >> day [ label::_val += label::_1 ]
184  >> char_('T') [ label::_val += label::_1 ]
185  >> hour [ label::_val += label::_1 ]
186  >> minute [ label::_val += label::_1 ]
187  >> second [ label::_val += label::_1 ]
188  >> millisecond [ label::_val += label::_1 ]
189  >> - typeDesignator [ label::_val += label::_1 ]
190  ;
191 
192  sign = encoding::string("+")
193  | encoding::string("-");
194 
195  typeDesignator = char_('a','z')
196  | char_('A','Z');
197 
198  digit = char_('0','9');
199 
200  year = digit
201  >> digit
202  >> digit
203  >> digit;
204 
205  month = digit
206  >> digit;
207 
208  day = month.alias();
209  hour = month.alias();
210  minute = month.alias();
211  second = month.alias();
212 
213  millisecond = digit
214  >> digit
215  >> digit
216  ;
217 
218  FIPA_DEBUG_RULE(date_time);
219 
220  }
221 
222  qi::rule<Iterator, std::string()> year;
223  qi::rule<Iterator, std::string()> month;
224  qi::rule<Iterator, std::string()> day;
225  qi::rule<Iterator, std::string()> hour;
226  qi::rule<Iterator, std::string()> minute;
227  qi::rule<Iterator, std::string()> second;
228 
229  qi::rule<Iterator, char()> digit;
230  qi::rule<Iterator, std::string()> sign;
231  qi::rule<Iterator, char()> typeDesignator;
232 
233  qi::rule<Iterator, std::string()> millisecond;
234  qi::rule<Iterator, std::string()> date_time;
235 };
236 
237 template<typename Iterator>
238 struct DateTime : qi::grammar<Iterator, base::Time() >
239 {
240  DateTime() : DateTime::base_type(date_time, "date_time-string_grammar")
241  {
242  date_time = dateTime [ label::_val = convertToBaseTime(label::_1) ]
243  ;
244 
245  FIPA_DEBUG_RULE(date_time);
246  }
247 
249  qi::rule<Iterator, base::Time()> date_time;
250 };
251 
252 
253 template<typename Iterator, typename Skipper = qi::unused_type>
254 struct Expression : qi::grammar<Iterator, std::string(), Skipper>
255 {
256 
257  Expression() : Expression::base_type(expression, "expression-string_grammar")
258  {
259  using phoenix::construct;
260  using phoenix::val;
261  using encoding::char_;
262 
263  using namespace fipa::acl;
264  namespace label = qi::labels;
265 
266  expression = expression_base [ label::_val = label::_1 ]
267  | ( char_('(')
268  >> *expression [ label::_val = concatStringsWithSeparator(label::_val,label::_1," ") ]
269  >> char_(')')
270  )
271  ;
272 
273  expression_base = string
274  | number
275  | dateTime
276  | wordWithoutKeyword
277  ;
278  }
279 
280  grammar::String<Iterator> string;
284 
285  qi::rule<Iterator, std::string(), Skipper> expression;
286  qi::rule<Iterator, std::string()> expression_base;
287 };
288 
289 template<typename Iterator>
290 struct UserdefinedParameter : qi::grammar<Iterator, fipa::acl::UserdefParam(), qi::locals<std::string, std::string> >
291 {
292 
293  UserdefinedParameter() : UserdefinedParameter::base_type(param, "userdefined_parameter-string_grammar")
294  {
295  using phoenix::construct;
296  using phoenix::val;
297 
298  using namespace fipa::acl;
299  namespace label = qi::labels;
300 
301  param = (paramLabel [ label::_a = label::_1 ]
302  >> expression [ label::_b = label::_1 ]
303  ) [ label::_val = phoenix::construct<fipa::acl::UserdefParam>(label::_a, label::_b)]
304  ;
305 
306  paramLabel = qi::lit(":X-")
307  // TODO: keyword list needs to be dynamically updated or previously known,
308  // otherwise parsing will greedly consume the following parameter expression
309  // For now expression should be provided with parentheses to handle this
310  >> wordWithoutKeyword [ label::_val = label::_1 ]
311  ;
312  }
313 
314  qi::rule<Iterator, std::string()> paramLabel;
317  qi::rule<Iterator, fipa::acl::UserdefParam(), qi::locals<std::string,std::string> > param;
318 };
319 
320 template<typename Iterator>
321 struct UserdefinedParameterList : qi::grammar<Iterator, std::vector<fipa::acl::UserdefParam>()>
322 {
323 
324  UserdefinedParameterList() : UserdefinedParameterList::base_type(param_list, "userdefined_parameter_list-string_grammar")
325  {
326  using namespace fipa::acl;
327  namespace label = qi::labels;
328 
329  param_list = +userdefinedParam [ phoenix::push_back(label::_val, label::_1)]
330  ;
331  }
332 
334  qi::rule<Iterator, std::vector<fipa::acl::UserdefParam>() > param_list;
335 };
336 
337 template<typename Iterator, typename Skipper = qi::unused_type>
338 struct Resolver : qi::grammar<Iterator, fipa::acl::AgentID(), Skipper>
339 {
340 
341  Resolver() : Resolver::base_type(agentId, "resolver-string_grammar")
342  {
343  using namespace fipa::acl;
344  namespace label = qi::labels;
345 
346  agentId = qi::lit("(")
347  >> qi::no_case[qi::lit("agent-identifier")]
348  >> qi::no_case[qi::lit(":name")] >> word [ phoenix::at_c<0>(label::_val) = label::_1 ]
349  >> - (qi::no_case[qi::lit(":addresses")] >> urlSequence [ phoenix::at_c<1>(label::_val) = label::_1 ])
350  // Leaving out additional resolvers !!! to break recursion
351  >> - (userdefinedParameterList [ phoenix::at_c<3>(label::_val) = label::_1 ])
352  >> ")";
353 
354  //FIPA_DEBUG_RULE(agentId);
355  }
356 
361  qi::rule<Iterator, fipa::acl::AgentID(), Skipper> agentId;
362 };
363 
364 template<typename Iterator, typename Skipper = qi::unused_type>
365 struct AgentIdentifierSequence : qi::grammar<Iterator,AgentIDList(), Skipper>
366 {
367 
368  AgentIdentifierSequence() : AgentIdentifierSequence::base_type(agentIdList, "agent_identifier_sequence-string_grammar")
369  {
370  using namespace fipa::acl;
371  namespace label = qi::labels;
372 
373  agentIdList = qi::lit("(")
374  >> qi::no_case[qi::lit("sequence")]
375  >> * agentIdentifier [ phoenix::push_back(label::_val, label::_1) ]
376  >> ")";
377 
378  //FIPA_DEBUG_RULE(agentIdList);
379  }
380 
382  qi::rule<Iterator, fipa::acl::AgentIDList(), Skipper> agentIdList;
383 };
384 
385 
386 template<typename Iterator, typename Skipper = qi::unused_type>
387 struct AgentIdentifier : qi::grammar<Iterator, fipa::acl::AgentID(), Skipper>
388 {
389 
390  AgentIdentifier() : AgentIdentifier::base_type(agentId, "agentidentifier-string_grammar")
391  {
392  using namespace fipa::acl;
393  namespace label = qi::labels;
394 
395  agentId = qi::lit("(")
396  >> qi::no_case[qi::lit("agent-identifier")]
397  >> qi::no_case[qi::lit(":name")] >> word [ phoenix::at_c<0>(label::_val) = label::_1 ]
398  >> -( qi::no_case[qi::lit(":addresses")] >> urlSequence [ phoenix::at_c<1>(label::_val) = label::_1 ])
399  >> -( qi::no_case[qi::lit(":resolvers")] >> agentIdSequence [ phoenix::at_c<2>(label::_val) = label::_1 ])
400  >> - (userdefinedParameterList [ phoenix::at_c<3>(label::_val) = label::_1 ])
401  >> ")";
402 
403  //FIPA_DEBUG_RULE(agentId);
404  }
405 
410  qi::rule<Iterator, fipa::acl::AgentID(), Skipper> agentId;
411 
412 };
413 
414 template<typename Iterator, typename Skipper = qi::unused_type>
415 struct AgentIdentifierSet : qi::grammar<Iterator,AgentIDList(),Skipper >
416 {
417 
418  AgentIdentifierSet() : AgentIdentifierSet::base_type(agentIdList, "agent_identifier_set-string_grammar")
419  {
420  using namespace fipa::acl;
421  namespace label = qi::labels;
422 
423  agentIdList = qi::lit("(")
424  >> qi::no_case[qi::lit("set")]
425  >> * agentIdentifier [ phoenix::push_back(label::_val, label::_1) ]
426  >> ")";
427 
428  //FIPA_DEBUG_RULE(agentIdList);
429  }
430 
432  qi::rule<Iterator, fipa::acl::AgentIDList(), Skipper> agentIdList;
433 };
434 
435 
436 template<typename Iterator, typename Skipper = qi::unused_type >
437 struct Message : qi::grammar<Iterator, fipa::acl::ACLMessage(), Skipper>
438 {
439  Message() : Message::base_type(aclCommunicativeAct, "message-string_grammar")
440  {
441  using namespace fipa::acl;
442  using namespace MessageField;
443 
444  // To avoid namespace clashes with boost::bind
445  namespace label = qi::labels;
446 
447  aclCommunicativeAct = "("
448  >> messageType [ phoenix::at_c<0>(label::_val) = label::_1 ]
449  >> *( qi::no_case[
450  qi::lit(":" + MessageFieldTxt[SENDER]) >> agentId [ phoenix::at_c<1>(label::_val) = label::_1 ]
451  | qi::lit(":" + MessageFieldTxt[RECEIVER]) >> agentIdList [ phoenix::at_c<2>(label::_val) = label::_1 ]
452  | qi::lit(":" + MessageFieldTxt[CONTENT]) >> content [ phoenix::at_c<3>(label::_val) = label::_1 ]
453  | qi::lit(":" + MessageFieldTxt[REPLY_WITH]) >> expression [ phoenix::at_c<4>(label::_val) = label::_1 ]
454  | qi::lit(":" + MessageFieldTxt[REPLY_BY]) >> dateTime [ phoenix::at_c<5>(label::_val) = label::_1 ]
455  | qi::lit(":" + MessageFieldTxt[IN_REPLY_TO]) >> expression [ phoenix::at_c<6>(label::_val) = label::_1 ]
456  | qi::lit(":" + MessageFieldTxt[REPLY_TO]) >> agentIdList [ phoenix::at_c<7>(label::_val) = label::_1 ]
457  | qi::lit(":" + MessageFieldTxt[LANGUAGE]) >> expression [ phoenix::at_c<8>(label::_val) = label::_1 ]
458  | qi::lit(":" + MessageFieldTxt[ENCODING]) >> expression [ phoenix::at_c<9>(label::_val) = label::_1 ]
459  | qi::lit(":" + MessageFieldTxt[ONTOLOGY]) >> expression [ phoenix::at_c<10>(label::_val) = label::_1 ]
460  | qi::lit(":" + MessageFieldTxt[PROTOCOL]) >> wordWithoutKeyword [ phoenix::at_c<11>(label::_val) = label::_1 ]
461  | qi::lit(":" + MessageFieldTxt[CONVERSATION_ID]) >> expression [ phoenix::at_c<12>(label::_val) = label::_1 ]
462  | userdefinedParam [ phoenix::at_c<13>(label::_val) = label::_1 ]
463  ])
464  >> ")";
465 
466  messageType = qi::no_case[
467  qi::string(PerformativeTxt[ACLMessage::ACCEPT_PROPOSAL]) [ label::_val = label::_1 ]
468  | qi::string(PerformativeTxt[ACLMessage::AGREE]) [ label::_val = label::_1 ]
469  | qi::string(PerformativeTxt[ACLMessage::CANCEL]) [ label::_val = label::_1 ]
470  | qi::string(PerformativeTxt[ACLMessage::CALL_FOR_PROPOSAL]) [ label::_val = label::_1 ]
471  | qi::string(PerformativeTxt[ACLMessage::CONFIRM]) [ label::_val = label::_1 ]
472  | qi::string(PerformativeTxt[ACLMessage::DISCONFIRM]) [ label::_val = label::_1 ]
473  | qi::string(PerformativeTxt[ACLMessage::FAILURE]) [ label::_val = label::_1 ]
474  | qi::string(PerformativeTxt[ACLMessage::INFORM_IF]) [ label::_val = label::_1 ]
475  | qi::string(PerformativeTxt[ACLMessage::INFORM_REF]) [ label::_val = label::_1 ]
476  | qi::string(PerformativeTxt[ACLMessage::INFORM]) [ label::_val = label::_1 ]
477  | qi::string(PerformativeTxt[ACLMessage::NOT_UNDERSTOOD]) [ label::_val = label::_1 ]
478  | qi::string(PerformativeTxt[ACLMessage::PROPAGATE]) [ label::_val = label::_1 ]
479  | qi::string(PerformativeTxt[ACLMessage::PROPOSE]) [ label::_val = label::_1 ]
480  | qi::string(PerformativeTxt[ACLMessage::PROXY]) [ label::_val = label::_1 ]
481  | qi::string(PerformativeTxt[ACLMessage::QUERY_IF]) [ label::_val = label::_1 ]
482  | qi::string(PerformativeTxt[ACLMessage::QUERY_REF]) [ label::_val = label::_1 ]
483  | qi::string(PerformativeTxt[ACLMessage::REFUSE]) [ label::_val = label::_1 ]
484  | qi::string(PerformativeTxt[ACLMessage::REJECT_PROPOSAL]) [ label::_val = label::_1 ]
485  // order from most specific to least specific, to avoid early parsing success
486  | qi::string(PerformativeTxt[ACLMessage::REQUEST_WHENEVER]) [ label::_val = label::_1 ]
487  | qi::string(PerformativeTxt[ACLMessage::REQUEST_WHEN]) [ label::_val = label::_1 ]
488  | qi::string(PerformativeTxt[ACLMessage::REQUEST]) [ label::_val = label::_1 ]
489  | qi::string(PerformativeTxt[ACLMessage::SUBSCRIBE]) [ label::_val = label::_1 ]
490  ];
491 
492  FIPA_DEBUG_RULE(messageType);
493  }
494 
495 
498  grammar::String<Iterator> content;
499  grammar::Word<Iterator> word;
502  qi::rule<Iterator, std::string()> messageType;
503  qi::rule<Iterator, fipa::acl::ACLMessage(), Skipper> aclCommunicativeAct;
506 
507 };
508 
509 } // end namespace string
510 } // end namespace grammar
511 } // end namespace acl
512 } // end namespace fipa
513 
514 
515 #endif //FIPA_ACL_GRAMMAR_STRING_MESSAGE_H
phoenix::function< concatStringsWithSeparatorImpl > concatStringsWithSeparator
qi::rule< Iterator, fipa::acl::ACLMessage(), Skipper > aclCommunicativeAct
qi::rule< Iterator, std::string()> url
UserdefinedParameterList< Iterator > userdefinedParameterList
UrlSequence< Iterator, Skipper > urlSequence
qi::rule< Iterator, std::string()> sign
AgentIdentifier< Iterator, Skipper > agentIdentifier
qi::rule< Iterator, std::string()> minute
qi::rule< Iterator, std::string()> sign
qi::rule< Iterator, fipa::acl::UserdefParam(), qi::locals< std::string, std::string > > param
qi::rule< Iterator, std::string()> integer_number
qi::rule< Iterator, std::string()> messageType
qi::rule< Iterator, std::string()> date_time
qi::rule< Iterator, std::string()> float_number
qi::rule< Iterator, std::string()> float_exponent
WordWithoutKeyword< Iterator > wordWithoutKeyword
qi::rule< Iterator, std::string()> second
std::map< MessageField::Type, std::string > MessageFieldTxt
qi::rule< Iterator, std::string()> month
qi::rule< Iterator, std::string()> year
UserdefinedParameterList< Iterator > userdefinedParameterList
qi::rule< Iterator, std::string()> keyword
qi::rule< Iterator, std::string()> hour
qi::rule< Iterator, fipa::acl::AgentID(), Skipper > agentId
UserdefinedParameter< Iterator > userdefinedParam
AgentIdentifierSet< Iterator, Skipper > agentIdList
qi::rule< Iterator, std::string()> exponent
qi::rule< Iterator, std::string()> float_mantissa
AgentIdentifier< Iterator, Skipper > agentId
WordWithoutKeyword< Iterator > word
std::map< ACLMessage::Performative, std::string > PerformativeTxt
Definition: acl_message.cpp:15
qi::rule< Iterator, fipa::acl::AgentID(), Skipper > agentId
AgentIdentifierSequence< Iterator, Skipper > agentIdSequence
phoenix::function< convertToBaseTimeImpl > convertToBaseTime
qi::rule< Iterator, fipa::acl::AgentIDList(), Skipper > agentIdList
WordWithoutKeyword< Iterator > wordWithoutKeyword
qi::rule< Iterator, fipa::acl::AgentIDList(), Skipper > agentIdList
qi::rule< Iterator, std::string()> number
qi::rule< Iterator, std::string()> day
qi::rule< Iterator, std::string()> expression_base
qi::rule< Iterator, std::string()> millisecond
#define FIPA_DEBUG_RULE(X)
qi::rule< Iterator, std::string()> word_rule
Foundation of Physical Intelligent Agents.
Definition: conversation.cpp:6
qi::rule< Iterator, std::string(), Skipper > expression
qi::rule< Iterator, base::Time()> date_time
UrlSequence< Iterator, Skipper > urlSequence
Agent Communication Language.
Definition: conversation.cpp:7
Expression< Iterator, Skipper > expression
WordWithoutKeyword< Iterator > wordWithoutKeyword