Updates to model and parser
diff --git a/plyproto/model.py b/plyproto/model.py
index bfa5e95..4b184fe 100644
--- a/plyproto/model.py
+++ b/plyproto/model.py
@@ -282,20 +282,20 @@
             visitor.visit_LinkSpec_post(self)
 
 class MessageDefinition(SourceElement):
-    def __init__(self, name, bclass, body, linespan=None, lexspan=None, p=None):
+    def __init__(self, name, bases, body, linespan=None, lexspan=None, p=None):
         super(MessageDefinition, self).__init__(linespan=linespan, lexspan=lexspan, p=p)
-        self._fields += ['name', 'bclass', 'body']
+        self._fields += ['name', 'bases', 'body']
         self.name = name
         Base.p(self.name, self)
-        self.bclass = bclass
-        Base.p(self.bclass, self)
+        self.bases = bases
+        Base.p(self.bases, self)
         self.body = body
         Base.p(self.body, self)
 
     def accept(self, visitor):
         if visitor.visit_MessageDefinition(self):
             self.v(self.name, visitor)
-            self.v(self.bclass, visitor)
+            self.v(self.bases, visitor)
             self.v(self.body, visitor)
             visitor.visit_MessageDefinition_post(self)
 
diff --git a/plyproto/parser.py b/plyproto/parser.py
index eb2d776..585d0b9 100755
--- a/plyproto/parser.py
+++ b/plyproto/parser.py
@@ -18,6 +18,7 @@
 
     tokens = [
         'NAME',
+        'PLUS',
         'NUM',
         'STRING_LITERAL',
         'LINE_COMMENT', 'BLOCK_COMMENT',
@@ -30,7 +31,7 @@
     ] + [k.upper() for k in keywords]
     literals = '()+-*/=?:,.^|&~!=[]{};<>@%'
 
-    t_NUM = r'[+-]?\d+'
+    t_NUM = r'[+-]?\d+(\.\d+)?'
     t_STRING_LITERAL = r'\"([^\\\n]|(\\.))*?\"'
 
     t_ignore_LINE_COMMENT = '//.*'
@@ -44,6 +45,7 @@
     t_RBRACK = '\\]'
     t_LPAR = '\\('
     t_RPAR = '\\)'
+    t_PLUS = '\\+'
     t_EQ = '='
     t_SEMI = ';'
     t_ARROW = '\\-\\>'
@@ -198,6 +200,27 @@
         p[0] = FieldDirective(Name(LU.i(p, 1)), LU.i(p, 3))
         self.lh.set_parse_object(p[0], p)
 
+
+    def p_csv_expr(self, p):
+        '''csv_expr : LPAR csv RPAR'''
+        p[0] = p[2]
+
+    def p_csv_expr2(self, p):
+        '''csv_expr : empty'''
+        p[0] = []
+
+    def p_csv2(self, p):
+        '''csv : empty'''
+
+    def p_csv(self, p):
+        '''csv : NAME 
+               | csv COMMA NAME'''
+
+        if len(p) == 2:
+            p[0] = [LU(p,1)]
+        else:
+            p[0] = p[1] + [LU(p,3)]
+
     def p_field_directive_times(self, p):
         '''field_directive_times : field_directive_plus'''
         p[0] = p[1]
@@ -226,6 +249,7 @@
     def p_fieldName(self, p):
         '''field_name : NAME
                       | MESSAGE
+                      | PLUS
                       | MAX'''
         p[0] = Name(LU.i(p,1))
         self.lh.set_parse_object(p[0], p)
@@ -344,18 +368,10 @@
         else:
             p[0] = p[1] + [p[2]]
 
-    def p_base_definition(self, p):
-        '''base_definition : LPAR NAME RPAR'''
-        p[0] = p[2]
-    
-    def p_base_definition2(self, p):
-        '''base_definition : empty'''
-        p[0] = None
-
     # Root of the message declaration.
     # message_definition = MESSAGE_ - ident("messageId") + LBRACE + message_body("body") + RBRACE
     def p_message_definition(self, p):
-        '''message_definition : MESSAGE NAME base_definition LBRACE message_body RBRACE'''
+        '''message_definition : MESSAGE NAME csv_expr LBRACE message_body RBRACE'''
         p[0] = MessageDefinition(Name(LU.i(p, 2)), LU.i(p, 3), LU.i(p,5))
         self.lh.set_parse_object(p[0], p)