ruby: slicc: improve the grammar
authorNilay Vaish <nilay@cs.wisc.edu>
Mon, 1 Sep 2014 21:55:44 +0000 (16:55 -0500)
committerNilay Vaish <nilay@cs.wisc.edu>
Mon, 1 Sep 2014 21:55:44 +0000 (16:55 -0500)
This patch changes the grammar for SLICC so as to remove some of the
redundant / duplicate rules.  In particular rules for object/variable
declaration and class member declaration have been unified. Similarly, the
rules for a general function and a class method have been unified.

One more change is in the priority of two rules.  The first rule is on
declaring a function with all the params typed and named.  The second rule is
on declaring a function with all the params only typed.  Earlier the second
rule had a higher priority.  Now the first rule has a higher priority.

src/mem/slicc/ast/FuncDeclAST.py
src/mem/slicc/ast/ObjDeclAST.py
src/mem/slicc/ast/TypeFieldMemberAST.py [deleted file]
src/mem/slicc/ast/TypeFieldMethodAST.py [deleted file]
src/mem/slicc/ast/__init__.py
src/mem/slicc/parser.py
src/mem/slicc/symbols/StateMachine.py
src/mem/slicc/symbols/Type.py

index 1d7e2c3ffee836b968b1289e323950949c14dcd4..052d9f05e7465bed3664a0704ba3416571d3021a 100644 (file)
@@ -57,9 +57,14 @@ class FuncDeclAST(DeclAST):
         # Generate function header
         for formal in self.formals:
             # Lookup parameter types
-            type, ident = formal.generate()
-            types.append(type)
-            params.append(ident)
+            try:
+                type, ident = formal.generate()
+                types.append(type)
+                params.append(ident)
+
+            except AttributeError:
+                types.append(formal.type)
+                params.append(None)
 
         body = self.slicc.codeFormatter()
         if self.statements is None:
index 5cb662fc00b337e1b8007bc7a742d7c304d5b3aa..ffd71bbb137dfad8d5996cd7c34788cfee7a0276 100644 (file)
@@ -29,21 +29,23 @@ from slicc.ast.DeclAST import DeclAST
 from slicc.symbols import Var
 
 class ObjDeclAST(DeclAST):
-    def __init__(self, slicc, type_ast, ident, pairs):
+    def __init__(self, slicc, type_ast, ident, pairs, rvalue):
         super(ObjDeclAST, self).__init__(slicc, pairs)
 
         self.type_ast = type_ast
         self.ident = ident
+        self.rvalue = rvalue
 
     def __repr__(self):
         return "[ObjDecl: %r]" % self.ident
 
-    def generate(self):
+    def generate(self, parent = None):
         if "network" in self and not ("virtual_network" in self or
                                       "physical_network" in self) :
             self.error("Network queues require a 'virtual_network' attribute")
 
         type = self.type_ast.type
+
         if type.isBuffer and "ordered" not in self:
             self.error("Buffer object decls require an 'ordered' attribute")
 
@@ -60,8 +62,6 @@ class ObjDeclAST(DeclAST):
                 self.error("The 'random' attribute is '%s' " + \
                            "must be 'true' or 'false'.", value)
 
-        machine = self.symtab.state_machine
-
         # FIXME : should all use accessors here to avoid public member
         # variables
         if self.ident == "version":
@@ -73,10 +73,26 @@ class ObjDeclAST(DeclAST):
         else:
             c_code = "(*m_%s_ptr)" % (self.ident)
 
+        # check type if this is a initialization
+        init_code = ""
+        if self.rvalue:
+            rvalue_type,init_code = self.rvalue.inline(True)
+            if type != rvalue_type:
+                self.error("Initialization type mismatch '%s' and '%s'" % \
+                           (type, rvalue_type))
+
+        machine = self.symtab.state_machine
+
         v = Var(self.symtab, self.ident, self.location, type, c_code,
                 self.pairs, machine)
 
-        if machine:
+        # Add data member to the parent type
+        if parent:
+            if not parent.addDataMember(self.ident, type, self.pairs, init_code):
+                self.error("Duplicate data member: %s:%s" % (parent, self.ident))
+
+        elif machine:
             machine.addObject(v)
 
-        self.symtab.newSymbol(v)
+        else:
+            self.symtab.newSymbol(v)
diff --git a/src/mem/slicc/ast/TypeFieldMemberAST.py b/src/mem/slicc/ast/TypeFieldMemberAST.py
deleted file mode 100644 (file)
index 30e2fcd..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
-# Copyright (c) 2009 The Hewlett-Packard Development Company
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-from slicc.ast.TypeFieldAST import TypeFieldAST
-
-class TypeFieldMemberAST(TypeFieldAST):
-    def __init__(self, slicc, type_ast, field_id, pairs, rvalue):
-        super(TypeFieldMemberAST, self).__init__(slicc, pairs)
-
-        self.type_ast = type_ast
-        self.field_id = field_id
-        self.rvalue = rvalue
-
-    def __repr__(self):
-        return "[TypeFieldMember: %r]" % self.field_id
-
-    def generate(self, type):
-        # Lookup type
-        field_type = self.type_ast.type
-
-        # check type if this is a initialization
-        init_code = ""
-        if self.rvalue:
-            rvalue_type,init_code = self.rvalue.inline(True)
-            if field_type != rvalue_type:
-                self.error("Initialization type mismatch '%s' and '%s'" % \
-                           (field_type, rvalue_type))
-
-        # Add data member to the parent type
-        if not type.addDataMember(self.field_id, field_type, self.pairs,
-                                  init_code):
-
-            self.error("Duplicate data member: %s:%s" % (field_type, self.field_id))
diff --git a/src/mem/slicc/ast/TypeFieldMethodAST.py b/src/mem/slicc/ast/TypeFieldMethodAST.py
deleted file mode 100644 (file)
index b89f7f9..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
-# Copyright (c) 2009 The Hewlett-Packard Development Company
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met: redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer;
-# redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution;
-# neither the name of the copyright holders nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-from slicc.ast.TypeFieldAST import TypeFieldAST
-
-class TypeFieldMethodAST(TypeFieldAST):
-    def __init__(self, slicc, return_type_ast, ident, type_asts, pairs,
-        statements = None):
-        super(TypeFieldMethodAST, self).__init__(slicc, pairs)
-
-        self.return_type_ast = return_type_ast
-        self.ident = ident
-        self.type_asts = type_asts
-        self.statements = statements
-
-    def __repr__(self):
-        return ""
-
-    def generate(self, type):
-        # Lookup return type
-        return_type = self.return_type_ast.type
-
-        # Lookup parameter types
-        types = [ t.type for t in self.type_asts ]
-
-        # Add method
-        if not type.addMethod(self.ident, return_type, types):
-            self.error("Duplicate method: %s:%s()" % (type, self.ident))
index 98472cdf263273f4119a4683a2b115dee248f772..9fc52eff83b692a0373847b16c63453e40104156 100644 (file)
@@ -67,7 +67,5 @@ from slicc.ast.TypeAST import *
 from slicc.ast.TypeDeclAST import *
 from slicc.ast.TypeFieldAST import *
 from slicc.ast.TypeFieldEnumAST import *
-from slicc.ast.TypeFieldMemberAST import *
-from slicc.ast.TypeFieldMethodAST import *
 from slicc.ast.TypeFieldStateAST import *
 from slicc.ast.VarExprAST import *
index 1a8fbd93793e4a69121313536869cd692249bd89..04ba4640ca52f130e2459465a0fabf2d00a3574c 100644 (file)
@@ -318,9 +318,41 @@ class SLICC(Grammar):
         p[4]["state_decl"] = "yes"
         p[0] = ast.StateDeclAST(self, p[3], p[4], p[7])
 
-    def p_decl__object(self, p):
-        "decl : type ident pairs SEMI"
-        p[0] = ast.ObjDeclAST(self, p[1], p[2], p[3])
+    # Type fields
+    def p_type_members__list(self, p):
+        "type_members : type_member type_members"
+        p[0] = [ p[1] ] + p[2]
+
+    def p_type_members__empty(self, p):
+        "type_members : empty"
+        p[0] = []
+
+    def p_type_member__0(self, p):
+        """type_member : obj_decl
+                       | func_decl
+                       | func_def"""
+        p[0] = p[1]
+
+    # Member / Variable declarations
+    def p_decl__obj_decl(self, p):
+        "decl : obj_decl"
+        p[0] = p[1]
+
+    def p_obj_decl__0(self, p):
+        "obj_decl : type ident pairs SEMI"
+        p[0] = ast.ObjDeclAST(self, p[1], p[2], p[3], None)
+
+    def p_obj_decl__1(self, p):
+        "obj_decl : type STAR ident pairs SEMI"
+        p[0] = ast.ObjDeclAST(self, p[1], p[3], p[4], None)
+
+    def p_obj_decl__2(self, p):
+        "obj_decl : type ident ASSIGN expr SEMI"
+        p[0] = ast.ObjDeclAST(self, p[1], p[2], ast.PairListAST(self), p[4])
+
+    def p_obj_decl__3(self, p):
+        "obj_decl : type STAR ident ASSIGN expr SEMI"
+        p[0] = ast.ObjDeclAST(self, p[1], p[3], ast.PairListAST(self), p[5])
 
     # Function definition and declaration
     def p_decl__func_decl(self, p):
@@ -332,6 +364,11 @@ class SLICC(Grammar):
                 | type ident '(' params ')' pairs SEMI"""
         p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], None)
 
+    def p_func_decl__1(self, p):
+        """func_decl :  void ident '(' types ')' pairs SEMI
+                | type ident '(' types ')' pairs SEMI"""
+        p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], None)
+
     def p_decl__func_def(self, p):
         "decl : func_def"
         p[0] = p[1]
@@ -341,32 +378,6 @@ class SLICC(Grammar):
             | type ident '(' params ')' pairs statements"""
         p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], p[7])
 
-    # Type fields
-    def p_type_members__list(self, p):
-        "type_members : type_member type_members"
-        p[0] = [ p[1] ] + p[2]
-
-    def p_type_members__empty(self, p):
-        "type_members : empty"
-        p[0] = []
-
-    def p_type_method__0(self, p):
-        "type_member : type_or_void ident '(' types ')' pairs SEMI"
-        p[0] = ast.TypeFieldMethodAST(self, p[1], p[2], p[4], p[6])
-
-    def p_type_method__1(self, p):
-        "type_member : type_or_void ident '(' params ')' pairs statements"
-        p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], p[7])
-
-    def p_type_member__1(self, p):
-        "type_member : type_or_void ident pairs SEMI"
-        p[0] = ast.TypeFieldMemberAST(self, p[1], p[2], p[3], None)
-
-    def p_type_member__2(self, p):
-        "type_member : type_or_void ident ASSIGN expr SEMI"
-        p[0] = ast.TypeFieldMemberAST(self, p[1], p[2],
-                                      ast.PairListAST(self), p[4])
-
     # Enum fields
     def p_type_enums__list(self, p):
         "type_enums : type_enum type_enums"
@@ -393,40 +404,6 @@ class SLICC(Grammar):
         "type_state : ident ',' enumeration pairs SEMI"
         p[0] = ast.TypeFieldStateAST(self, p[1], p[3], p[4])
 
-    # Type
-    def p_types__multiple(self, p):
-        "types : type ',' types"
-        p[0] = [ p[1] ] + p[3]
-
-    def p_types__one(self, p):
-        "types : type"
-        p[0] = [ p[1] ]
-
-    def p_types__empty(self, p):
-        "types : empty"
-        p[0] = []
-
-    def p_typestr__multi(self, p):
-        "typestr : typestr DOUBLE_COLON ident"
-        p[0] = '%s::%s' % (p[1], p[3])
-
-    def p_typestr__single(self, p):
-        "typestr : ident"
-        p[0] = p[1]
-
-    def p_type__one(self, p):
-        "type : typestr"
-        p[0] = ast.TypeAST(self, p[1])
-
-    def p_void(self, p):
-        "void : VOID"
-        p[0] = ast.TypeAST(self, p[1])
-
-    def p_type_or_void(self, p):
-        """type_or_void : type
-                        | void"""
-        p[0] = p[1]
-
     # Formal Param
     def p_params__many(self, p):
         "params : param ',' params"
