[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[certi-cvs] certi/scripts GenerateMessages.py TestMessageSp...
From: |
certi-cvs |
Subject: |
[certi-cvs] certi/scripts GenerateMessages.py TestMessageSp... |
Date: |
Tue, 14 Jul 2009 12:40:51 +0000 |
CVSROOT: /sources/certi
Module name: certi
Changes by: Eric NOULARD <erk> 09/07/14 12:40:50
Modified files:
scripts : GenerateMessages.py TestMessageSpec.msg
Added files:
scripts : CertiNetworkMessage.msg
Log message:
Better parser.
The AST is near complete, but
- needs to attach comment
- better defined sub-object for
EnumSymbol
MessageField
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/certi/scripts/GenerateMessages.py?cvsroot=certi&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/certi/scripts/TestMessageSpec.msg?cvsroot=certi&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/certi/scripts/CertiNetworkMessage.msg?cvsroot=certi&rev=1.1
Patches:
Index: GenerateMessages.py
===================================================================
RCS file: /sources/certi/certi/scripts/GenerateMessages.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- GenerateMessages.py 13 Jul 2009 21:39:28 -0000 1.2
+++ GenerateMessages.py 14 Jul 2009 12:40:49 -0000 1.3
@@ -4,8 +4,18 @@
import getopt, sys
import shutil
# We use PLY in order to parse CERTI message specification files
+# PLY is there: http://www.dabeaz.com/ply/
import ply.yacc
import ply.lex
+# We use logging for ... logging :-)
+import logging
+
+
+stdoutHandler = logging.StreamHandler(sys.stdout)
+stdoutHandler.setFormatter(logging.Formatter("%(msecs)d-[%(name)s::%(levelname)s]
%(message)s"))
+mylogger = logging.Logger("GenerateMessage")
+mylogger.setLevel(logging.ERROR)
+mylogger.addHandler(stdoutHandler)
def usage():
print "Usage:\n %s --file=<message> [--language=C++|Java|Python]
[--type=header|body|factory] [--verbose] [--help]" %
os.path.basename(sys.argv[0])
@@ -13,7 +23,7 @@
try:
opts, args = getopt.getopt(sys.argv[1:], "f:l:t:vh",
["file=","language=","type=","verbose","help"])
except getopt.GetoptError, err:
- print >> stderr, "opt = %s, msg = %s" % (err.opt,err.msg)
+ mylogger.error("opt = %s, msg = %s" % (err.opt,err.msg))
usage()
sys.exit(2)
@@ -43,6 +53,7 @@
# Lexer+Parser specification begins here
# reserved keywords
reserved = {
+ 'package' : 'PACKAGE',
'native_message' : 'NATIVE_MESSAGE',
'message' : 'MESSAGE',
'merge' : 'MERGE',
@@ -77,9 +88,10 @@
'COMMA',
'EQUAL',
'COLON',
+ 'PERIOD',
] + list(reserved.values())
-# This is a message of field identifier
+# This is a message of field or name identifier
def t_ID(t):
r'[a-zA-Z_][a-zA-Z_0-9]*'
t.type = reserved.get(t.value,'ID') # Check for reserved words
@@ -128,6 +140,7 @@
t_COMMA = r','
t_EQUAL = r'='
t_COLON = r':'
+t_PERIOD = r'\.'
# Define a rule so we can track line numbers
def t_newline(t):
@@ -145,17 +158,60 @@
# Build the PLY lexer
lexer = ply.lex.lex()
+# Named Class
+class Named(object):
+ def __init__(self,name):
+ self.__name = name
+ self.__comment = None
+
+ def __getName(self):
+ return self.__name
+ def __setName(self,name):
+ self.__name = name
+ # pythonic getter/setter using properties
+ name = property(fget=__getName,fset=__setName)
+
+ def __getComment(self):
+ return self.__comment
+ def __setComment(self,comment):
+ self.__comment = comment
+ # pythonic getter/setter using properties
+ name = property(fget=__getComment,fset=__setComment)
+
# Message set
-class MessageAST(object):
+class MessageNotAnAST(Named):
def __init__(self,name):
- self.name = name
- self.nativeMessageType = set()
- self.messageTypeSet = set()
- self.enumTypeSet = set()
+ super(MessageNotAnAST,self).__init__(name=name)
+ self.__nativeMessageTypeSet = set()
+ self.__messageTypeSet = set()
+ self.__enumTypeSet = set()
+ self.__package = None
+ self.__types = dict()
+ self.logger = logging.Logger("MessageNotAnAST")
+ self.logger.setLevel(logging.ERROR)
+ self.logger.addHandler(stdoutHandler)
+
+ def __getNativeMessageTypeSet(self):
+ return self.__nativeMessageTypeSet
+ nativeMessages = property(fget=__getNativeMessageTypeSet)
+
+ def __getMessageTypeSet(self):
+ return self.__messageTypeSet
+ messages = property(fget=__getMessageTypeSet)
+
+ def __getEnumTypeSet(self):
+ return self.__enumTypeSet
+ enums = property(fget=__getEnumTypeSet)
+
+ def __getPackage(self):
+ return self.__package
+ def __setPackage(self,package):
+ self.__package = package
+ package = property(fget=__getPackage,fset=__setPackage)
def add(self,any):
if any == None:
- print "<None> given to AST some rule aren't finished"
+ self.logger.error("<None> given to AST some rule aren't finished")
elif isinstance(any,type("")):
pass
else:
@@ -165,33 +221,61 @@
self.addNativeMessageType(any)
elif isinstance(any,MessageType):
self.addMessageType(any)
+ elif isinstance(any,Package):
+ self.package = any
else:
- print "<%s> not handle [yet]" % any
- print "%s added to AST" % any
+ self.logger.error("<%s> not handle [yet]" % any)
def addMessageType(self,message):
- self.messageTypeSet.add(message)
+ self.__messageTypeSet.add(message)
+ self.__types[message.name] = message
def addEnumType(self,enumType):
- self.enumTypeSet.add(enumType)
+ self.__enumTypeSet.add(enumType)
+ self.__types[enumType.name] = enumType
+ self.logger.debug("Adding enum type %s" % enumType.name)
def addNativeMessageType(self,message):
- self.messageTypeSet.add(message)
+ self.__nativeMessageTypeSet.add(message)
+ self.__types[message.name] = message
+
+ def isDefined(self,typename):
+ self.logger.debug("%s" % self.__types.keys())
+ if typename in self.__types.keys():
+ return True
+ else:
+ return False
+
+ def __repr__(self):
+ res = "AST with:\n <%d> native messages type,\n <%d> message type,\n
<%d> enum type\n" %
(len(self.nativeMessages),len(self.messages),len(self.enums))
+ res = res + " will be in package <%s>\n" % self.package
+ return res
+
+ def visit(self):
+ return None
+
+class Package(Named):
+ """Represents a package"""
+ def __init__(self,name):
+ super(Package,self).__init__(name=name)
-class NativeMessageType(object):
+ def __repr__(self):
+ return "package %s" % self.name
+
+class NativeMessageType(Named):
""" Represents a native message type
"""
def __init__(self,name):
- self.name = name
+ super(NativeMessageType,self).__init__(name=name)
def __repr__(self):
return "native_message %s" % self.name
-class MessageType(object):
+class MessageType(Named):
""" Represents a message type
"""
def __init__(self,name,field_list,merge):
- self.name = name
+ super(MessageType,self).__init__(name=name)
self.field_list = field_list
self.merge = merge
@@ -202,11 +286,11 @@
res = "message %s " % self.name
return res
-class EnumType(object):
+class EnumType(Named):
""" Represents an enum type
"""
def __init__(self,name,values):
- self.name = name
+ super(EnumType,self).__init__(name=name)
# rebuild dictionary with value from the list
self.values = []
lastval = -1
@@ -221,54 +305,67 @@
def __repr__(self):
res = "Enum %s {\n" % self.name
for val in self.values:
- res = res + " " + str(val[0]) + "=" + str(val[1]) + ", \n"
+ res = res + " " + str(val[0]) + " = " + str(val[1]) + ", \n"
res = res + "}"
return res
-
def addValue(self,value):
self.values.append(value)
+def p_statement_list(p):
+ '''statement_list : statement
+ | statement statement_list'''
+ p.parser.AST.add(p[1])
+
def p_statement(p):
'''statement : comment_line
- | comment_line statement
+ | package
| message
- | message statement
| native_message
- | native_message statement
- | enum
- | enum statement'''
-
- p.parser.AST.add(p[1])
+ | enum'''
+ p[0]=p[1]
def p_comment_line(p):
'''comment_line : COMMENT'''
p[0]=p[1].strip('/')
+def p_package(p):
+ '''package : PACKAGE package_id
+ | PACKAGE package_id optional_comment'''
+ p[0]=Package(p[2])
+
+def p_package_id(p):
+ '''package_id : ID
+ | ID PERIOD package_id'''
+ if len(p)==2:
+ p[0]=p[1]
+ else:
+ p[0]=p[1]+"."+p[3]
+
def p_message(p):
- '''message : MESSAGE ID LBRACE optional_comment field_list RBRACE
optional_comment
- | MESSAGE ID LBRACE optional_comment RBRACE optional_comment
- | MESSAGE ID COLON MERGE ID LBRACE optional_comment RBRACE
optional_comment
- | MESSAGE ID COLON MERGE ID LBRACE optional_comment field_list
RBRACE optional_comment'''
- if len(p)==7:
+ '''message : MESSAGE ID LBRACE RBRACE optional_comment
+ | MESSAGE ID LBRACE field_list RBRACE optional_comment
+ | MESSAGE ID COLON MERGE ID LBRACE RBRACE optional_comment
+ | MESSAGE ID COLON MERGE ID LBRACE field_list RBRACE
optional_comment'''
+ if len(p)==6:
p[0] = MessageType(p[2],[],None)
+ elif len(p)==7:
+ p[0] = MessageType(p[2],p[4],None)
elif len(p)==8:
- p[0] = MessageType(p[2],p[5],None)
+ p[0] = MessageType(p[2],[],p[4])
elif len(p)==9:
- p[0] = MessageType(p[2],[],p[5])
- elif len(p)==10:
- p[0] = MessageType(p[2],p[7],p[5])
+ p[0] = MessageType(p[2],p[7],p[4])
def p_native_message(p):
- 'native_message : NATIVE_MESSAGE ID optional_comment'
+ 'native_message : NATIVE_MESSAGE ID'
p[0]=NativeMessageType(p[2])
def p_enum(p):
- 'enum : ENUM ID LBRACE optional_comment enum_value_list RBRACE
optional_comment'
+ 'enum : ENUM ID LBRACE enum_value_list RBRACE optional_comment'
# we should reverse the enum value list
# because the parse build it the other way around (recursive way)
- p[5].reverse()
- p[0] = EnumType(p[2],p[5])
+ p[4].reverse()
+ p[0] = EnumType(p[2],p[4])
def p_empty(p):
'empty :'
@@ -310,7 +407,8 @@
if len(p)==3:
p[0] = [p[1]]
else:
- p[0] = p[3].append(p[1])
+ p[0] = p[3]
+ p[0].append(p[1])
def p_field_spec(p):
'''field_spec : qualifier typeid ID optional_comment
@@ -340,17 +438,36 @@
| UINT64_T
| FLOAT_T
| DOUBLE_T
- | ID'''
+ | defined_type'''
p[0] = p[1]
+def p_defined_type(p):
+ '''defined_type : ID'''
+ # This kind of type should be checked
+ # When the AST has been built.
+ # We cannot check it now because of the recursive
+ # nature of the parser.
+ p[0]=p[1]
+
def p_value(p):
'''value : INTEGER_VALUE
| FLOAT_VALUE
| BOOL_VALUE'''
p[0]=p[1].value
+# Compute column.
+# input is the input text string
+# token is a token instance
+def find_column(input,token):
+ last_cr = input.rfind('\n',0,token.lexpos)
+ if last_cr < 0:
+ last_cr = 0
+ column = (token.lexpos - last_cr) + 1
+ return column
+
def p_error(p):
- print "Syntax error at '%s' on line %d (token type is '%s')" %
(p.value,p.lineno,p.type)
+ print "Syntax error at '%s' on line %d column %d (token type is '%s')" %
(p.value,p.lineno,find_column(p.lexer.lexdata, p),p.type)
+
# Build the PLY parser
parser = ply.yacc.yacc()
@@ -372,10 +489,10 @@
print "Trying to parse..."
msgFile = open(messagefile,'r')
lexer.lineno = 1
-parser.AST = MessageAST(messagefile)
-ast = parser.parse(msgFile.read(),lexer=lexer)
+parser.AST = MessageNotAnAST(messagefile)
+parser.parse(msgFile.read(),lexer=lexer)
msgFile.close()
-print "Parse succeeded AST = %s" % ast
+print "Parse succeeded AST = %s (type=%s)" % (parser.AST,type(parser.AST))
sys.exit()
for l in msgFile:
Index: TestMessageSpec.msg
===================================================================
RCS file: /sources/certi/certi/scripts/TestMessageSpec.msg,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- TestMessageSpec.msg 13 Jul 2009 21:39:28 -0000 1.2
+++ TestMessageSpec.msg 14 Jul 2009 12:40:49 -0000 1.3
@@ -1,10 +1,14 @@
-
// CERTI message description spec test file
+package my.hierarchy.pack // don't you know it
+//
+// This is a multiline
+// comment
+//
enum MessageType {
- FIRST_VAL = 0,
- REAL_VAL1,
- REAL_VAL2,
+ FIRST_VAL = 0, // one may specify the value of the first enum symbol
+ REAL_VAL1 ,
+ REAL_VAL2 ,
UNUSED
}
@@ -15,10 +19,12 @@
native_message ANotherativeMessageType
-message MyMessage { // another comment
+message MyMessage {
repeated int32 whatever
}
message MyOtherMessage : merge MyMessage {
required bool constrained
+ required MessageType type
+ required uint32 a
}
\ No newline at end of file
Index: CertiNetworkMessage.msg
===================================================================
RCS file: CertiNetworkMessage.msg
diff -N CertiNetworkMessage.msg
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ CertiNetworkMessage.msg 14 Jul 2009 12:40:49 -0000 1.1
@@ -0,0 +1,108 @@
+// CERTI messages description
+
+// The messages related classes will be placed in the certi package
+package certi
+
+// Network message is the base class
+// for message exchanged between RTIA and RTIG
+// AKA CERTI Network Message
+native_message NetworkMessage
+
+native_message BasicMessage
+
+native_message Message
+
+enum Message_T {
+ NOT_USED = 0, // Not used.
+ CLOSE_CONNEXION,
+ MESSAGE_NULL,
+ CREATE_FEDERATION_EXECUTION,
+ DESTROY_FEDERATION_EXECUTION,
+ JOIN_FEDERATION_EXECUTION,
+ RESIGN_FEDERATION_EXECUTION,
+ SET_TIME_REGULATING,
+ SET_TIME_CONSTRAINED,
+ TIME_REGULATION_ENABLED, // RTIG to RTIA
+ TIME_CONSTRAINED_ENABLED, // RTIG to RTIA
+ REGISTER_FEDERATION_SYNCHRONIZATION_POINT,
+ SYNCHRONIZATION_POINT_REGISTRATION_SUCCEEDED, // RTIG to RTIA
+ ANNOUNCE_SYNCHRONIZATION_POINT, // RTIG to RTIA
+ SYNCHRONIZATION_POINT_ACHIEVED,
+ FEDERATION_SYNCHRONIZED, // RTIG to RTIA
+ REQUEST_FEDERATION_SAVE,
+ FEDERATE_SAVE_BEGUN,
+ FEDERATE_SAVE_COMPLETE,
+ FEDERATE_SAVE_NOT_COMPLETE,
+ INITIATE_FEDERATE_SAVE, // RTIG to RTIA
+ FEDERATION_SAVED, // RTIG to RTIA
+ FEDERATION_NOT_SAVED, // RTIG to RTIA
+ REQUEST_FEDERATION_RESTORE,
+ FEDERATE_RESTORE_COMPLETE,
+ FEDERATE_RESTORE_NOT_COMPLETE,
+ REQUEST_FEDERATION_RESTORE_SUCCEEDED, // RTIG to RTIA
+ REQUEST_FEDERATION_RESTORE_FAILED, // RTIG to RTIA
+ FEDERATION_RESTORE_BEGUN, // RTIG to RTIA
+ INITIATE_FEDERATE_RESTORE, // RTIG to RTIA
+ FEDERATION_RESTORED, // RTIG to RTIA
+ FEDERATION_NOT_RESTORED, // RTIG to RTIA
+ PUBLISH_OBJECT_CLASS,
+ UNPUBLISH_OBJECT_CLASS,
+ PUBLISH_INTERACTION_CLASS,
+ UNPUBLISH_INTERACTION_CLASS,
+ SUBSCRIBE_OBJECT_CLASS,
+ UNSUBSCRIBE_OBJECT_CLASS,
+ SUBSCRIBE_INTERACTION_CLASS,
+ UNSUBSCRIBE_INTERACTION_CLASS,
+ TURN_INTERACTIONS_ON, // only RTIG->RTIA
+ TURN_INTERACTIONS_OFF, // only RTIG->RTIA
+ REGISTER_OBJECT,
+ DISCOVER_OBJECT, // only RTIG->RTIA
+ UPDATE_ATTRIBUTE_VALUES,
+ REFLECT_ATTRIBUTE_VALUES, // only RTIG->RTIA
+ SEND_INTERACTION,
+ RECEIVE_INTERACTION, // only RTIG->RTIA
+ DELETE_OBJECT,
+ REMOVE_OBJECT, // only RTIG->RTIA
+ CHANGE_ATTRIBUTE_TRANSPORT_TYPE,
+ CHANGE_ATTRIBUTE_ORDER_TYPE,
+ CHANGE_INTERACTION_TRANSPORT_TYPE,
+ CHANGE_INTERACTION_ORDER_TYPE,
+ REQUEST_CLASS_ATTRIBUTE_VALUE_UPDATE,
+ REQUEST_OBJECT_ATTRIBUTE_VALUE_UPDATE,
+ IS_ATTRIBUTE_OWNED_BY_FEDERATE,
+ QUERY_ATTRIBUTE_OWNERSHIP,
+ ATTRIBUTE_IS_NOT_OWNED,
+ INFORM_ATTRIBUTE_OWNERSHIP,
+ NEGOTIATED_ATTRIBUTE_OWNERSHIP_DIVESTITURE,
+ ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION,
+ ATTRIBUTE_OWNERSHIP_DIVESTITURE_NOTIFICATION,
+ REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION,
+ ATTRIBUTE_OWNERSHIP_UNAVAILABLE,
+ ATTRIBUTE_OWNERSHIP_ACQUISITION_IF_AVAILABLE,
+ UNCONDITIONAL_ATTRIBUTE_OWNERSHIP_DIVESTITURE,
+ ATTRIBUTE_OWNERSHIP_ACQUISITION,
+ REQUEST_ATTRIBUTE_OWNERSHIP_RELEASE,
+ CANCEL_NEGOTIATED_ATTRIBUTE_OWNERSHIP_DIVESTITURE,
+ ATTRIBUTE_OWNERSHIP_RELEASE_RESPONSE,
+ CANCEL_ATTRIBUTE_OWNERSHIP_ACQUISITION,
+ CONFIRM_ATTRIBUTE_OWNERSHIP_ACQUISITION_CANCELLATION,
+ DDM_CREATE_REGION,
+ DDM_MODIFY_REGION,
+ DDM_DELETE_REGION,
+ DDM_ASSOCIATE_REGION,
+ DDM_REGISTER_OBJECT,
+ DDM_UNASSOCIATE_REGION,
+ DDM_SUBSCRIBE_ATTRIBUTES,
+ DDM_UNSUBSCRIBE_ATTRIBUTES,
+ DDM_SUBSCRIBE_INTERACTION,
+ DDM_UNSUBSCRIBE_INTERACTION,
+ PROVIDE_ATTRIBUTE_VALUE_UPDATE,
+ GET_FED_FILE,
+ SET_CLASS_RELEVANCE_ADVISORY_SWITCH,
+ SET_INTERACTION_RELEVANCE_ADVISORY_SWITCH,
+ SET_ATTRIBUTE_RELEVANCE_ADVISORY_SWITCH,
+ SET_ATTRIBUTE_SCOPE_ADVISORY_SWITCH,
+ START_REGISTRATION_FOR_OBJECT_CLASS,
+ STOP_REGISTRATION_FOR_OBJECT_CLASS,
+ LAST
+}
\ No newline at end of file