[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: |
Mon, 13 Jul 2009 19:25:43 +0000 |
CVSROOT: /sources/certi
Module name: certi
Changes by: Eric NOULARD <erk> 09/07/13 19:25:43
Added files:
scripts : GenerateMessages.py TestMessageSpec.msg
Log message:
Preliminary CERTI message parser and generator
lexer+parser are OK.
The real work, i.e. building the AST, may begin now.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/certi/scripts/GenerateMessages.py?cvsroot=certi&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/certi/scripts/TestMessageSpec.msg?cvsroot=certi&rev=1.1
Patches:
Index: GenerateMessages.py
===================================================================
RCS file: GenerateMessages.py
diff -N GenerateMessages.py
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ GenerateMessages.py 13 Jul 2009 19:25:43 -0000 1.1
@@ -0,0 +1,343 @@
+#!/usr/bin/env python
+
+import os
+import getopt, sys
+import shutil
+# We use PLY in order to parse CERTI message specification files
+import ply.yacc
+import ply.lex
+
+def usage():
+ print "Usage:\n %s --file=<message> [--language=C++|Java|Python]
[--type=header|body|factory] [--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"])
+except getopt.GetoptError, err:
+ print >> stderr, "opt = %s, msg = %s" % (err.opt,err.msg)
+ usage()
+ sys.exit(2)
+
+if len(opts) < 1:
+ usage()
+ sys.exit(2)
+
+# default value
+verbose=False
+gentype="header"
+language="C++"
+
+# Parse command line options
+for o, a in opts:
+ if o in ("-f", "--file"):
+ messagefile=a
+ if o in ("-l", "--language"):
+ language=a
+ if o in ("-t", "--type"):
+ gentype=a
+ if o in ("-v", "--verbose"):
+ verbose=True
+ if o in ("-h", "--help"):
+ usage()
+ sys.exit(0)
+
+# Lexer+Parser specification begins here
+# reserved keywords
+reserved = {
+ 'native_message' : 'NATIVE_MESSAGE',
+ 'message' : 'MESSAGE',
+ 'merge' : 'MERGE',
+ 'enum' : 'ENUM',
+ 'default' : 'DEFAULT',
+ 'required' : 'REQUIRED',
+ 'optional': 'OPTIONAL',
+ 'repeated': 'REPEATED',
+ 'bool' : 'BOOL_T',
+ 'string' : 'STRING_T',
+ 'byte' : 'BYTE_T',
+ 'int8' : 'INT8_T',
+ 'uint8' : 'UINT8_T',
+ 'int16' : 'INT16_T',
+ 'uint16' : 'UINT16_T',
+ 'int32' : 'INT32_T',
+ 'uint32' : 'UINT32_T',
+ 'int64' : 'INT64_T',
+ 'uint64' : 'UINT64_T',
+ 'float' : 'FLOAT_T',
+ 'double' : 'DOUBLE_T',
+}
+
+# List of token names. This is always required
+tokens = ['ID',
+ 'COMMENT',
+ 'INTEGER_VALUE',
+ 'FLOAT_VALUE',
+ 'BOOL_VALUE',
+ 'RBRACE','LBRACE',
+ 'RBRACKET','LBRACKET',
+ 'COMMA',
+ 'EQUAL',
+ 'COLON',
+ ] + list(reserved.values())
+
+# This is a message of field 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
+ return t
+
+# Comment begins with // and ends up at the end of the line
+def t_COMMENT(t):
+ r'//.*'
+ return t
+ #pass
+ # if pass No return value. Comments are discarded
+
+def t_INTEGER_VALUE(t):
+ r'\d+'
+ try:
+ t.value = int(t.value)
+ except ValueError:
+ print "Integer value too large", t.value
+ t.value = 0
+ return t
+
+def t_FLOAT_VALUE(t):
+ r'\d+\.\d+'
+ try:
+ t.value = float(t.value)
+ except ValueError:
+ print "Float value too large", t.value
+ t.value = 0.0
+ return t
+
+def t_BOOL_VALUE(t):
+ r'true|false|True|False'
+ if (t.value.lower()=="true"):
+ t.value = True
+ elif (t.value.lower()=="false"):
+ t.value = False
+ else:
+ print "Invalid Boolean value too large", t.value
+ t.value = False
+ return t
+
+t_LBRACE = r'{'
+t_RBRACE = r'}'
+t_LBRACKET = r'\['
+t_RBRACKET = r'\]'
+t_COMMA = r','
+t_EQUAL = r'='
+t_COLON = r':'
+
+# Define a rule so we can track line numbers
+def t_newline(t):
+ r'\n'
+ t.lexer.lineno += 1
+
+# A string containing ignored characters (spaces and tabs)
+t_ignore = ' \t'
+
+# Error handling rule
+def t_error(t):
+ print "Illegal character '%s'" % t.value[0]
+ t.lexer.skip(1)
+
+# Build the PLY lexer
+lexer = ply.lex.lex()
+
+# Message set
+class MessageAST(object):
+ def __init__(self,name):
+ self.messageTypeSet = set()
+ self.enumSet = set()
+
+ def addMessageType(self,message):
+ self.messageTypeSet.add(message)
+
+ def addEnumType(self,enumType):
+ self.enumSet.add(enumType)
+
+class MessageType(object):
+ """ Represents a message type
+ """
+ def __init__(self,name):
+ self.name = name
+
+ def addField(self,name,type,defaultValue=None):
+ self.field[name] = [type,defaultValue]
+
+
+class EnumType(object):
+ """ Represents an enum type
+ """
+ def __init__(self,name):
+ self.name = name
+ self.values = list()
+
+ def addValue(self,value):
+ self.values.append(value)
+
+def p_statement(p):
+ '''statement : comment_line
+ | comment_line statement
+ | message
+ | message statement
+ | native_message
+ | native_message statement
+ | enum
+ | enum statement'''
+ print "statement"
+
+def p_comment_line(p):
+ '''comment_line : COMMENT'''
+ print "comment line =",p[1]
+
+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'''
+ print "message =",p[1],p[2],p[3],p[4]
+
+def p_native_message(p):
+ 'native_message : NATIVE_MESSAGE ID optional_comment'
+ print "native_message = ", p[1],p[2],p[3]
+
+def p_enum(p):
+ 'enum : ENUM ID LBRACE optional_comment enum_list RBRACE optional_comment'
+ print p[0]
+
+def p_empty(p):
+ 'empty :'
+ pass
+
+def p_optional_comment(p):
+ '''optional_comment : COMMENT
+ | empty'''
+ print "Comment = %s" % p[1]
+
+def p_enum_list(p):
+ '''enum_list : enum_val optional_comment
+ | enum_val COMMA optional_comment
+ | enum_val COMMA optional_comment enum_list'''
+ print p
+
+def p_enum_val(p):
+ '''enum_val : ID
+ | ID EQUAL INTEGER_VALUE'''
+ print p
+
+def p_field_list(p):
+ '''field_list : field_spec optional_comment
+ | field_spec optional_comment field_list'''
+ print p
+
+def p_field_spec(p):
+ '''field_spec : qualifier typeid ID optional_comment
+ | qualifier typeid ID LBRACKET DEFAULT EQUAL value RBRACKET
optional_comment'''
+ print p
+
+def p_qualifier(p):
+ '''qualifier : REQUIRED
+ | REPEATED
+ | OPTIONAL'''
+ print p
+
+def p_typeid(p):
+ '''typeid : BOOL_T
+ | STRING_T
+ | BYTE_T
+ | INT8_T
+ | UINT8_T
+ | INT16_T
+ | UINT16_T
+ | INT32_T
+ | UINT32_T
+ | INT64_T
+ | UINT64_T
+ | FLOAT_T
+ | DOUBLE_T
+ | ID'''
+ print p
+
+def p_value(p):
+ '''value : INTEGER_VALUE
+ | FLOAT_VALUE
+ | BOOL_VALUE'''
+ print p
+
+def p_error(p):
+ print "Syntax error at '%s' on line %d (token type is '%s')" %
(p.value,p.lineno,p.type)
+
+
+# Build the PLY parser
+parser = ply.yacc.yacc()
+
+if False:
+ print "Trying to lex..."
+ msgFile = open(messagefile,'r')
+ lexer.lineno = 1
+ lexer.input(msgFile.read())
+ msgFile.close()
+ # Tokenize
+ while True:
+ tok = lexer.token()
+ if not tok: break # No more input
+ #print tok
+ print "Lex succeeded"
+
+
+print "Trying to parse..."
+msgFile = open(messagefile,'r')
+lexer.lineno = 1
+parser.parse(msgFile.read(),lexer=lexer)
+msgFile.close()
+print "Parse succeeded"
+
+sys.exit()
+for l in msgFile:
+ cname = l.strip('_ \n')
+ if (gentype.lower()=="header"):
+ print "/*<BEGIN>---------- %s ------------<BEGIN>*/" % cname.title()
+ print "class CERTI_EXPORT NM_%s : public NetworkMessage {" %
cname.title()
+ print " public:"
+ print " NM_%s();" % cname.title()
+ print " virtual ~NM_%s();" % cname.title()
+ print " virtual void serialize();"
+ print " virtual void deserialize();"
+ print " /* specific Getter/Setter */"
+ print " protected:"
+ print " /* specific field */"
+ print " private:"
+ print "};\n"
+ print "/*<END>---------- %s ------------<END>*/\n" % cname.title()
+
+
+ if (gentype.lower()=="body"):
+ print "/*<BEGIN>---------- %s ------------<BEGIN>*/" % cname.title()
+ print "NM_%s::NM_%s() {" % (cname.title(),cname.title())
+ print " this->name = \"%s\";" % cname
+ print " this->type = NetworkMessage::%s;" % cname
+ print " /* specific field init */"
+ print "}"
+ print "NM_%s::~NM_%s() {" % (cname.title(), cname.title())
+ print "}"
+ print "void NM_%s::serialize() {" % cname.title()
+ print " /* call mother class */ "
+ print " NetworkMessage::serialize(); "
+ print " /* specific code (if any) goes here */"
+ print "} /* end of serialize */ "
+ print "void NM_%s::deserialize() {" % cname.title()
+ print " /* call mother class */ "
+ print " NetworkMessage::deserialize(); "
+ print " /* specific code (if any) goes here */"
+ print "} /* end of deserialize */"
+ print "/*<END>---------- %s ------------<END>*/\n" % cname.title()
+
+
+ if (gentype.lower()=="factory"):
+ print "case NetworkMessage::%s:" % cname
+ print " msg = new NM_%s(); " %cname.title()
+ print " break;"
+
+msgFile.close()
Index: TestMessageSpec.msg
===================================================================
RCS file: TestMessageSpec.msg
diff -N TestMessageSpec.msg
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ TestMessageSpec.msg 13 Jul 2009 19:25:43 -0000 1.1
@@ -0,0 +1,16 @@
+
+// CERTI message description spec test file
+
+message MyMessage {}
+
+// blah
+native_message ANativeMessageType
+
+native_message ANotherativeMessageType
+
+message MyMessage { // another comment
+}
+
+message MyOtherMessage : merge MyMessage {
+ required bool constrained [default=false]
+}
\ No newline at end of file
- [certi-cvs] certi/scripts GenerateMessages.py TestMessageSp...,
certi-cvs <=
- [certi-cvs] certi/scripts GenerateMessages.py TestMessageSp..., certi-cvs, 2009/07/13
- [certi-cvs] certi/scripts GenerateMessages.py TestMessageSp..., certi-cvs, 2009/07/14
- [certi-cvs] certi/scripts GenerateMessages.py TestMessageSp..., certi-cvs, 2009/07/14
- [certi-cvs] certi/scripts GenerateMessages.py TestMessageSp..., certi-cvs, 2009/07/14
- [certi-cvs] certi/scripts GenerateMessages.py TestMessageSp..., certi-cvs, 2009/07/15