slicc: cleanup slicc code and make it less verbose

This commit is contained in:
Nathan Binkert 2011-07-05 18:30:05 -07:00
parent 3d252f8e5f
commit 831e9b3b7a
7 changed files with 73 additions and 108 deletions

View file

@ -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"),

View file

@ -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))

View file

@ -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()

View file

@ -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([

View file

@ -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

View file

@ -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' ]

View file

@ -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)