@@ -464,6 +441,35 @@ class SLICC(Grammar):
         "param : type ident '=' STRING"
         p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
 
+    # Type
+    def p_types__multiple(self, p):
+        "types : type ',' types"
+        p[0] = [ p[1] ] + p[3]
+
+    def p_types__one(self, p):
+        "types : type"
+        p[0] = [ p[1] ]
+
+    def p_types__empty(self, p):
+        "types : empty"
+        p[0] = []
+
+    def p_typestr__multi(self, p):
+        "typestr : typestr DOUBLE_COLON ident"
+        p[0] = '%s::%s' % (p[1], p[3])
+
+    def p_typestr__single(self, p):
+        "typestr : ident"
+        p[0] = p[1]
+
+    def p_type__one(self, p):
+        "type : typestr"
+        p[0] = ast.TypeAST(self, p[1])
+
+    def p_void(self, p):
+        "void : VOID"
+        p[0] = ast.TypeAST(self, p[1])
+
     # Idents and lists
     def p_idents__braced(self, p):
         "idents : '{' identx '}'"
index 6048383a5aef6ce30b3be2f74156b943de55df08..2cda3a49d78f55139b2ade100d7110af00b20124 100644 (file)
@@ -120,6 +120,7 @@ class StateMachine(Symbol):
         self.functions.append(func)
 
     def addObject(self, obj):
+        self.symtab.registerSym(str(obj), obj)
         self.objects.append(obj)
 
     def addType(self, type):
index 7641739166bfd3a15aa77a161b8e55f55eff169e..d9bd85c0184c847264ea3d00e94f96e26064339e 100644 (file)
@@ -43,11 +43,6 @@ class Enumeration(PairContainer):
         super(Enumeration, self).__init__(pairs)
         self.ident = ident
 
-class Method(object):
-    def __init__(self, return_type, param_types):
-        self.return_type = return_type
-        self.param_types = param_types
-
 class Type(Symbol):
     def __init__(self, table, ident, location, pairs, machine=None):
         super(Type, self).__init__(table, ident, location, pairs)
@@ -96,12 +91,7 @@ class Type(Symbol):
         self.statePermPairs = []
 
         self.data_members = orderdict()
-
-        # Methods
         self.methods = {}
-        self.functions = {}
-
-        # Enums
         self.enums = orderdict()
 
     @property
@@ -160,23 +150,12 @@ class Type(Symbol):
     def statePermPairAdd(self, state_name, perm_name):
         self.statePermPairs.append([state_name, perm_name])
 
-    def addMethod(self, name, return_type, param_type_vec):
-        ident = self.methodId(name, param_type_vec)
-        if ident in self.methods:
-            return False
-
-        self.methods[ident] = Method(return_type, param_type_vec)
-        return True
-
-    # Ideally either this function or the one above should exist. But
-    # methods and functions have different structures right now.
-    # Hence, these are different, at least for the time being.
     def addFunc(self, func):
         ident = self.methodId(func.ident, func.param_types)
-        if ident in self.functions:
+        if ident in self.methods:
             return False
 
-        self.functions[ident] = func
+        self.methods[ident] = func
         return True
 
     def addEnum(self, ident, pairs):
@@ -379,9 +358,9 @@ set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
 
                 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
 
-        # Prototypes for functions defined for the Type
-        for item in self.functions:
-            proto = self.functions[item].prototype
+        # Prototypes for methods defined for the Type
+        for item in self.methods:
+            proto = self.methods[item].prototype
             if proto:
                 code('$proto')
 
@@ -442,9 +421,9 @@ ${{self.c_ident}}::print(ostream& out) const
     out << "]";
 }''')
 
-        # print the code for the functions in the type
-        for item in self.functions:
-            code(self.functions[item].generateCode())
+        # print the code for the methods in the type
+        for item in self.methods:
+            code(self.methods[item].generateCode())
 
         code.write(path, "%s.cc" % self.c_ident)