import sys
from m5.util import code_formatter
-from m5.util.grammar import Grammar, TokenError, ParseError
+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, protocol, **kwargs):
- super(SLICC, self).__init__(**kwargs)
- self.decl_list_vec = []
- self.current_file = None
- self.protocol = protocol
+ 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:
+ self.decl_list = self.parse_file(filename, **kwargs)
+ except ParseError, e:
+ if not self.traceback:
+ sys.exit(str(e))
+ raise
+
+ def currentLocation(self):
+ return util.Location(self.current_source, self.current_line,
+ no_warning=not self.verbose)
def codeFormatter(self, *args, **kwargs):
code = code_formatter(*args, **kwargs)
code['protocol'] = self.protocol
return code
- def parse(self, filename):
- self.current_file = filename
- f = file(filename, 'r')
- text = f.read()
- 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
-
- def findMachines(self):
- for decl_list in self.decl_list_vec:
- decl_list.findMachines()
+ def process(self):
+ self.decl_list.findMachines()
+ self.decl_list.generate()
- def generate(self):
- for decl_list in self.decl_list_vec:
- decl_list.generate()
+ def writeCodeFiles(self, code_path, includes):
+ self.symtab.writeCodeFiles(code_path, includes)
- def writeCodeFiles(self, code_path):
- util.makeDir(code_path)
- self.symtab.writeCodeFiles(code_path)
-
- def writeHTMLFiles(self, code_path):
- util.makeDir(code_path)
- self.symtab.writeHTMLFiles(code_path)
+ 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',
'is_invalid' : 'IS_INVALID',
'else' : 'ELSE',
'return' : 'RETURN',
- 'THIS' : 'THIS',
- 'CHIP' : 'CHIP',
'void' : 'VOID',
'new' : 'NEW',
'OOD' : 'OOD',
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"
"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"
"aexpr : OOD"
p[0] = ast.OodAST(self)
- # 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__member(self, p):
"aexpr : aexpr DOT ident"
p[0] = ast.MemberExprAST(self, p[1], p[3])
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]