certi-cvs
[Top][All Lists]
Advanced

[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 17:18:24 +0000

CVSROOT:        /sources/certi
Module name:    certi
Changes by:     Eric NOULARD <erk>      09/07/14 17:18:24

Modified files:
        scripts        : GenerateMessages.py TestMessageSpec.msg 

Log message:
        Looks like we now have a clean AST
        Now let's go on with some generator

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/certi/scripts/GenerateMessages.py?cvsroot=certi&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/certi/scripts/TestMessageSpec.msg?cvsroot=certi&r1=1.3&r2=1.4

Patches:
Index: GenerateMessages.py
===================================================================
RCS file: /sources/certi/certi/scripts/GenerateMessages.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- GenerateMessages.py 14 Jul 2009 12:40:49 -0000      1.3
+++ GenerateMessages.py 14 Jul 2009 17:18:23 -0000      1.4
@@ -10,20 +10,23 @@
 # We use logging for ... logging :-)
 import logging 
 
-
+# Build some logger related objects
 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)
+# See formatting there:
+# http://docs.python.org/library/datetime.html#strftime-behavior
+# http://docs.python.org/library/logging.html#formatter-objects
+stdoutHandler.setFormatter(logging.Formatter("%(asctime)s.%(msecs)d-[%(name)s::%(levelname)s]
 %(message)s","%a %H:%M:%S"))
+mainlogger = logging.Logger("Main")
+mainlogger.setLevel(logging.INFO)
+mainlogger.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])
+    print "Usage:\n %s --file=<message> [--language=C++|Java|Python] 
[--type=header|body|factory] [--output=<filename>] [--verbose] [--help]" % 
os.path.basename(sys.argv[0])
     
 try:
-    opts, args = getopt.getopt(sys.argv[1:], "f:l:t:vh", 
["file=","language=","type=","verbose","help"])
+    opts, args = getopt.getopt(sys.argv[1:], "f:l:t:vho:", 
["file=","language=","type=","output","verbose","help"])
 except getopt.GetoptError, err:
-    mylogger.error("opt = %s, msg = %s" % (err.opt,err.msg))    
+    mainlogger.error("opt = %s, msg = %s" % (err.opt,err.msg))    
     usage()
     sys.exit(2)
 
@@ -35,6 +38,7 @@
 verbose=False
 gentype="header"
 language="C++"
+output=sys.stdout
 
 # Parse command line options
 for o, a in opts:
@@ -44,6 +48,9 @@
         language=a
     if o in ("-t", "--type"):
         gentype=a
+    if o in ("-o", "--output"):
+        mainlogger.info("output send to file: <%s>" % a)
+        output=open(a)
     if o in ("-v", "--verbose"):
         verbose=True
     if o in ("-h", "--help"):
@@ -129,7 +136,7 @@
     elif (t.value.lower()=="false"):
         t.value = False
     else:                
-        print "Invalid Boolean value too large", t.value 
+        t.lexer.logger.error("Invalid Boolean value too large", t.value) 
         t.value = False 
     return t
     
@@ -156,65 +163,79 @@
     t.lexer.skip(1)
 
 # Build the PLY lexer
-lexer = ply.lex.lex()
+lexerlogger = logging.Logger("Lexer")
+lexerlogger.setLevel(logging.ERROR)
+lexerlogger.addHandler(stdoutHandler)
+lexer = ply.lex.lex(debug=False)
+lexer.logger = lexerlogger
 
 # Named Class
-class Named(object):
+class ASTElement(object):
     def __init__(self,name):
         self.__name    = name
         self.__comment = None
+        self.logger = logging.Logger("ASTElement")
+        self.logger.setLevel(logging.DEBUG)
+        self.logger.addHandler(stdoutHandler)
     
-    def __getName(self):
+    def getName(self):
         return self.__name    
-    def __setName(self,name):
+    def setName(self,name):        
         self.__name = name
     # pythonic getter/setter using properties    
-    name = property(fget=__getName,fset=__setName)
+    name = property(fget=getName,fset=setName,fdel=None, doc=None)    
     
-    def __getComment(self):
+    def getComment(self):
         return self.__comment    
-    def __setComment(self,comment):
+    def setComment(self,comment):
+        if isinstance(comment,type("")):
+            pass
+        else:
+            self.logger.info("Adding comment %s to element %s" % 
(comment.lines,self.name))
         self.__comment = comment
     # pythonic getter/setter using properties    
-    name = property(fget=__getComment,fset=__setComment)
+    comment = property(fget=getComment,fset=setComment,fdel=None, doc=None)
 
 # Message set
-class MessageNotAnAST(Named):
+class MessageAST(ASTElement):
     def __init__(self,name):
