Code cleanup in pybison's python file.

parent 858c8461
...@@ -19,17 +19,21 @@ If you wish to use this software in a commercial application, ...@@ -19,17 +19,21 @@ If you wish to use this software in a commercial application,
and wish to depart from the GPL licensing requirements, and wish to depart from the GPL licensing requirements,
please contact the author and apply for a commercial license. please contact the author and apply for a commercial license.
""" """
#@+others import sys
#@+node:imports import os
import sys, os, sha, re, imp, traceback, xml.dom, xml.dom.minidom, types import sha
import re
import imp
import traceback
import xml.dom
import xml.dom.minidom
import types
import distutils.sysconfig import distutils.sysconfig
import distutils.ccompiler import distutils.ccompiler
from bison_ import ParserEngine, unquoted from bison_ import ParserEngine, unquoted
#@-node:imports reSpaces = re.compile('\\s+')
#@+node:globals
reSpaces = re.compile("\\s+")
class ParserSyntaxError(Exception): class ParserSyntaxError(Exception):
...@@ -48,7 +52,7 @@ class BisonError: ...@@ -48,7 +52,7 @@ class BisonError:
""" """
_pyBisonError = 1 _pyBisonError = 1
def __init__(self, value="syntax error"): def __init__(self, value='syntax error'):
self.value = value self.value = value
...@@ -81,7 +85,7 @@ class BisonNode: ...@@ -81,7 +85,7 @@ class BisonNode:
self.kw = kw self.kw = kw
def __str__(self): def __str__(self):
return "<BisonNode:%s>" % self.target return '<BisonNode:%s>' % self.target
def __repr__(self): def __repr__(self):
return str(self) return str(self)
...@@ -105,7 +109,8 @@ class BisonNode: ...@@ -105,7 +109,8 @@ class BisonNode:
return self return self
return self.values[item[0]][item[1:]] return self.values[item[0]][item[1:]]
else: else:
raise TypeError("Can only index %s objects with an int or a list/tuple" % self.__class.__name__) raise TypeError('Can only index %s objects with an int or a'
' list/tuple' % self.__class.__name__)
def __len__(self): def __len__(self):
...@@ -122,17 +127,18 @@ class BisonNode: ...@@ -122,17 +127,18 @@ class BisonNode:
For debugging - prints a recursive dump of a parse tree node and its children For debugging - prints a recursive dump of a parse tree node and its children
""" """
specialAttribs = ['option', 'target', 'names', 'values'] specialAttribs = ['option', 'target', 'names', 'values']
indents = " " * indent * 2 indents = ' ' * indent * 2
#print "%s%s: %s %s" % (indents, self.target, self.option, self.names) #print "%s%s: %s %s" % (indents, self.target, self.option, self.names)
print "%s%s:" % (indents, self.target) print '%s%s:' % (indents, self.target)
for name, val in self.kw.items() + zip(self.names, self.values): for name, val in self.kw.items() + zip(self.names, self.values):
if name in specialAttribs or name.startswith("_"): if name in specialAttribs or name.startswith('_'):
continue continue
if isinstance(val, BisonNode): if isinstance(val, BisonNode):
val.dump(indent+1) val.dump(indent+1)
else: else:
print indents + " %s=%s" % (name, val) print indents + ' %s=%s' % (name, val)
def toxml(self): def toxml(self):
""" """
...@@ -145,7 +151,8 @@ class BisonNode: ...@@ -145,7 +151,8 @@ class BisonNode:
def toprettyxml(self, indent=' ', newl='\n', encoding=None): def toprettyxml(self, indent=' ', newl='\n', encoding=None):
""" """
returns a human-readable xml serialisation of this node and its children Returns a human-readable xml serialisation of this node and its
children.
""" """
return self.toxmldoc().toprettyxml(indent=indent, return self.toxmldoc().toprettyxml(indent=indent,
newl=newl, newl=newl,
...@@ -153,7 +160,8 @@ class BisonNode: ...@@ -153,7 +160,8 @@ class BisonNode:
def toxmldoc(self): def toxmldoc(self):
""" """
Returns the node and its children as an xml.dom.minidom.Document object Returns the node and its children as an xml.dom.minidom.Document
object.
""" """
d = xml.dom.minidom.Document() d = xml.dom.minidom.Document()
d.appendChild(self.toxmlelem(d)) d.appendChild(self.toxmlelem(d))
...@@ -161,7 +169,7 @@ class BisonNode: ...@@ -161,7 +169,7 @@ class BisonNode:
def toxmlelem(self, docobj): def toxmlelem(self, docobj):
""" """
Returns a DOM Element object of this node and its children Returns a DOM Element object of this node and its children.
""" """
specialAttribs = ['option', 'target', 'names', 'values'] specialAttribs = ['option', 'target', 'names', 'values']
...@@ -170,16 +178,18 @@ class BisonNode: ...@@ -170,16 +178,18 @@ class BisonNode:
# set attribs # set attribs
for name, val in self.kw.items(): for name, val in self.kw.items():
if name in ['names', 'values'] or name.startswith("_"): if name in ['names', 'values'] or name.startswith('_'):
continue continue
x.setAttribute(name, str(val)) x.setAttribute(name, str(val))
#x.setAttribute('target', self.target) #x.setAttribute('target', self.target)
#x.setAttribute('option', self.option) #x.setAttribute('option', self.option)
# and add the children # and add the children
for name, val in zip(self.names, self.values): for name, val in zip(self.names, self.values):
if name in specialAttribs or name.startswith("_"): if name in specialAttribs or name.startswith('_'):
continue continue
if isinstance(val, BisonNode): if isinstance(val, BisonNode):
x.appendChild(val.toxmlelem(docobj)) x.appendChild(val.toxmlelem(docobj))
else: else:
...@@ -205,20 +215,20 @@ class BisonParser(object): ...@@ -205,20 +215,20 @@ class BisonParser(object):
# override these if you need to # override these if you need to
# command and options for running yacc/bison, except for filename arg # command and options for running yacc/bison, except for filename arg
bisonCmd = ["bison", "-d", "-v", '-t'] bisonCmd = ['bison', '-d', '-v', '-t']
bisonFile = "tmp.y" bisonFile = 'tmp.y'
bisonCFile = "tmp.tab.c" bisonCFile = 'tmp.tab.c'
bisonHFile = "tmp.tab.h" # name of header file generated by bison cmd bisonHFile = 'tmp.tab.h' # name of header file generated by bison cmd
bisonCFile1 = "tmp.bison.c" # c output file from bison gets renamed to this bisonCFile1 = 'tmp.bison.c' # c output file from bison gets renamed to this
bisonHFile1 = "tokens.h" # bison-generated header file gets renamed to this bisonHFile1 = 'tokens.h' # bison-generated header file gets renamed to this
flexCmd = ["flex", ] # command and options for running [f]lex, except for filename arg flexCmd = ['flex', ] # command and options for running [f]lex, except for filename arg
flexFile = "tmp.l" flexFile = 'tmp.l'
flexCFile = "lex.yy.c" flexCFile = 'lex.yy.c'
flexCFile1 = "tmp.lex.c" # c output file from lex gets renamed to this flexCFile1 = 'tmp.lex.c' # c output file from lex gets renamed to this
cflags_pre = ['-fPIC'] # = CFLAGS added before all arguments. cflags_pre = ['-fPIC'] # = CFLAGS added before all arguments.
cflags_post = ['-O3','-g'] # = CFLAGS added after all arguments. cflags_post = ['-O3','-g'] # = CFLAGS added after all arguments.
...@@ -266,11 +276,11 @@ class BisonParser(object): ...@@ -266,11 +276,11 @@ class BisonParser(object):
fileobj = kw.get('file', None) fileobj = kw.get('file', None)
if fileobj: if fileobj:
if type(fileobj) == type(""): if isinstance(fileobj, str):
try: try:
fileobj = open(fileobj, "rb") fileobj = open(fileobj, 'rb')
except: except:
raise Exception("Cannot open input file %s" % fileobj) raise Exception('Cannot open input file %s' % fileobj)
self.file = fileobj self.file = fileobj
else: else:
self.file = sys.stdin self.file = sys.stdin
...@@ -286,7 +296,7 @@ class BisonParser(object): ...@@ -286,7 +296,7 @@ class BisonParser(object):
# if engine lib name not declared, invent ont # if engine lib name not declared, invent ont
if not self.bisonEngineLibName: if not self.bisonEngineLibName:
self.bisonEngineLibName = self.__class__.__module__ + "-parser" self.bisonEngineLibName = self.__class__.__module__ + '-parser'
# get an engine # get an engine
self.engine = ParserEngine(self) self.engine = ParserEngine(self)
...@@ -320,7 +330,7 @@ class BisonParser(object): ...@@ -320,7 +330,7 @@ class BisonParser(object):
# % (targetname, repr(self.last)) # % (targetname, repr(self.last))
else: else:
if self.verbose: if self.verbose:
print "no handler for %s, using default" % targetname print 'no handler for %s, using default' % targetname
self.last = BisonNode(targetname, option=option, names=names, values=values) self.last = BisonNode(targetname, option=option, names=names, values=values)
# reset any resulting errors (assume they've been handled) # reset any resulting errors (assume they've been handled)
...@@ -342,16 +352,16 @@ class BisonParser(object): ...@@ -342,16 +352,16 @@ class BisonParser(object):
- debug - enables garrulous parser debugging output, default 0 - debug - enables garrulous parser debugging output, default 0
""" """
if self.verbose: if self.verbose:
print "Parser.run: calling engine" print 'Parser.run: calling engine'
# grab keywords # grab keywords
fileobj = kw.get('file', self.file) fileobj = kw.get('file', self.file)
if type(fileobj) == type(""): if isinstance(fileobj, str):
filename = fileobj filename = fileobj
try: try:
fileobj = open(fileobj, "rb") fileobj = open(fileobj, 'rb')
except: except:
raise Exception("Cannot open input file %s" % fileobj) raise Exception('Cannot open input file "%s"' % fileobj)
else: else:
filename = None filename = None
fileobj = None fileobj = None
...@@ -375,18 +385,20 @@ class BisonParser(object): ...@@ -375,18 +385,20 @@ class BisonParser(object):
self.engine.runEngine(debug) self.engine.runEngine(debug)
if self.lasterror: if self.lasterror:
#print "Got error: %s" % repr(self.error)
if filename != None: if filename != None:
raise ParserSyntaxError("%s:%d: '%s' near '%s'" % ((filename,) + self.lasterror)) raise ParserSyntaxError('%s:%d: "%s" near "%s"'
% ((filename,) + self.lasterror))
else: else:
raise ParserSyntaxError("Line %d: '%s' near '%s'" % self.lasterror) raise ParserSyntaxError('Line %d: "%s" near "%s"'
% self.lasterror)
# restore old values # restore old values
self.file = oldfile self.file = oldfile
self.read = oldread self.read = oldread
if self.verbose: if self.verbose:
print "Parser.run: back from engine" print 'Parser.run: back from engine'
return self.last return self.last
def read(self, nbytes): def read(self, nbytes):
...@@ -400,15 +412,19 @@ class BisonParser(object): ...@@ -400,15 +412,19 @@ class BisonParser(object):
""" """
# default to stdin # default to stdin
if self.verbose: if self.verbose:
print "Parser.read: want %s bytes" % nbytes print 'Parser.read: want %s bytes' % nbytes
bytes = self.file.readline(nbytes) bytes = self.file.readline(nbytes)
if self.verbose: if self.verbose:
print "Parser.read: got %s bytes" % len(bytes) print 'Parser.read: got %s bytes' % len(bytes)
return bytes return bytes
def _error(self, linenum, msg, tok): def _error(self, linenum, msg, tok):
print "Parser: line %s: syntax error '%s' before '%s'" % (linenum, msg, tok) print 'Parser: line %s: syntax error "%s" before "%s"' \
% (linenum, msg, tok)
def error(self, value): def error(self, value):
""" """
...@@ -484,15 +500,15 @@ class BisonParser(object): ...@@ -484,15 +500,15 @@ class BisonParser(object):
namespace = globals() namespace = globals()
objname = xmlobj.tagName objname = xmlobj.tagName
classname = objname + "_Node" classname = objname + '_Node'
classobj = namespace.get(classname, None) classobj = namespace.get(classname, None)
namespacekeys = namespace.keys() namespacekeys = namespace.keys()
# barf if node is not a known parse node or token # barf if node is not a known parse node or token
if (not classobj) and objname not in self.tokens: if (not classobj) and objname not in self.tokens:
raise Exception("Cannot reconstitute %s: can't find required node class or token %s" % ( raise Exception('Cannot reconstitute %s: can\'t find required'
objname, classname)) ' node class or token %s' % (objname, classname))
if classobj: if classobj:
nodeobj = classobj() nodeobj = classobj()
...@@ -500,28 +516,27 @@ class BisonParser(object): ...@@ -500,28 +516,27 @@ class BisonParser(object):
# add the attribs # add the attribs
for k,v in xmlobj.attributes.items(): for k,v in xmlobj.attributes.items():
setattr(nodeobj, k, v) setattr(nodeobj, k, v)
else: else:
nodeobj = None nodeobj = None
#print "----------------" #print '----------------'
#print "objname=%s" % repr(objname) #print 'objname=%s' % repr(objname)
#print "classname=%s" % repr(classname) #print 'classname=%s' % repr(classname)
#print "classobj=%s" % repr(classobj) #print 'classobj=%s' % repr(classobj)
#print "nodeobj=%s" % repr(nodeobj) #print 'nodeobj=%s' % repr(nodeobj)
# now add the children # now add the children
for child in xmlobj.childNodes: for child in xmlobj.childNodes:
#print "%s attributes=%s" % (child, child.attributes.items()) #print '%s attributes=%s' % (child, child.attributes.items())
childname = child.attributes['target'].value childname = child.attributes['target'].value
#print "childname=%s" % childname #print 'childname=%s' % childname
if childname + "_Node" in namespacekeys: if childname + '_Node' in namespacekeys:
#print "we have a node for class %s" % classname #print 'we have a node for class %s' % classname
childobj = self.loadxmlobj(child, namespace) childobj = self.loadxmlobj(child, namespace)
else: else:
# it's a token # it's a token
childobj = child.childNodes[0].nodeValue childobj = child.childNodes[0].nodeValue
#print "got token %s=%s" % (childname, childobj) #print 'got token %s=%s' % (childname, childobj)
nodeobj.names.append(childname) nodeobj.names.append(childname)
nodeobj.values.append(childobj) nodeobj.values.append(childobj)
...@@ -533,10 +548,9 @@ class BisonParser(object): ...@@ -533,10 +548,9 @@ class BisonParser(object):
def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
""" """
Rips the rules, tokens and precedences from a bison file, and the Rips the rules, tokens and precedences from a bison file, and the verbatim
verbatim text from a lex file and generates text from a lex file and generates a boilerplate python file containing a
a boilerplate python file containing a Parser class with handler Parser class with handler methods and grammar attributes.
methods and grammar attributes
Arguments: Arguments:
- bisonfileName - name of input bison script - bisonfileName - name of input bison script
...@@ -544,56 +558,60 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -544,56 +558,60 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
- pyfileName - name of output python file - pyfileName - name of output python file
- generateClasses - flag - default 0 - if 1, causes a unique class to - generateClasses - flag - default 0 - if 1, causes a unique class to
be defined for each parse target, and for the corresponding target be defined for each parse target, and for the corresponding target
handler method in the main Parser class to use this class when creating handler method in the main Parser class to use this class when
the node. creating the node.
""" """
# try to create output file # try to create output file
try: try:
pyfile = file(pyfileName, "w") pyfile = file(pyfileName, 'w')
except: except:
raise Exception("Cannot create output file '%s'" % pyfileName) raise Exception('Cannot create output file "%s"' % pyfileName)
# try to open/read the bison file # try to open/read the bison file
try: try:
rawBison = file(bisonfileName).read() rawBison = file(bisonfileName).read()
except: except:
raise Exception("Cannot open bison file %s" % bisonfileName) raise Exception('Cannot open bison file "%s"' % bisonfileName)
# try to open/read the lex file # try to open/read the lex file
try: try:
rawLex = file(lexfileName).read() rawLex = file(lexfileName).read()
except: except:
raise Exception("Cannot open lex file %s" % lexfileName) raise Exception('Cannot open lex file %s' % lexfileName)
# break up into the three '%%'-separated sections # break up into the three '%%'-separated sections
try: try:
prologue, rulesRaw, epilogue = rawBison.split("\n%%\n") prologue, rulesRaw, epilogue = rawBison.split('\n%%\n')
except: except:
raise Exception( raise Exception(
"File %s is not a properly formatted bison file" 'File %s is not a properly formatted bison file'
" (needs 3 sections separated by %%%%" % (bisonfileName) ' (needs 3 sections separated by %%%%' % (bisonfileName)
) )
# -------------------------------------- # --------------------------------------
# process prologue # process prologue
prologue = prologue.split("%}")[-1].strip() # ditch the C code prologue = prologue.split('%}')[-1].strip() # ditch the C code
prologue = re.sub("\\n([\t ]+)", " ", prologue) # join broken lines prologue = re.sub('\\n([\t ]+)', ' ', prologue) # join broken lines
#prologueLines = [line.strip() for line in prologue.split("\n")] #prologueLines = [line.strip() for line in prologue.split('\n')]
lines = prologue.split("\n") lines = prologue.split('\n')
tmp = [] tmp = []
for line in lines: for line in lines:
tmp.append(line.strip()) tmp.append(line.strip())
prologueLines = tmp prologueLines = tmp
prologueLines = filter(None, prologueLines) prologueLines = filter(None, prologueLines)
tokens = [] tokens = []
precRules = [] precRules = []
for line in prologueLines: for line in prologueLines:
words = reSpaces.split(line) words = reSpaces.split(line)
kwd = words[0] kwd = words[0]
args = words[1:] args = words[1:]
if kwd == '%token': if kwd == '%token':
tokens.extend(args) tokens.extend(args)
elif kwd in ['%left', '%right', '%nonassoc']: elif kwd in ['%left', '%right', '%nonassoc']:
...@@ -603,37 +621,29 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -603,37 +621,29 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
# ------------------------------------------------------------- # -------------------------------------------------------------
# process rules # process rules
rulesRaw = re.sub("\\n([\t ]+)", " ", rulesRaw) # join broken lines rulesRaw = re.sub('\\n([\t ]+)', ' ', rulesRaw) # join broken lines
rulesLines = filter('', map(str.strip, re.split(unquoted % ';', rulesRaw)))
#rulesLines = filter(None, [r.strip() for r in rulesRaw.split(";")])
rulesLines = []
#for r in rulesRaw.split(";"):
for r in re.split(unquoted % ";", rulesRaw):
r = r.strip()
if r:
rulesLines.append(r)
rules = [] rules = []
for rule in rulesLines: for rule in rulesLines:
#print "--" #print '--'
#print repr(rule) #print repr(rule)
#tgt, terms = rule.split(":") #tgt, terms = rule.split(':')
try: try:
tgt, terms = re.split(unquoted % ":", rule) tgt, terms = re.split(unquoted % ':', rule)
except ValueError: except ValueError:
print "Error in rule: %s" % rule print 'Error in rule: %s' % rule
raise raise
tgt, terms = tgt.strip(), terms.strip() tgt, terms = tgt.strip(), terms.strip()
#terms = [t.strip() for t in terms.split("|")] #terms = [t.strip() for t in terms.split('|')]
#terms = [reSpaces.split(t) for t in terms] #terms = [reSpaces.split(t) for t in terms]
tmp = [] tmp = []
#for t in terms.split("|"): #for t in terms.split('|'):
for t in re.split(unquoted % r"\|", terms): for t in re.split(unquoted % r'\|', terms):
t = t.strip() t = t.strip()
tmp.append(reSpaces.split(t)) tmp.append(reSpaces.split(t))
...@@ -642,7 +652,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -642,7 +652,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
rules.append((tgt, terms)) rules.append((tgt, terms))
# now we have our rulebase, we can churn out our skeleton Python file # now we have our rulebase, we can churn out our skeleton Python file
pyfile.write("\n".join([ pyfile.write('\n'.join([
'#!/usr/bin/env python', '#!/usr/bin/env python',
'', '',
'"""', '"""',
...@@ -654,8 +664,8 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -654,8 +664,8 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
'', '',
'from bison import BisonParser, BisonNode, BisonError', 'from bison import BisonParser, BisonNode, BisonError',
'', '',
'bisonFile = "%s" # original bison file' % bisonfileName, 'bisonFile = \'%s\' # original bison file' % bisonfileName,
'lexFile = "%s" # original flex file' % lexfileName, 'lexFile = \'%s\' # original flex file' % lexfileName,
'\n', '\n',
])) ]))
...@@ -674,7 +684,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -674,7 +684,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
'', '',
' def __str__(self):', ' def __str__(self):',
' """Customise as needed"""', ' """Customise as needed"""',
' return "<%s instance at 0x%x>" % (self.__class__.__name__, hash(self))', ' return \'<%s instance at 0x%x>\' % (self.__class__.__name__, hash(self))',
'', '',
' def __repr__(self):', ' def __repr__(self):',
' """Customise as needed"""', ' """Customise as needed"""',
...@@ -695,9 +705,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -695,9 +705,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
# now spit out class decs for every parse target # now spit out class decs for every parse target
for target, options in rules: for target, options in rules:
tmp = [] tmp = map(' '.join, options)
for t in options:
tmp.append(" ".join(t))
# totally self-indulgent grammatical pedantry # totally self-indulgent grammatical pedantry
if target[0].lower() in ['a','e','i','o','u']: if target[0].lower() in ['a','e','i','o','u']:
...@@ -720,7 +728,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -720,7 +728,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
# start churning out the class dec # start churning out the class dec
pyfile.write("\n".join([ pyfile.write('\n'.join([
'class Parser(BisonParser):', 'class Parser(BisonParser):',
' """', ' """',
' bison Parser class generated automatically by bison2py from the', ' bison Parser class generated automatically by bison2py from the',
...@@ -740,7 +748,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -740,7 +748,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
# add the default node class # add the default node class
if not generateClasses: if not generateClasses:
pyfile.write("\n".join([ pyfile.write('\n'.join([
' # -------------------------------------------------', ' # -------------------------------------------------',
' # Default class to use for creating new parse nodes', ' # Default class to use for creating new parse nodes',
' # -------------------------------------------------', ' # -------------------------------------------------',
...@@ -749,22 +757,21 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -749,22 +757,21 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
])) ]))
# add the name of the dynamic library we need # add the name of the dynamic library we need
libfileName = os.path.splitext(os.path.split(pyfileName)[1])[0] + "-engine" libfileName = os.path.splitext(os.path.split(pyfileName)[1])[0] \
pyfile.write("\n".join([ + '-engine'
pyfile.write('\n'.join([
' # --------------------------------------------', ' # --------------------------------------------',
' # basename of binary parser engine dynamic lib', ' # basename of binary parser engine dynamic lib',
' # --------------------------------------------', ' # --------------------------------------------',
' bisonEngineLibName = "%s"' % (parser.buildDirectory + libfileName), ' bisonEngineLibName = \'%s\'' % (parser.buildDirectory + libfileName),
'\n', '\n',
])) ]))
# add the tokens # add the tokens
#pyfile.write(' tokens = (%s,)\n\n' % ", ".join(['"%s"' % t for t in tokens])) #pyfile.write(' tokens = (%s,)\n\n' % ', '.join([''%s'' % t for t in tokens]))
tmp = [] toks = ', '.join(tokens)
for t in tokens:
#tmp.append('"'+t+'"')
tmp.append(t)
toks = ", ".join(tmp)
pyfile.write(' # ----------------------------------------------------------------\n') pyfile.write(' # ----------------------------------------------------------------\n')
pyfile.write(' # lexer tokens - these must match those in your lex script (below)\n') pyfile.write(' # lexer tokens - these must match those in your lex script (below)\n')
pyfile.write(' # ----------------------------------------------------------------\n') pyfile.write(' # ----------------------------------------------------------------\n')
...@@ -776,59 +783,52 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -776,59 +783,52 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
pyfile.write(' # ------------------------------\n') pyfile.write(' # ------------------------------\n')
pyfile.write(' precedences = (\n') pyfile.write(' precedences = (\n')
for prec in precRules: for prec in precRules:
tmp = [] precline = ', '.join(prec[1])
for p in prec[1]: pyfile.write(' (\'%s\', %s,),\n' % (
#tmp.append('"'+p+'"')
tmp.append(p)
precline = ", ".join(tmp)
#pyfile.write(' ("%s", (%s,)),\n' % (
pyfile.write(' ("%s", %s,),\n' % (
prec[0][1:], # left/right/nonassoc, quote-wrapped, no '%s' prec[0][1:], # left/right/nonassoc, quote-wrapped, no '%s'
tmp, # quote-wrapped targets tmp, # quote-wrapped targets
) )
) )
pyfile.write(' )\n\n'), pyfile.write(' )\n\n'),
pyfile.write("\n".join([ pyfile.write('\n'.join([
' # ---------------------------------------------------------------', ' # ---------------------------------------------------------------',
' # Declare the start target here (by name)', ' # Declare the start target here (by name)',
' # ---------------------------------------------------------------', ' # ---------------------------------------------------------------',
' start = "%s"' % startTarget, ' start = \'%s\'' % startTarget,
'\n', '\n',
])) ]))
# now the interesting bit - write the rule handler methods # now the interesting bit - write the rule handler methods
pyfile.write("\n".join([ pyfile.write('\n'.join([
' # ---------------------------------------------------------------', ' # ---------------------------------------------------------------',
' # These methods are the python handlers for the bison targets.', ' # These methods are the python handlers for the bison targets.',
' # (which get called by the bison code each time the corresponding', ' # (which get called by the bison code each time the corresponding',
' # parse target is unambiguously reached)', ' # parse target is unambiguously reached)',
' #', ' #',
" # WARNING - don't touch the method docstrings unless you know what", ' # WARNING - don\'t touch the method docstrings unless you know what',
" # you are doing - they are in bison rule syntax, and are passed", ' # you are doing - they are in bison rule syntax, and are passed',
" # verbatim to bison to build the parser engine library.", ' # verbatim to bison to build the parser engine library.',
' # ---------------------------------------------------------------', ' # ---------------------------------------------------------------',
'\n', '\n',
])) ]))
for target, options in rules: for target, options in rules:
tmp = [] tmp = map(' '.join, options)
for t in options:
tmp.append(" ".join(t))
if generateClasses: if generateClasses:
nodeClassName = target + "_Node" nodeClassName = target + '_Node'
else: else:
nodeClassName = 'self.defaultNodeClass' nodeClassName = 'self.defaultNodeClass'
pyfile.write("\n".join([ pyfile.write('\n'.join([
' def on_%s(self, target, option, names, values):' % target, ' def on_%s(self, target, option, names, values):' % target,
' """', ' """',
' %s' % target, ' %s' % target,
' : ' + "\n | ".join(tmp), ' : ' + '\n | '.join(tmp),
' """', ' """',
' return %s(' % nodeClassName, ' return %s(' % nodeClassName,
' target="%s",' % target, ' target=\'%s\',' % target,
' option=option,', ' option=option,',
' names=names,', ' names=names,',
' values=values)', ' values=values)',
...@@ -836,7 +836,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -836,7 +836,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
])) ]))
# now the ugly bit - add the raw lex script # now the ugly bit - add the raw lex script
pyfile.write("\n".join([ pyfile.write('\n'.join([
' # -----------------------------------------', ' # -----------------------------------------',
' # raw lex script, verbatim here', ' # raw lex script, verbatim here',
' # -----------------------------------------', ' # -----------------------------------------',
...@@ -851,14 +851,14 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -851,14 +851,14 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
])) ]))
# and now, create a main for testing which either reads stdin, or a filename arg # and now, create a main for testing which either reads stdin, or a filename arg
pyfile.write("\n".join([ pyfile.write('\n'.join([
'def usage():', 'def usage():',
' print "%s: PyBison parser derived from %s and %s" % (sys.argv[0], bisonFile, lexFile)', ' print \'%s: PyBison parser derived from %s and %s\' % (sys.argv[0], bisonFile, lexFile)',
' print "Usage: %s [-k] [-v] [-d] [filename]" % sys.argv[0]', ' print \'Usage: %s [-k] [-v] [-d] [filename]\' % sys.argv[0]',
' print " -k Keep temporary files used in building parse engine lib"', ' print \' -k Keep temporary files used in building parse engine lib\'',
' print " -v Enable verbose messages while parser is running"', ' print \' -v Enable verbose messages while parser is running\'',
' print " -d Enable garrulous debug messages from parser engine"', ' print \' -d Enable garrulous debug messages from parser engine\'',
' print " filename path of a file to parse, defaults to stdin"', ' print \' filename path of a file to parse, defaults to stdin\'',
'', '',
'def main(*args):', 'def main(*args):',
' """', ' """',
...@@ -870,21 +870,21 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -870,21 +870,21 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
' debug = 0', ' debug = 0',
' filename = None', ' filename = None',
'', '',
' for s in ["-h", "-help", "--h", "--help", "-?"]:', ' for s in [\'-h\', \'-help\', \'--h\', \'--help\', \'-?\']:',
' if s in args:', ' if s in args:',
' usage()', ' usage()',
' sys.exit(0)', ' sys.exit(0)',
'', '',
' if len(args) > 0:', ' if len(args) > 0:',
' if "-k" in args:', ' if \'-k\' in args:',
' keepfiles = 1', ' keepfiles = 1',
' args.remove("-k")', ' args.remove(\'-k\')',
' if "-v" in args:', ' if \'-v\' in args:',
' verbose = 1', ' verbose = 1',
' args.remove("-v")', ' args.remove(\'-v\')',
' if "-d" in args:', ' if \'-d\' in args:',
' debug = 1', ' debug = 1',
' args.remove("-d")', ' args.remove(\'-d\')',
' if len(args) > 0:', ' if len(args) > 0:',
' filename = args[0]', ' filename = args[0]',
'', '',
...@@ -892,7 +892,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0): ...@@ -892,7 +892,7 @@ def bisonToPython(bisonfileName, lexfileName, pyfileName, generateClasses=0):
' tree = p.run(file=filename, debug=debug)', ' tree = p.run(file=filename, debug=debug)',
' return tree', ' return tree',
'', '',
'if __name__ == "__main__":', 'if __name__ == \'__main__\':',
' main(*(sys.argv[1:]))', ' main(*(sys.argv[1:]))',
'', '',
'', '',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment