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.
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
@@ -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))
|
||||
@@ -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 *
|
||||
|
||||
@@ -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 '}'"
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
def addFunc(self, func):
|
||||
ident = self.methodId(func.ident, func.param_types)
|
||||
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:
|
||||
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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user