ruby: move stall and wakeup functions to AbstractController
[gem5.git] / src / mem / slicc / parser.py
index 823e088192928c184332301426755765e9563929..78b842f7487722049c9a474d3e1f902f1717299f 100644 (file)
@@ -31,94 +31,45 @@ import re
 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 generate(self):
-        for decl_list in self.decl_list_vec:
-            decl_list.generate()
+    def process(self):
+        self.decl_list.findMachines()
+        self.decl_list.generate()
 
-    def writeCodeFiles(self, code_path):
-        util.makeDir(code_path)
-        self.symtab.writeCodeFiles(code_path)
+    def writeCodeFiles(self, code_path, includes):
+        self.symtab.writeCodeFiles(code_path, includes)
 
-    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([
@@ -126,8 +77,7 @@ class SLICC(Grammar):
             'MachineType.hh',
             'Types.hh' ])
 
-        for decl_list in self.decl_list_vec:
-            f |= decl_list.files()
+        f |= self.decl_list.files()
 
         return f
 
@@ -147,6 +97,8 @@ class SLICC(Grammar):
         t.lexer.lineno += len(t.value)
 
     reserved = {
+        'protocol' : 'PROTOCOL',
+        'include' : 'INCLUDE',
         'global' : 'GLOBAL',
         'machine' : 'MACHINE',
         'in_port' : 'IN_PORT',
@@ -156,10 +108,9 @@ class SLICC(Grammar):
         'structure' : 'STRUCT',
         'external_type' : 'EXTERN_TYPE',
         'enumeration' : 'ENUM',
+        'state_declaration' : 'STATE_DECL',
         'peek' : 'PEEK',
         'stall_and_wait' : 'STALL_AND_WAIT',
-        'wake_up_dependents' : 'WAKE_UP_DEPENDENTS',
-        'wake_up_all_dependents' : 'WAKE_UP_ALL_DEPENDENTS',
         'enqueue' : 'ENQUEUE',
         'copy_head' : 'COPY_HEAD',
         'check_allocate' : 'CHECK_ALLOCATE',
@@ -170,8 +121,6 @@ class SLICC(Grammar):
         'is_invalid' : 'IS_INVALID',
         'else' : 'ELSE',
         'return' : 'RETURN',
-        'THIS' : 'THIS',
-        'CHIP' : 'CHIP',
         'void' : 'VOID',
         'new' : 'NEW',
         'OOD' : 'OOD',
@@ -239,7 +188,7 @@ class SLICC(Grammar):
         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):
@@ -247,7 +196,7 @@ class SLICC(Grammar):
         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):
@@ -275,12 +224,36 @@ class SLICC(Grammar):
 
     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])
@@ -299,22 +272,25 @@ class SLICC(Grammar):
 
     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"
@@ -329,18 +305,33 @@ class SLICC(Grammar):
         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
@@ -352,28 +343,23 @@ class SLICC(Grammar):
         "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"
@@ -387,6 +373,19 @@ class SLICC(Grammar):
         "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"
@@ -558,14 +557,6 @@ class SLICC(Grammar):
         "statement : STALL_AND_WAIT '(' var ',' var ')' SEMI"
         p[0] = ast.StallAndWaitStatementAST(self, p[3], p[5])
 
-    def p_statement__wake_up_dependents(self, p):
-        "statement : WAKE_UP_DEPENDENTS '(' var ')' SEMI"
-        p[0] = ast.WakeUpDependentsStatementAST(self, p[3])
-
-    def p_statement__wake_up_all_dependents(self, p):
-        "statement : WAKE_UP_ALL_DEPENDENTS '(' ')' SEMI"
-        p[0] = ast.WakeUpAllDependentsStatementAST(self)
-
     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")
@@ -639,27 +630,6 @@ class SLICC(Grammar):
         "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])
@@ -738,7 +708,3 @@ class SLICC(Grammar):
     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]