-        super(MessageNotAnAST,self).__init__(name=name)        
+        super(MessageAST,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.__ultimateElement      = None
+        self.__penultimateElement   = None
+        self.__currentComment       = None
+        self.logger = logging.Logger("MessageAST")
+        self.logger.setLevel(logging.DEBUG)
         self.logger.addHandler(stdoutHandler)
         
     def __getNativeMessageTypeSet(self):
         return self.__nativeMessageTypeSet        
-    nativeMessages = property(fget=__getNativeMessageTypeSet)
+    nativeMessages = 
property(fget=__getNativeMessageTypeSet,fset=None,fdel=None,doc=None)
     
     def __getMessageTypeSet(self):
         return self.__messageTypeSet        
-    messages = property(fget=__getMessageTypeSet)
+    messages = property(fget=__getMessageTypeSet,fset=None,fdel=None,doc=None)
     
     def __getEnumTypeSet(self):
         return self.__enumTypeSet    
-    enums = property(fget=__getEnumTypeSet)         
+    enums = property(fget=__getEnumTypeSet,fset=None,fdel=None,doc=None)       
  
     
     def __getPackage(self):
         return self.__package
     def __setPackage(self,package):
         self.__package = package
-    package = property(fget=__getPackage,fset=__setPackage)
+    package = property(fget=__getPackage,fset=__setPackage,fdel=None,doc=None) 
         
     def add(self,any):
+        """ Add an ASTElement to the AST """
         if any == None:
             self.logger.error("<None> given to AST some rule aren't finished")
-        elif isinstance(any,type("")):
-            pass
         else:         
+            self.logger.debug("Add %s %s" % (type(any).__name__,any.name))     
       
             if isinstance(any,EnumType):            
                 self.addEnumType(any)                            
             elif isinstance(any,NativeMessageType):
@@ -223,8 +244,22 @@
                 self.addMessageType(any)
             elif isinstance(any,Package):
                 self.package = any
+            # Handle multiline comment
+            elif isinstance(any,CommentBlock):                
+                if isinstance(self.__ultimateElement,CommentBlock):
+                    # the Comment block continues
+                    self.__ultimateElement.lines.append(any.lines)
+                elif self.__ultimateElement != None:
+                    # attach the comment block to the preceding
+                    # AST element (recursion is backtracking)
+                    self.__ultimateElement.comment = any
+                else:
+                    pass               
             else:            
                 self.logger.error("<%s> not handle [yet]" % any)            
+            # update ultimate and penultimate AST element                      
+            self.__penultimateElement = self.__ultimateElement                 
     
+            self.__ultimateElement    = any            
             
     def addMessageType(self,message):
         self.__messageTypeSet.add(message)
@@ -233,7 +268,6 @@
     def addEnumType(self,enumType):
         self.__enumTypeSet.add(enumType)
         self.__types[enumType.name] = enumType       
-        self.logger.debug("Adding enum type %s" % enumType.name) 
     
     def addNativeMessageType(self,message):
         self.__nativeMessageTypeSet.add(message)
@@ -251,18 +285,21 @@
         res = res + " will be in package <%s>\n" % self.package
         return res
     
-    def visit(self):        
-        return None
+class CommentBlock(ASTElement):
+    def __init__(self,content,optComment):
+        super(CommentBlock,self).__init__(name="comment")
+        self.lines=[content]
+        self.__optComment=optComment
     
-class Package(Named):
+class Package(ASTElement):
     """Represents a package"""
     def __init__(self,name):
-        super(Package,self).__init__(name=name)
+        super(Package,self).__init__(name)                        
           
     def __repr__(self):
         return "package %s" % self.name
      
-class NativeMessageType(Named):
+class NativeMessageType(ASTElement):
     """ Represents a native message type
     """
     def __init__(self,name):
@@ -271,7 +308,7 @@
     def __repr__(self):
         return "native_message %s" % self.name 
                     
-class MessageType(Named):
+class MessageType(ASTElement):
     """ Represents a message type
     """
     def __init__(self,name,field_list,merge):
@@ -279,14 +316,20 @@
         self.field_list = field_list
         self.merge      = merge
         
-    def addField(self,name,type,defaultValue=None):
-        self.field[name] = [type,defaultValue]
-    
     def __repr__(self):
         res = "message %s " % self.name
         return res
                 
-class EnumType(Named):
+    class MessageField(ASTElement):
+        """ Represents a message type
+        """
+        def __init__(self,qualifier,typeid,name,defaultValue=None):
+            super(MessageType.MessageField,self).__init__(name=name)
+            self.qualifier    = qualifier
+            self.typeid       = typeid
+            self.defaultValue = defaultValue
+                
+class EnumType(ASTElement):
     """ Represents an enum type 
     """
     def __init__(self,name,values):
@@ -295,12 +338,13 @@
         self.values = []
         lastval     = -1        
         for val in values:                                    
-            if (val[1]==None):
-                self.values.append((val[0],lastval+1))
+            if (val.value==None):
+                val.value = lastval+1
+                self.values.append(val)
                 lastval += 1
             else:
                 self.values.append(val)                           
-                lastval = val[1]
+                lastval = val.value
         
     def __repr__(self):
         res = "Enum %s {\n" % self.name
@@ -309,8 +353,12 @@
         res = res + "}"
         return res                 
         
-    def addValue(self,value):
-        self.values.append(value)        
+    class EnumValue(ASTElement):
+        """ Represents an Enum Value
+        """
+        def __init__(self,name,value):
+            super(EnumType.EnumValue,self).__init__(name=name)    
+            self.value = value
         
 def p_statement_list(p):
     '''statement_list : statement 
@@ -327,11 +375,10 @@
         
 def p_comment_line(p):
     '''comment_line : COMMENT'''
-    p[0]=p[1].strip('/')
+    p[0]=CommentBlock(p[1].strip('/'),optComment=False)
     
 def p_package(p):
-    '''package : PACKAGE package_id 
-               | PACKAGE package_id optional_comment'''    
+    '''package : PACKAGE package_id'''    
     p[0]=Package(p[2])
     
 def p_package_id(p):
@@ -376,7 +423,7 @@
                         | empty'''
     # we may store the comment text for future use
     if len(p) > 1 and isinstance(p[1],type("")) :
-        p[0] = p[1].strip('/')
+        p[0] = CommentBlock(p[1].strip('/'),optComment=True)        
     else:
         p[0] = ""         
     
@@ -385,11 +432,16 @@
                        | enum_val COMMA optional_comment
                        | enum_val COMMA optional_comment enum_value_list'''
     # Create or append the list (of pair)            
-    if len(p) > 4:        
+    if len(p)==3:
+        p[1].comment = p[2]
+        p[0]=[p[1]]
+    elif len(p)==4:
+        p[1].comment = p[3]
+        p[0]=[p[1]]              
+    else:
+        p[1].comment = p[3]
         p[4].append(p[1])
         p[0]=p[4]
-    else:
-        p[0]=[p[1]]    
     
 def p_enum_val(p):
     '''enum_val : ID 
@@ -397,9 +449,9 @@
     # Build a pair (ID,value)
     # value may be None    
     if len(p)>3:
-        p[0] = (p[1],p[3])
+        p[0] = EnumType.EnumValue(p[1],p[3])
     else:
-        p[0] = (p[1],None)     
+        p[0] = EnumType.EnumValue(p[1],None)     
 
 def p_field_list(p):
     '''field_list : field_spec optional_comment
@@ -414,9 +466,11 @@
     '''field_spec : qualifier typeid ID optional_comment
                   | qualifier typeid ID LBRACKET DEFAULT EQUAL value RBRACKET 
optional_comment'''
     if len(p)==5:
-        p[0] = (p[1],p[2],p[3],None)
+        p[0] = MessageType.MessageField(p[1],p[2],p[3],None)
+        p[0].comment = p[4]
     else:        
-        p[0] = (p[1],p[2],p[3],p[7])   
+        p[0] = MessageType.MessageField(p[1],p[2],p[3],p[7])
+        p[0].comment = p[8]   
 
 def p_qualifier(p):
     '''qualifier : REQUIRED
@@ -453,7 +507,7 @@
     '''value : INTEGER_VALUE 
              | FLOAT_VALUE 
              | BOOL_VALUE'''
-    p[0]=p[1].value
+    p[0]=p[1]
     
 # Compute column. 
 #     input is the input text string
@@ -469,8 +523,6 @@
     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() 
 
 if False:
     print "Trying to lex..."
@@ -485,14 +537,20 @@
         #print tok
         print "Lex succeeded"
         
+# Build the PLY parser
+parserlogger = logging.Logger("MessageParser")
+parserlogger.setLevel(logging.ERROR)
+parserlogger.addHandler(stdoutHandler)
+parser = ply.yacc.yacc(debug=True)
+parser.logger = parserlogger 
     
-print "Trying to parse..."    
+mainlogger.info("Trying to parse...")    
 msgFile =  open(messagefile,'r')
 lexer.lineno = 1
-parser.AST = MessageNotAnAST(messagefile)
+parser.AST = MessageAST(messagefile)
 parser.parse(msgFile.read(),lexer=lexer)
 msgFile.close()
-print "Parse succeeded AST = %s (type=%s)" % (parser.AST,type(parser.AST)) 
+mainlogger.info("Parse succeeded AST = %s" % (parser.AST)) 
 
 sys.exit()
 for l in msgFile:

Index: TestMessageSpec.msg
===================================================================
RCS file: /sources/certi/certi/scripts/TestMessageSpec.msg,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- TestMessageSpec.msg 14 Jul 2009 12:40:49 -0000      1.3
+++ TestMessageSpec.msg 14 Jul 2009 17:18:24 -0000      1.4
@@ -1,11 +1,12 @@
 // CERTI message description spec test file
-package my.hierarchy.pack // don't you know it
+// another line
+package my.hierarchy.pack
 
 //
 //  This is a multiline
 //  comment
 //
-enum MessageType {
+enum EType {
    FIRST_VAL = 0, // one may specify the value of the first enum symbol
    REAL_VAL1    ,
    REAL_VAL2    ,
@@ -26,5 +27,5 @@
 message MyOtherMessage : merge MyMessage {
     required bool              constrained     
        required MessageType       type
-       required uint32            a
+       required uint32            a [ default=1 ]
 }
\ No newline at end of file




reply via email to

[Prev in Thread] Current Thread [Next in Thread]