# 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']:
#
# 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
-
- 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)
+ 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([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)
-
- 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)
+ 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)
+
+slicc_builder = Builder(action=MakeAction(slicc_action, Transform("SLICC")),
+ emitter=slicc_emitter)
protocol = env['PROTOCOL']
sources = [ protocol_dir.File("RubySlicc_interfaces.slicc"),
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))
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)
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("Generator pass 2...")
- slicc.generate()
+ output("Processing AST...")
+ slicc.process()
- 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()
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
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)
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) \
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([
# (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
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):
yield symbol
def writeCodeFiles(self, path):
+ makeDir(path)
+
code = self.codeFormatter()
code('''
/** Auto generated C++ code started by $__file__:$__line__ */
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
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 = {}
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)
raise Exception, "%s: Error: %s" % (self, message)
sys.exit("\n%s: Error: %s" % (self, message))
-__all__ = [ 'makeDir', 'PairContainer', 'Location' ]
+__all__ = [ 'PairContainer', 'Location' ]
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)