slicc: cleanup slicc code and make it less verbose
This commit is contained in:
parent
3d252f8e5f
commit
831e9b3b7a
7 changed files with 73 additions and 108 deletions
|
@ -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"),
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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([
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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' ]
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue