import re
import sys
-from m5.util.grammar import Grammar, TokenError, ParseError
+from m5.util import code_formatter
+from m5.util.grammar import Grammar, ParseError
import slicc.ast as ast
import slicc.util as util
from slicc.symbols import SymbolTable
-def read_slicc(sources):
- if not isinstance(sources, (list,tuple)):
- sources = [ sources ]
-
- for source in sources:
- for sm_file in file(source, "r"):
- sm_file = sm_file.strip()
- if not sm_file:
- continue
- if sm_file.startswith("#"):
- continue
- yield sm_file
-
class SLICC(Grammar):
- def __init__(self, **kwargs):
- super(SLICC, self).__init__(**kwargs)
- self.decl_list_vec = []
- self.current_file = None
- self.symtab = SymbolTable()
-
- def parse(self, filename):
- self.current_file = filename
- f = file(filename, 'r')
- text = f.read()
+ def __init__(self, filename, base_dir, verbose=False, traceback=False, **kwargs):
+ self.protocol = None
+ self.traceback = traceback
+ self.verbose = verbose
+ self.symtab = SymbolTable(self)
+ self.base_dir = base_dir
+
try:
- decl_list = super(SLICC, self).parse(text)
- except (TokenError, ParseError), e:
- sys.exit("%s: %s:%d" % (e, filename, e.token.lineno))
- self.decl_list_vec.append(decl_list)
- self.current_file = None
-
- def _load(self, *filenames):
- filenames = list(filenames)
- while filenames:
- f = filenames.pop(0)
- if isinstance(f, (list, tuple)):
- filenames[0:0] = list(f)
- continue
-
- yield f
- if f.endswith(".slicc"):
- dirname,basename = os.path.split(f)
- filenames[0:0] = [ os.path.join(dirname, x) \
- for x in read_slicc(f)]
- else:
- assert f.endswith(".sm")
- self.parse(f)
-
- def load(self, *filenames, **kwargs):
- verbose = kwargs.pop("verbose", False)
- if kwargs:
- raise TypeError
-
- gen = self._load(*filenames)
- if verbose:
- return gen
- else:
- # Run out the generator if we don't want the verbosity
- for foo in gen:
- pass
+ self.decl_list = self.parse_file(filename, **kwargs)
+ except ParseError, e:
+ if not self.traceback:
+ sys.exit(str(e))
+ raise
- def findMachines(self):
- for decl_list in self.decl_list_vec:
- decl_list.findMachines()
+ def currentLocation(self):
+ return util.Location(self.current_source, self.current_line,
+ no_warning=not self.verbose)
- def generate(self):
- for decl_list in self.decl_list_vec:
- decl_list.generate()
+ def codeFormatter(self, *args, **kwargs):
+ code = code_formatter(*args, **kwargs)
+ code['protocol'] = self.protocol
+ return code
- def writeCodeFiles(self, code_path):
- util.makeDir(code_path)
- self.symtab.writeCodeFiles(code_path)
+ def process(self):
+ self.decl_list.findMachines()
+ self.decl_list.generate()
- def writeHTMLFiles(self, code_path):
- util.makeDir(code_path)
- self.symtab.writeHTMLFiles(code_path)
+ def writeCodeFiles(self, code_path, includes):
+ self.symtab.writeCodeFiles(code_path, includes)
+
+ def writeHTMLFiles(self, html_path):
+ self.symtab.writeHTMLFiles(html_path)
def files(self):
f = set([
'MachineType.hh',
'Types.hh' ])
- for decl_list in self.decl_list_vec:
- f |= decl_list.files()
+ f |= self.decl_list.files()
return f
t.lexer.lineno += len(t.value)
reserved = {
+ 'protocol' : 'PROTOCOL',
+ 'include' : 'INCLUDE',
'global' : 'GLOBAL',
'machine' : 'MACHINE',
'in_port' : 'IN_PORT',
'structure' : 'STRUCT',
'external_type' : 'EXTERN_TYPE',
'enumeration' : 'ENUM',
+ 'state_declaration' : 'STATE_DECL',
'peek' : 'PEEK',
+ 'stall_and_wait' : 'STALL_AND_WAIT',
'enqueue' : 'ENQUEUE',
'copy_head' : 'COPY_HEAD',
'check_allocate' : 'CHECK_ALLOCATE',
'check_stop_slots' : 'CHECK_STOP_SLOTS',
+ 'static_cast' : 'STATIC_CAST',
'if' : 'IF',
+ 'is_valid' : 'IS_VALID',
+ 'is_invalid' : 'IS_INVALID',
'else' : 'ELSE',
'return' : 'RETURN',
- 'THIS' : 'THIS',
- 'CHIP' : 'CHIP',
'void' : 'VOID',
'new' : 'NEW',
+ 'OOD' : 'OOD',
}
literals = ':[]{}(),='
try:
t.value = float(t.value)
except ValueError:
- raise TokenError("Illegal float", t)
+ raise ParseError("Illegal float", t)
return t
def t_NUMBER(self, t):
try:
t.value = int(t.value)
except ValueError:
- raise TokenError("Illegal number", t)
+ raise ParseError("Illegal number", t)
return t
def t_STRING1(self, t):
def p_declsx__list(self, p):
"declsx : decl declsx"
- p[0] = [ p[1] ] + p[2]
+ if isinstance(p[1], ast.DeclListAST):
+ decls = p[1].decls
+ elif p[1] is None:
+ decls = []
+ else:
+ decls = [ p[1] ]
+ p[0] = decls + p[2]
def p_declsx__none(self, p):
"declsx : empty"
p[0] = []
+ def p_decl__protocol(self, p):
+ "decl : PROTOCOL STRING SEMI"
+ if self.protocol:
+ msg = "Protocol can only be set once! Error at %s:%s\n" % \
+ (self.current_source, self.current_line)
+ raise ParseError(msg)
+ self.protocol = p[2]
+ p[0] = None
+
+ def p_decl__include(self, p):
+ "decl : INCLUDE STRING SEMI"
+ dirname = os.path.dirname(self.current_source)
+ if os.path.exists(os.path.join(dirname, p[2])):
+ filename = os.path.join(dirname, p[2])
+ else:
+ filename = os.path.join(self.base_dir, p[2])
+ p[0] = self.parse_file(filename)
+
def p_decl__machine(self, p):
"decl : MACHINE '(' ident pairs ')' ':' params '{' decls '}'"
p[0] = ast.MachineAST(self, p[3], p[4], p[7], p[9])
def p_decl__trans0(self, p):
"decl : TRANS '(' idents ',' idents ',' ident pairs ')' idents"
- p[0] = ast.TransitionDeclAST(self, p[3], p[5], p[7], p[8], p[10])
+ p[0] = ast.TransitionDeclAST(self, [], p[3], p[5], p[7], p[8], p[10])
def p_decl__trans1(self, p):
"decl : TRANS '(' idents ',' idents pairs ')' idents"
- p[0] = ast.TransitionDeclAST(self, p[3], p[5], None, p[6], p[8])
+ p[0] = ast.TransitionDeclAST(self, [], p[3], p[5], None, p[6], p[8])
+
+ def p_decl__trans2(self, p):
+ "decl : TRANS '(' idents ',' idents ',' ident pairs ')' idents idents"
+ p[0] = ast.TransitionDeclAST(self, p[10], p[3], p[5], p[7], p[8], p[11])
+
+ def p_decl__trans3(self, p):
+ "decl : TRANS '(' idents ',' idents pairs ')' idents idents"
+ p[0] = ast.TransitionDeclAST(self, p[8], p[3], p[5], None, p[6], p[9])
def p_decl__extern0(self, p):
"decl : EXTERN_TYPE '(' type pairs ')' SEMI"
p[4]["external"] = "yes"
p[0] = ast.TypeDeclAST(self, p[3], p[4], [])
- def p_decl__extern1(self, p):
- "decl : EXTERN_TYPE '(' type pairs ')' '{' type_methods '}'"
- p[4]["external"] = "yes"
- p[0] = ast.TypeDeclAST(self, p[3], p[4], p[7])
-
def p_decl__global(self, p):
"decl : GLOBAL '(' type pairs ')' '{' type_members '}'"
p[4]["global"] = "yes"
p[4]["enumeration"] = "yes"
p[0] = ast.EnumDeclAST(self, p[3], p[4], p[7])
+ def p_decl__state_decl(self, p):
+ "decl : STATE_DECL '(' type pairs ')' '{' type_states '}'"
+ p[4]["enumeration"] = "yes"
+ 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])
+ # Function definition and declaration
def p_decl__func_decl(self, p):
- """decl : void ident '(' params ')' pairs SEMI
+ "decl : func_decl"
+ p[0] = p[1]
+
+ def p_func_decl__0(self, p):
+ """func_decl : void ident '(' params ')' pairs SEMI
| type ident '(' params ')' pairs SEMI"""
p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], None)
def p_decl__func_def(self, p):
- """decl : void ident '(' params ')' pairs statements
- | type ident '(' params ')' pairs statements"""
+ "decl : func_def"
+ p[0] = p[1]
+
+ def p_func_def__0(self, p):
+ """func_def : void ident '(' params ')' pairs statements
+ | type ident '(' params ')' pairs statements"""
p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], p[7])
# Type fields
"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 ident pairs SEMI"
+ "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 ident ASSIGN expr SEMI"
+ "type_member : type_or_void ident ASSIGN expr SEMI"
p[0] = ast.TypeFieldMemberAST(self, p[1], p[2],
ast.PairListAST(self), p[4])
- # Methods
- def p_type_methods__list(self, p):
- "type_methods : type_method type_methods"
- p[0] = [ p[1] ] + p[2]
-
- def p_type_methods(self, p):
- "type_methods : empty"
- p[0] = []
-
- def p_type_method(self, p):
- "type_method : type_or_void ident '(' types ')' pairs SEMI"
- p[0] = ast.TypeFieldMethodAST(self, p[1], p[2], p[4], p[6])
-
# Enum fields
def p_type_enums__list(self, p):
"type_enums : type_enum type_enums"
"type_enum : ident pairs SEMI"
p[0] = ast.TypeFieldEnumAST(self, p[1], p[2])
+ # States
+ def p_type_states__list(self, p):
+ "type_states : type_state type_states"
+ p[0] = [ p[1] ] + p[2]
+
+ def p_type_states__empty(self, p):
+ "type_states : empty"
+ p[0] = []
+
+ def p_type_state(self, p):
+ "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"
"types : empty"
p[0] = []
- def p_type(self, p):
- "type : ident"
+ 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):
"param : type ident"
p[0] = ast.FormalParamAST(self, p[1], p[2])
- def p_param__default(self, p):
+ def p_param__pointer(self, p):
+ "param : type STAR ident"
+ p[0] = ast.FormalParamAST(self, p[1], p[3], None, True)
+
+ def p_param__pointer_default(self, p):
+ "param : type STAR ident '=' STRING"
+ p[0] = ast.FormalParamAST(self, p[1], p[3], p[5], True)
+
+ def p_param__default_number(self, p):
"param : type ident '=' NUMBER"
p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
+ def p_param__default_bool(self, p):
+ "param : type ident '=' LIT_BOOL"
+ p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
+
+ def p_param__default_string(self, p):
+ "param : type ident '=' STRING"
+ p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
+
# Idents and lists
def p_idents__braced(self, p):
"idents : '{' identx '}'"
def p_pair__assign(self, p):
"""pair : ident '=' STRING
- | ident '=' ident"""
+ | ident '=' ident
+ | ident '=' NUMBER"""
p[0] = ast.PairAST(self, p[1], p[3])
def p_pair__literal(self, p):
"statement : ENQUEUE '(' var ',' type pairs ')' statements"
p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[6], p[8])
+ def p_statement__stall_and_wait(self, p):
+ "statement : STALL_AND_WAIT '(' var ',' var ')' SEMI"
+ p[0] = ast.StallAndWaitStatementAST(self, p[3], p[5])
+
def p_statement__peek(self, p):
"statement : PEEK '(' var ',' type pairs ')' statements"
p[0] = ast.PeekStatementAST(self, p[3], p[5], p[6], p[8], "peek")
"statement : CHECK_STOP_SLOTS '(' var ',' STRING ',' STRING ')' SEMI"
p[0] = ast.CheckStopStatementAST(self, p[3], p[5], p[7])
+ def p_statement__static_cast(self, p):
+ "aexpr : STATIC_CAST '(' type ',' expr ')'"
+ p[0] = ast.StaticCastAST(self, p[3], "ref", p[5])
+
+ def p_statement__static_cast_ptr(self, p):
+ "aexpr : STATIC_CAST '(' type ',' STRING ',' expr ')'"
+ p[0] = ast.StaticCastAST(self, p[3], p[5], p[7])
+
def p_statement__return(self, p):
"statement : RETURN expr SEMI"
p[0] = ast.ReturnStatementAST(self, p[2])
"aexpr : var"
p[0] = p[1]
+ def p_expr__localvar(self, p):
+ "aexpr : type ident"
+ p[0] = ast.LocalVariableAST(self, p[1], p[2])
+
def p_expr__literal(self, p):
"aexpr : literal"
p[0] = p[1]
"aexpr : NEW type"
p[0] = ast.NewExprAST(self, p[2])
- # globally access a local chip component and call a method
- def p_expr__local_chip_method(self, p):
- "aexpr : THIS DOT var '[' expr ']' DOT var DOT ident '(' exprs ')'"
- p[0] = ast.LocalChipMethodAST(self, p[3], p[5], p[8], p[10], p[12])
-
- # globally access a local chip component and access a data member
- def p_expr__local_chip_member(self, p):
- "aexpr : THIS DOT var '[' expr ']' DOT var DOT field"
- p[0] = ast.LocalChipMemberAST(self, p[3], p[5], p[8], p[10])
-
- # globally access a specified chip component and call a method
- def p_expr__specified_chip_method(self, p):
- "aexpr : CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT ident '(' exprs ')'"
- p[0] = ast.SpecifiedChipMethodAST(self, p[3], p[6], p[8], p[11], p[13],
- p[15])
-
- # globally access a specified chip component and access a data member
- def p_expr__specified_chip_member(self, p):
- "aexpr : CHIP '[' expr ']' DOT var '[' expr ']' DOT var DOT field"
- p[0] = ast.SpecifiedChipMemberAST(self, p[3], p[6], p[8], p[11], p[13])
+ def p_expr__null(self, p):
+ "aexpr : OOD"
+ p[0] = ast.OodAST(self)
def p_expr__member(self, p):
"aexpr : aexpr DOT ident"
"aexpr : '(' expr ')'"
p[0] = p[2]
+ def p_expr__is_valid_ptr(self, p):
+ "aexpr : IS_VALID '(' var ')'"
+ p[0] = ast.IsValidPtrExprAST(self, p[3], True)
+
+ def p_expr__is_invalid_ptr(self, p):
+ "aexpr : IS_INVALID '(' var ')'"
+ p[0] = ast.IsValidPtrExprAST(self, p[3], False)
+
def p_literal__string(self, p):
"literal : STRING"
- p[0] = ast.LiteralExprAST(self, p[1], "string")
+ p[0] = ast.LiteralExprAST(self, p[1], "std::string")
def p_literal__number(self, p):
"literal : NUMBER"
def p_var(self, p):
"var : ident"
p[0] = ast.VarExprAST(self, p[1])
-
- def p_field(self, p):
- "field : ident"
- p[0] = p[1]