Package spade :: Module ACLParser
[hide private]
[frames] | no frames]

Source Code for Module spade.ACLParser

  1  # -*- coding: cp1252 -*- 
  2  from pyparsing import * 
  3  import sys 
  4  from ACLMessage import * 
  5  import AID 
  6  from BasicFipaDateTime import * 
  7   
  8  import xml.sax 
  9  from xml.sax import handler 
 10   
11 -class ACLParser:
12 """ 13 Parser for the ACL language 14 """ 15
16 - def __init__(self):
17 18 lpar = Literal("(").suppress() 19 rpar = Literal(")").suppress() 20 digit = oneOf("0 1 2 3 4 5 6 7 8 9") 21 sign = oneOf("+ -") 22 dot = Literal(".") 23 Exponent = oneOf("e E") 24 25 _bslash = "\\" 26 _escapables = 'tnrfbacdeghijklmopqsuvwxyz"' + _bslash 27 _octDigits = "01234567" 28 _escapedChar = ( Word( _bslash, _escapables, exact=2 ) | Word( _bslash, _octDigits, min=2, max=4 ) ) 29 30 _sglQuote = Literal("'") 31 _dblQuote = Literal('"') 32 StringLiteral = Combine( _dblQuote.suppress() + ZeroOrMore( CharsNotIn('\\"\r') | _escapedChar ) + _dblQuote.suppress() ).streamline() 33 34 35 #Word = [~ "\0x00" – "\0x20", "(", ")", "#", "0" – "9", "-", "@"] 36 # [~ "\0x00" – "\0x20", "(", ")"]* 37 ACLWord = Word(alphanums+"#@.-") 38 #StringLiteral = "\"" ([ ~ "\"" ] | "\\\"")* "\"" 39 #StringLiteral = Combine(Literal('"')+OneOrMore(Word(alphanums+"#@ .:-_[]()+?'¿¡!$%&=*,,;<>/\\"))+Literal('"')) 40 41 #ByteLengthEncodedString = "#" Digit+ "\"" <byte sequence> 42 ByteLengthEncodedString = Literal("TODO") 43 String = (StringLiteral | ByteLengthEncodedString) 44 45 46 Year = Combine(digit + digit + digit + digit) 47 Month = Combine(digit + digit) 48 Day = Combine(digit + digit) 49 Hour = Combine(digit + digit) 50 Minute = Combine(digit + digit) 51 Second = Combine(digit + digit) 52 MilliSecond = Combine(digit + digit + digit) 53 DateTime = Combine(Optional(sign) + Year + Month + Day + Literal("T") + Hour + Minute + Second + MilliSecond) 54 55 FloatExponent = Combine(Exponent + Optional(sign) + OneOrMore(digit)) 56 FloatMantissa = Combine((OneOrMore(digit) + dot + ZeroOrMore(digit)) | (ZeroOrMore(digit) + dot + OneOrMore(digit)) ) 57 Float = Combine((Optional(sign) + FloatMantissa + Optional(FloatExponent) ) | ( Optional(sign) + OneOrMore(digit) + FloatExponent )) 58 59 Integer = Combine(Optional(sign) + OneOrMore(digit)) 60 Number = Group(Integer | Float) 61 62 """ 63 #bnf de una URL 64 void=empty 65 digits = nums 66 hex = nums + "abcdefABCDEF" 67 safe = "$-_@.&+-" 68 extra = "!*\"'()," 69 escape = "%" + hex + hex 70 xalphas = Word(alphanums+safe+extra+escape) 71 ialpha = (Word(alphas) + Optional(xalphas)) 72 alphanum2 = alphanums+"-"+"_"+"."+"+" 73 password = Forward() 74 password << (alphanum2+Optional(password)) 75 user=Forward() 76 user << (alphanum2+Optional(user)) 77 search = Forward() 78 search << (xalphas + Optional(Literal("+")+search)) 79 segment = xalphas 80 path = Forward() 81 path << (void | (segment + Optional(Literal("/")+path))) 82 port = digits 83 hostname = Forward() 84 hostnumber = (digits + dot + digits + dot + digits + dot + digits) 85 hostname << ialpha + Optional(dot + hostname) 86 formcode = (Literal("N")|Literal("T")|Literal("C")) 87 ftptype = ((Literal("A")+formcode)|(Literal("E")+formcode)|Literal("I")|(Literal("L")+digits)) 88 host = (hostname|hostnumber) 89 hostport = (host + Optional(Literal(":")+port)) 90 login = (Optional(user + Optional(Literal(":")+password) + Literal("@")) + hostport ) 91 mailtoaddress = Combine(Literal("mailto:")+ xalphas + Literal("@") + hostname) 92 ftpaddress = Combine(Literal("ftp://")+login+Literal("/")+path+Optional(Literal(";")+ftptype)) 93 httpaddress = Combine(Literal("http://")+hostport+Optional(Literal("/")+path) +Optional(Literal("?")+search)) 94 URL = (httpaddress|ftpaddress|mailtoaddress) 95 """ 96 97 #URL = Word(alphanums+":/#@.") 98 URL = Word(alphanums+":/#@.-") 99 100 101 URLSequence = (lpar + Literal("sequence").suppress() + OneOrMore(URL) + rpar)#.setResultsName("URLseq") 102 103 AgentIdentifier = Forward() 104 105 AgentIdentifierSequence = Group(lpar + Literal("sequence").suppress() + OneOrMore(AgentIdentifier) + rpar)#.setResultsName("AIDseq") 106 107 #AddressSequence = Group(lpar + Literal("sequence").suppress() + OneOrMore(URL)+rpar) #Word(alphanums+"/.:+?")) + rpar) 108 109 AgentIdentifier << Group( \ 110 lpar + Literal("agent-identifier").suppress() + \ 111 #Literal(":name").suppress() + ACLWord.setResultsName("name") + \ 112 Literal(":name").suppress() + URL.setResultsName("name") + \ 113 Optional(Literal(":addresses").suppress() + URLSequence.setResultsName("addresses")) + \ 114 Optional(Literal(":resolvers").suppress() + AgentIdentifierSequence.setResultsName("resolvers")) +\ 115 # This one for the X-tras (thanks Jade) 116 # Make it more general-case oriented 117 Optional(Literal(":X-JADE-agent-classname").suppress() + URL.suppress()) + \ 118 rpar)#.setResultsName("AID") 119 120 #AgentIdentifier << Group(lpar + Literal("agent-identifier").suppress() + Literal(":name").suppress() + Word(alphanums+"@.").setResultsName("name") + Optional(Literal(":addresses").suppress() + URLSequence.setResultsName("addresses")) + Optional(Literal(":resolvers").suppress() + AgentIdentifierSequence.setResultsName("resolvers")) + rpar)#.setResultsName("AID") 121 122 AgentIdentifierSet = Group(lpar + Literal("set").suppress() + OneOrMore(AgentIdentifier) + rpar) 123 124 Expression = Forward() 125 Expression << (ACLWord | String | Number | DateTime | (lpar + Expression + rpar)) 126 #Expression << (Word(alphanums).setResultsName("word") | String.setResultsName("string") | Number.setResultsName("number") | DateTime.setResultsName("datetime") | Combine(lpar + Expression + rpar).setResultsName("expression")) 127 128 129 MessageParameter = ( \ 130 Literal(":sender").suppress() + AgentIdentifier.setResultsName("sender") | \ 131 Literal(":receiver").suppress() + AgentIdentifierSet.setResultsName("receiver") | \ 132 Literal(":content").suppress() + String.setResultsName("content") | \ 133 #Literal(":reply-with").suppress() + Expression.setResultsName("reply-with") | \ 134 Literal(":reply-with").suppress() + URL.setResultsName("reply-with") | \ 135 Literal(":reply-by").suppress() + DateTime.setResultsName("reply-by") | \ 136 Literal(":in-reply-to").suppress() + Expression.setResultsName("in-reply-to") | \ 137 Literal(":reply-to").suppress() + AgentIdentifierSet.setResultsName("reply-to") | \ 138 Literal(":language").suppress() + Expression.setResultsName("language") | \ 139 Literal(":encoding").suppress() + Expression.setResultsName("encoding") | \ 140 Literal(":ontology").suppress() + Expression.setResultsName("ontology") | \ 141 Literal(":protocol").suppress() + ACLWord.setResultsName("protocol") | \ 142 #Literal(":conversation-id").suppress() + Expression.setResultsName("conversation-id") \ 143 Literal(":conversation-id").suppress() + URL.setResultsName("conversation-id") \ 144 ) 145 146 MessageType = ( \ 147 Literal("accept-proposal")|\ 148 Literal("agree")|\ 149 Literal("cancel")|\ 150 Literal("cfp")|\ 151 Literal("confirm")|\ 152 Literal("disconfirm")|\ 153 Literal("failure")|\ 154 Literal("inform")|\ 155 Literal("inform-if")|\ 156 Literal("inform-ref")|\ 157 Literal("not-understood")|\ 158 Literal("propagate")|\ 159 Literal("propose")|\ 160 Literal("proxy")|\ 161 Literal("query-if")|\ 162 Literal("query-ref")|\ 163 Literal("refuse")|\ 164 Literal("reject-proposal")|\ 165 Literal("request")|\ 166 Literal("request-when")|\ 167 Literal("request-whenever")|\ 168 Literal("subscribe")|\ 169 # I'm looking at you, Jade! 170 Literal("ACCEPT-PROPOSAL")|\ 171 Literal("AGREE")|\ 172 Literal("CANCEL")|\ 173 Literal("CFP")|\ 174 Literal("CONFIRM")|\ 175 Literal("DISCONFIRM")|\ 176 Literal("FAILURE")|\ 177 Literal("INFORM")|\ 178 Literal("INFORM-IF")|\ 179 Literal("INFORM-REF")|\ 180 Literal("NOT-UNDERSTOOD")|\ 181 Literal("PROPAGATE")|\ 182 Literal("PROPOSE")|\ 183 Literal("PROXY")|\ 184 Literal("QUERY-IF")|\ 185 Literal("QUERY-REF")|\ 186 Literal("REFUSE")|\ 187 Literal("REJECT-PROPOSAL")|\ 188 Literal("REQUEST")|\ 189 Literal("REQUEST-WHEN")|\ 190 Literal("REQUEST-WHENEVER")|\ 191 Literal("SUBSCRIBE")\ 192 ) 193 194 Message = (lpar + MessageType.setResultsName("msgtype") + OneOrMore(MessageParameter.setResultsName("msgParameter")) + rpar)#.setResultsName("message") 195 196 ACLCommunicativeAct = Message 197 198 self.bnf = ACLCommunicativeAct 199 200 #bnf = OneOrMore(line).setResultsName("program") 201 202 #bnf.ignore(comment) 203 #bnf.ignore(directive) 204 205 try: 206 self.bnf.validate() 207 208 except Exception, err: 209 print err 210 sys.exit(-1)
211 212 213 #bnf.setDebug() 214
215 - def processAID(self, _aid):
216 """ 217 parses an AID. 218 returns a pyparsing.ParseResult class 219 """ 220 221 aid = AID.aid() 222 223 if 'name' in _aid: 224 aid.setName(_aid['name']) 225 226 if 'addresses' in _aid: 227 addr = _aid['addresses'] 228 for i in addr: 229 aid.addAddress(i) 230 231 if 'resolvers' in _aid: 232 res = _aid['resolvers'] 233 for i in res: 234 aid.addResolvers(self.processAID(i)) 235 236 return aid
237
238 - def parse(self,string):
239 """ 240 parses a string 241 returns a pyparsing.ParseResult class 242 """ 243 244 try: 245 m = self.bnf.parseString(string) 246 except ParseException, err: 247 print err.line 248 print " "*(err.column-1)+"^" 249 print err 250 sys.exit(-1) 251 except Exception, err: 252 print "Unkwonw Exception" 253 print err 254 sys.exit(-1) 255 256 return self.buildACL(m)
257
258 - def parseFile(self,file):
259 """ 260 parses a file 261 returns an ACLMessage 262 """ 263 264 try: 265 m = self.bnf.parseFile(file) 266 except ParseException, err: 267 print err.line 268 print " "*(err.column-1)+"^" 269 print err 270 sys.exit(-1) 271 except Exception, err: 272 print "Unkwonw Exception" 273 print err 274 sys.exit(-1) 275 276 return self.buildACL(m)
277
278 - def buildACL(self, m):
279 """ 280 returns an ACLMessage object from a pyparsing.ParseResults object 281 """ 282 283 #print repr(m) 284 #print m.asXML() 285 #print m.asList() 286 287 msg = ACLMessage() 288 289 if 'msgtype' in m: 290 msg.setPerformative(m['msgtype']) 291 292 if 'sender' in m: 293 msg.setSender(self.processAID(m['sender'])) 294 295 if 'receiver' in m: 296 recv = m['receiver'] 297 for i in recv: 298 msg.addReceiver(self.processAID(i)) 299 300 if 'content' in m: 301 msg.setContent(m['content']) 302 303 if 'reply-with' in m: 304 msg.setReplyWith(m['reply-with']) 305 306 if 'reply-by' in m: 307 msg.setReplyBy(BasicFipaDateTime(m['reply-by'])) 308 309 if 'in-reply-to' in m: 310 msg.setInReplyTo(m['in-reply-to']) 311 312 if 'reply-to' in m: 313 r = m['reply-to'] 314 for i in r: 315 msg.AddReplyTo(self.processAID(i)) 316 317 if 'language' in m: 318 msg.setLanguage(m['language']) 319 320 if 'encoding' in m: 321 msg.setEncoding(m['encoding']) 322 323 if 'ontology' in m: 324 msg.setOntology(m['ontology']) 325 326 if 'protocol' in m: 327 msg.setProtocol(m['protocol']) 328 329 if 'conversation-id' in m: 330 msg.setConversationId(m['conversation-id']) 331 332 333 return msg
334
335 -class ACLxmlParser(handler.ContentHandler):
336
337 - def __init__(self):
338 339 #constants 340 self.FIPA_MESSAGE_TAG = "fipa-message" 341 self.ACT_TAG = "act" 342 self.CONVERSATION_ID_TAG = "conversation-id" 343 self.SENDER_TAG = "sender" 344 self.RECEIVER_TAG = "receiver" 345 self.CONTENT_TAG = "content" 346 self.LANGUAGE_TAG = "language" 347 self.ENCODING_TAG = "encoding" 348 self.ONTOLOGY_TAG = "ontology" 349 self.PROTOCOL_TAG = "protocol" 350 self.REPLY_WITH_TAG = "reply-with" 351 self.IN_REPLY_TO_TAG = "in-reply-to" 352 self.REPLY_BY_TAG = "reply-by" 353 self.REPLY_TO_TAG = "reply-to" 354 self.CONVERSATION_ID_TAG = "conversation-id" 355 self.AGENT_ID_TAG = "agent-identifier" 356 self.NAME_TAG = "name" 357 self.ADDRESSES_TAG = "addresses" 358 self.URL_TAG = "url" 359 self.RESOLVERS_TAG = "resolvers" 360 self.USER_DEFINED_TAG = "user-defined" 361 self.TIME_TAG = "time" 362 self.ID_TAG = "id" 363 self.HREF_TAG = "href" 364 self.OT = "<" 365 self.ET = "</" 366 self.CT = ">" 367 self.NULL = ""
368 369 """ 370 *************************************************** 371 * Decoding methods * 372 *************************************************** 373 """ 374
375 - def startDocument(self):
376 self.msg = ACLMessage()
377
378 - def endDocument(self):
379 pass
380 381 #This method is called when exist characters in the elements
382 - def characters(self, buff):
383 self.accumulator = self.accumulator + buff
384
385 - def startElement(self, localName, attributes):
386 387 self.accumulator = "" 388 389 if self.FIPA_MESSAGE_TAG == localName.lower(): 390 self.msg.setPerformative(attributes.getValue(self.ACT_TAG)) 391 try: 392 self.msg.setConversationId(attributes.getValue(self.CONVERSATION_ID_TAG)) 393 394 except: 395 pass 396 397 if self.SENDER_TAG == localName.lower(): 398 self.aid = AID.aid() 399 self.aidTag = self.SENDER_TAG 400 401 if self.RECEIVER_TAG == localName.lower(): 402 self.aid = AID.aid() 403 self.aidTag = self.RECEIVER_TAG 404 405 if self.REPLY_TO_TAG == localName.lower(): 406 self.aid = AID.aid() 407 self.aidTag = self.REPLY_TO_TAG 408 409 if self.RESOLVERS_TAG == localName.lower(): 410 self.aid = AID.aid() 411 self.aidTag = self.RESOLVERS_TAG 412 413 if self.REPLY_BY_TAG == localName.lower(): 414 self.msg.setReplyBy(BasicFipaDateTime(attributes.getValue(self.TIME_TAG))) 415 416 if self.NAME_TAG == localName.lower(): 417 self.aid.setName(attributes.getValue(self.ID_TAG)) 418 419 if self.URL_TAG == localName.lower(): 420 self.aid.addAddress(attributes.getValue(self.HREF_TAG))
421 422
423 - def endElement(self, localName):
424 425 if self.CONTENT_TAG == localName.lower(): 426 self.msg.setContent(self.accumulator) 427 428 if self.LANGUAGE_TAG == localName.lower(): 429 self.msg.setLanguage(self.accumulator) 430 431 if self.ENCODING_TAG == localName.lower(): 432 self.msg.setEncoding(self.accumulator) 433 434 if self.ONTOLOGY_TAG == localName.lower(): 435 self.msg.setOntology(self.accumulator) 436 437 if self.PROTOCOL_TAG == localName.lower(): 438 self.msg.setProtocol(self.accumulator) 439 440 if self.REPLY_WITH_TAG == localName.lower(): 441 self.msg.setReplyWith(self.accumulator) 442 443 if self.IN_REPLY_TO_TAG == localName.lower(): 444 self.msg.setInReplyTo(self.accumulator) 445 446 if self.REPLY_TO_TAG == localName.lower() or \ 447 self.SENDER_TAG == localName.lower() or \ 448 self.RECEIVER_TAG == localName.lower() or \ 449 self.RESOLVERS_TAG == localName.lower(): 450 self.aidTag = "" 451 452 if self.CONVERSATION_ID_TAG == localName.lower(): 453 self.msg.setConversationId(self.accumulator) 454 455 if self.AGENT_ID_TAG == localName.lower(): 456 if self.aidTag == self.SENDER_TAG: 457 self.msg.setSender(self.aid) 458 elif self.aidTag == self.RECEIVER_TAG: 459 self.msg.addReceiver(self.aid) 460 elif self.aidTag == self.REPLY_TO_TAG: 461 self.msg.addReplyTo(self.aid) 462 elif self.aidTag == self.RESOLVERS_TAG: 463 self.msg.addResolvers(self.aid)
464 465 466 """ 467 This does the following: 468 < tag > 469 content 470 </ tag > 471 """
472 - def encodeTag( self, tag, content, proptag=None, propcontent=None):
473 sb = self.OT + tag 474 if proptag != None: 475 sb = sb + " " + proptag + '="' + str(propcontent) + '"' 476 477 if content == None or content == "": 478 sb = sb + "/" + self.CT 479 return sb 480 sb = sb + self.CT 481 sb = sb + content 482 sb = sb + self.ET + tag + self.CT 483 484 return sb
485 486 """ Encode the information of Agent, Tags To and From """
487 - def encodeAid(self, aid):
488 489 sb = self.OT + self.AGENT_ID_TAG + self.CT 490 sb = sb + self.encodeTag( self.NAME_TAG, None, self.ID_TAG, aid.getName() ) 491 492 sb = sb + self.OT + self.ADDRESSES_TAG + self.CT 493 addresses = aid.getAddresses() 494 for addr in addresses: 495 sb = sb + self.encodeTag( self.URL_TAG, "", self.HREF_TAG, addr ) 496 sb = sb + self.ET + self.ADDRESSES_TAG + self.CT 497 498 resolvers = aid.getResolvers() 499 if len(resolvers) > 0: 500 sb = sb + self.OT + self.RESOLVERS_TAG + self.CT 501 for res in resolvers: 502 sb = sb + self.encodeAid( res ) 503 sb = sb + self.ET + self.RESOLVERS_TAG + self.CT 504 505 sb = sb + self.ET + self.AGENT_ID_TAG + self.CT 506 507 return sb
508 509
510 - def encodeXML(self, msg):
511 512 sb = self.OT + self.FIPA_MESSAGE_TAG 513 if msg.getPerformative(): 514 sb += " " + self.ACT_TAG + '="' + msg.getPerformative() + '"' 515 sb += self.CT 516 517 #sender 518 if msg.getSender(): 519 sb += self.OT + self.SENDER_TAG + self.CT 520 sb += self.encodeAid(msg.getSender()) 521 sb += self.ET + self.SENDER_TAG + self.CT 522 523 #receivers 524 if len(msg.getReceivers()) > 0: 525 sb += self.OT + self.RECEIVER_TAG + self.CT 526 for r in msg.getReceivers(): 527 sb += self.encodeAid(r) 528 sb += self.ET + self.RECEIVER_TAG + self.CT 529 530 531 if msg.getContent(): 532 sb += self.encodeTag(self.CONTENT_TAG, str(msg.getContent())) 533 534 if msg.getLanguage(): 535 sb += self.encodeTag(self.LANGUAGE_TAG, msg.getLanguage()) 536 537 if msg.getEncoding(): 538 sb += self.encodeTag(self.ENCODING_TAG, msg.getEncoding()) 539 540 if msg.getOntology(): 541 sb += self.encodeTag(self.ONTOLOGY_TAG, msg.getOntology()) 542 543 if msg.getProtocol(): 544 sb += self.encodeTag(self.PROTOCOL_TAG, msg.getProtocol()) 545 546 if msg.getReplyWith(): 547 sb += self.encodeTag(self.REPLY_WITH_TAG, msg.getReplyWith()) 548 549 if msg.getInReplyTo(): 550 sb += self.encodeTag(self.IN_REPLY_TO_TAG, msg.getInReplyTo()) 551 552 if msg.getReplyBy(): 553 date = BasicFipaDateTime() 554 date.fromString( str(msg.getReplyBy()) ) 555 sb += self.encodeTag(self.REPLY_BY_TAG, str(date)) 556 557 if len(msg.getReplyTo()) > 0: 558 sb += self.OT + self.REPLY_TO_TAG + self.CT 559 for e in msg.getReplyTo(): 560 sb += self.encodeAid(e) 561 sb += self.ET + self.REPLY_TO_TAG + self.CT 562 563 if msg.getConversationId(): 564 sb += self.encodeTag(self.CONVERSATION_ID_TAG, msg.getConversationId()) 565 566 sb += self.ET + self.FIPA_MESSAGE_TAG + self.CT 567 568 return sb
569 570
571 - def parse(self, _in):
572 """ 573 parses the xml input 574 """ 575 xml.sax.parseString(_in, self) 576 return self.msg
577
578 - def parseFile(self, file):
579 xml.sax.parse(file,self) 580 return self.msg
581 582 583 584 585 586 #p = ACLParser() 587 #msg = p.parse("message3.acl") 588 #print msg 589 590 if __name__ == "__main__": 591 592 p = ACLxmlParser() 593 m= p.parseFile("m.xml") 594 print m 595 print p.encodeXML(m) 596 597 598 599 #Debug print 600 #print program.asXML("instruction") 601 #for line in program: 602 # print line 603 # for k in line.keys(): 604 # print k + ':' + str(line[k]) 605 # print 606 607 608 #exception control 609 # except ParseException,err: 610 # print err.line 611 # print " "*(err.column-1)+"^" 612 # print err 613 # 614 # except RecursiveGrammarException, err: 615 # print err.line 616 # print err 617