From b1d3873ec52692b0442666718da4175379697bb2 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Mon, 1 Sep 2014 16:55:44 -0500 Subject: [PATCH] ruby: slicc: improve the grammar 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 | 11 +- src/mem/slicc/ast/ObjDeclAST.py | 28 +++-- src/mem/slicc/ast/TypeFieldMemberAST.py | 57 ---------- src/mem/slicc/ast/TypeFieldMethodAST.py | 52 ---------- src/mem/slicc/ast/__init__.py | 2 - src/mem/slicc/parser.py | 132 +++++++++++++----------- src/mem/slicc/symbols/StateMachine.py | 1 + src/mem/slicc/symbols/Type.py | 37 ++----- 8 files changed, 108 insertions(+), 212 deletions(-) delete mode 100644 src/mem/slicc/ast/TypeFieldMemberAST.py delete mode 100644 src/mem/slicc/ast/TypeFieldMethodAST.py diff --git a/src/mem/slicc/ast/FuncDeclAST.py b/src/mem/slicc/ast/FuncDeclAST.py index 1d7e2c3ff..052d9f05e 100644 --- a/src/mem/slicc/ast/FuncDeclAST.py +++ b/src/mem/slicc/ast/FuncDeclAST.py @@ -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: diff --git a/src/mem/slicc/ast/ObjDeclAST.py b/src/mem/slicc/ast/ObjDeclAST.py index 5cb662fc0..ffd71bbb1 100644 --- a/src/mem/slicc/ast/ObjDeclAST.py +++ b/src/mem/slicc/ast/ObjDeclAST.py @@ -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 index 30e2fcda5..000000000 --- a/src/mem/slicc/ast/TypeFieldMemberAST.py +++ /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 index b89f7f97e..000000000 --- a/src/mem/slicc/ast/TypeFieldMethodAST.py +++ /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)) diff --git a/src/mem/slicc/ast/__init__.py b/src/mem/slicc/ast/__init__.py index 98472cdf2..9fc52eff8 100644 --- a/src/mem/slicc/ast/__init__.py +++ b/src/mem/slicc/ast/__init__.py @@ -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 * diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py index 1a8fbd937..04ba4640c 100644 --- a/src/mem/slicc/parser.py +++ b/src/mem/slicc/parser.py @@ -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 '}'" diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index 6048383a5..2cda3a49d 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -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): diff --git a/src/mem/slicc/symbols/Type.py b/src/mem/slicc/symbols/Type.py index 764173916..d9bd85c01 100644 --- a/src/mem/slicc/symbols/Type.py +++ b/src/mem/slicc/symbols/Type.py @@ -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) -- 2.30.2