From 831e9b3b7a658663f5bffafef175d4f4a5615cfd Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 5 Jul 2011 18:30:05 -0700 Subject: [PATCH] slicc: cleanup slicc code and make it less verbose --- src/mem/protocol/SConscript | 84 ++++++++-------------------- src/mem/slicc/ast/AST.py | 2 +- src/mem/slicc/main.py | 22 ++++---- src/mem/slicc/parser.py | 32 ++++------- src/mem/slicc/symbols/SymbolTable.py | 12 +++- src/mem/slicc/util.py | 20 ++++--- src/python/m5/util/__init__.py | 9 +++ 7 files changed, 73 insertions(+), 108 deletions(-) diff --git a/src/mem/protocol/SConscript b/src/mem/protocol/SConscript index 5f64938c6..47a19aecb 100644 --- a/src/mem/protocol/SConscript +++ b/src/mem/protocol/SConscript @@ -29,10 +29,13 @@ # Authors: Nathan Binkert import os +import re import sys from os.path import isdir, isfile, join as joinpath +from SCons.Scanner import Classic + Import('*') if not env['RUBY']: @@ -54,77 +57,36 @@ for root,dirs,files in os.walk(slicc_dir.srcnode().abspath): # # Use SLICC # - -def slicc_scanner(node, env, path): - contents = node.get_contents() - files = [ line.strip() for line in contents.splitlines() if line ] - return files - -env.Append(SCANNERS=Scanner(function=slicc_scanner,skeys=['.slicc'])) +env['SLICC_PATH'] = str(protocol_dir) +slicc_scanner = Classic("SliccScanner", ['.sm', '.slicc'], "SLICC_PATH", + r'''include[ \t]["'](.*)["'];''') +env.Append(SCANNERS=slicc_scanner) def slicc_emitter(target, source, env): protocol = source[0].get_contents() files = [s.srcnode().abspath for s in source[1:]] - slicc = SLICC(protocol, debug=True) - print "SLICC parsing..." - for name in slicc.load(files, verbose=True): - print " %s" % name + slicc = SLICC(protocol, verbose=False) + slicc.load(files) + slicc.process() + slicc.writeCodeFiles(protocol_dir.abspath) + if not env['NO_HTML']: + slicc.writeHTMLFiles(html_dir.abspath) - target.extend(sorted(slicc.files())) - pdir = str(protocol_dir) - hdir = str(html_dir) - - if not isdir(pdir): - os.mkdir(pdir) - if not isdir(hdir): - os.mkdir(hdir) - - print "SLICC Generator pass 1..." - slicc.findMachines() - - print "SLICC Generator pass 2..." - slicc.generate() - - print "SLICC writing C++ files..." - slicc.writeCodeFiles(pdir) - - if env['NO_HTML']: - print "skipping HTML file creation" - else: - print "SLICC writing HTML files..." - slicc.writeHTMLFiles(hdir) + target.extend([protocol_dir.File(f) for f in sorted(slicc.files())]) return target, source def slicc_action(target, source, env): protocol = source[0].get_contents() - pdir = str(protocol_dir) - hdir = str(html_dir) + files = [s.srcnode().abspath for s in source[1:]] + slicc = SLICC(protocol, verbose=True) + slicc.load(files) + slicc.process() + slicc.writeCodeFiles(protocol_dir.abspath) + if not env['NO_HTML']: + slicc.writeHTMLFiles(html_dir.abspath) - if not isdir(pdir): - os.mkdir(pdir) - if not isdir(hdir): - os.mkdir(hdir) - - slicc = SLICC(protocol, debug=True) - files = [str(s) for s in source[1:]] - slicc.load(files, verbose=False) - - print "SLICC Generator pass 1..." - slicc.findMachines() - - print "SLICC Generator pass 2..." - slicc.generate() - - print "SLICC writing C++ files..." - slicc.writeCodeFiles(pdir) - - if env['NO_HTML']: - print "skipping HTML file creation" - else: - print "SLICC writing HTML files..." - slicc.writeHTMLFiles(hdir) - -slicc_builder = Builder(action=slicc_action, emitter=slicc_emitter) +slicc_builder = Builder(action=MakeAction(slicc_action, Transform("SLICC")), + emitter=slicc_emitter) protocol = env['PROTOCOL'] sources = [ protocol_dir.File("RubySlicc_interfaces.slicc"), diff --git a/src/mem/slicc/ast/AST.py b/src/mem/slicc/ast/AST.py index d098c8642..b74867114 100644 --- a/src/mem/slicc/ast/AST.py +++ b/src/mem/slicc/ast/AST.py @@ -30,7 +30,7 @@ from slicc.util import PairContainer, Location class AST(PairContainer): def __init__(self, slicc, pairs=None): self.slicc = slicc - self.location = Location(slicc.current_source, slicc.current_line) + self.location = slicc.currentLocation() self.pairs = {} if pairs: self.pairs.update(getattr(pairs, "pairs", pairs)) diff --git a/src/mem/slicc/main.py b/src/mem/slicc/main.py index f8efcc323..15eb9d4be 100644 --- a/src/mem/slicc/main.py +++ b/src/mem/slicc/main.py @@ -60,6 +60,8 @@ def main(args=None): help="Path where html output goes") parser.add_option("-F", "--print-files", help="Print files that SLICC will generate") + parser.add_option("--tb", "--traceback", action='store_true', + help="print traceback on error") parser.add_option("-q", "--quiet", help="don't print messages") opts,files = parser.parse_args(args=args) @@ -71,30 +73,26 @@ def main(args=None): output = nprint if opts.quiet else eprint output("SLICC v0.4") - slicc = SLICC(debug=opts.debug) - output("Parsing...") - for filename in slicc.load(files, verbose=True): - output(" %s", filename) + + slicc = SLICC(debug=opts.debug) + slicc.load(files) if opts.print_files: for i in sorted(slicc.files()): print ' %s' % i else: - output("Generator pass 1...") - slicc.findMachines() + output("Processing AST...") + slicc.process() - output("Generator pass 2...") - slicc.generate() - - output("Generating C++ files...") + output("Writing C++ files...") slicc.writeCodeFiles(opts.code_path) if opts.html_path: - nprint("Writing HTML files...") + output("Writing HTML files...") slicc.writeHTMLFiles(opts.html_path) - eprint("SLICC is Done.") + output("SLICC is Done.") if __name__ == "__main__": main() diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py index eb10c2dc4..596b89f64 100644 --- a/src/mem/slicc/parser.py +++ b/src/mem/slicc/parser.py @@ -51,11 +51,16 @@ def read_slicc(sources): yield sm_file class SLICC(Grammar): - def __init__(self, protocol, **kwargs): + def __init__(self, protocol, verbose=False): self.decl_list_vec = [] self.protocol = protocol + self.verbose = verbose self.symtab = SymbolTable(self) + 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 @@ -68,7 +73,7 @@ class SLICC(Grammar): sys.exit(str(e)) self.decl_list_vec.append(decl_list) - def _load(self, *filenames): + def load(self, filenames): filenames = list(filenames) while filenames: f = filenames.pop(0) @@ -76,7 +81,6 @@ class SLICC(Grammar): 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) \ @@ -85,34 +89,18 @@ class SLICC(Grammar): 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): + def process(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 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([ diff --git a/src/mem/slicc/symbols/SymbolTable.py b/src/mem/slicc/symbols/SymbolTable.py index dd45ac06c..81d0768f9 100644 --- a/src/mem/slicc/symbols/SymbolTable.py +++ b/src/mem/slicc/symbols/SymbolTable.py @@ -25,7 +25,7 @@ # (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 m5.util import code_formatter +from m5.util import makeDir from slicc.generate import html from slicc.symbols.StateMachine import StateMachine @@ -42,13 +42,15 @@ class SymbolTable(object): pairs = {} pairs["enumeration"] = "yes" - MachineType = Type(self, "MachineType", Location("init", 0), pairs) + location = Location("init", 0, no_warning=not slicc.verbose) + MachineType = Type(self, "MachineType", location, pairs) self.newSymbol(MachineType) pairs = {} pairs["primitive"] = "yes" pairs["external"] = "yes" - void = Type(self, "void", Location("init", 0), pairs) + location = Location("init", 0, no_warning=not slicc.verbose) + void = Type(self, "void", location, pairs) self.newSymbol(void) def __repr__(self): @@ -123,6 +125,8 @@ class SymbolTable(object): yield symbol def writeCodeFiles(self, path): + makeDir(path) + code = self.codeFormatter() code(''' /** Auto generated C++ code started by $__file__:$__line__ */ @@ -139,6 +143,8 @@ class SymbolTable(object): symbol.writeCodeFiles(path) def writeHTMLFiles(self, path): + makeDir(path) + machines = list(self.getAllType(StateMachine)) if len(machines) > 1: name = "%s_table.html" % machines[0].ident diff --git a/src/mem/slicc/util.py b/src/mem/slicc/util.py index abadc3e30..83badf46d 100644 --- a/src/mem/slicc/util.py +++ b/src/mem/slicc/util.py @@ -27,13 +27,6 @@ import os import sys -def makeDir(path): - if os.path.exists(path): - if not os.path.isdir(path): - raise AttributeError, "%s exists but is not directory" % path - else: - os.mkdir(path) - class PairContainer(object): def __init__(self, pairs=None): self.pairs = {} @@ -53,14 +46,23 @@ class PairContainer(object): return self.pairs.get(item, failobj) class Location(object): - def __init__(self, filename, lineno): + def __init__(self, filename, lineno, no_warning=False): + if not isinstance(filename, basestring): + raise AttributeError, \ + "filename must be a string, found '%s'" % (type(filename), ) + if not isinstance(lineno, (int, long)): + raise AttributeError, \ + "filename must be an integer, found '%s'" % (type(lineno), ) self.filename = filename self.lineno = lineno + self.no_warning = no_warning def __str__(self): return '%s:%d' % (os.path.basename(self.filename), self.lineno) def warning(self, message, *args): + if self.no_warning: + return if args: message = message % args #raise Exception, "%s: Warning: %s" % (self, message) @@ -72,4 +74,4 @@ class Location(object): raise Exception, "%s: Error: %s" % (self, message) sys.exit("\n%s: Error: %s" % (self, message)) -__all__ = [ 'makeDir', 'PairContainer', 'Location' ] +__all__ = [ 'PairContainer', 'Location' ] diff --git a/src/python/m5/util/__init__.py b/src/python/m5/util/__init__.py index 69f153bb4..591781977 100644 --- a/src/python/m5/util/__init__.py +++ b/src/python/m5/util/__init__.py @@ -176,3 +176,12 @@ def readCommand(cmd, **kwargs): raise return subp.communicate()[0] + +def makeDir(path): + """Make a directory if it doesn't exist. If the path does exist, + ensure that it is a directory""" + if os.path.exists(path): + if not os.path.isdir(path): + raise AttributeError, "%s exists but is not directory" % path + else: + os.mkdir(path)