[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: toLua 4.0a improvements
- From: "Nick Trout" <nick@...>
- Date: Wed, 2 May 2001 18:03:50 +0100
>>I'm attaching my toLuaFrontend perl script (for reals this time - last
time
I forgot to actually attach it). Let me know if you find it useful.
Well I may well attach mine in Python :-)
Access is set using comments: eg. // "public" or // "private" . You should
include "lua" in the first comment of any files wanting to be scanned eg. /*
"lua" */
Nick
# Generate a Lua interface for a given application
# We'll do this automatically as keeping the interface files up to date in
# a rapidly changing project could be a bind.
# - Nick -
"""
$Log: /Tools/build/genpkg.py $
*
* 9 14/12/00 15:23 Nick
* include inheritance as toLua can do this ie. widgets need it!
*
* 8 7/12/00 16:13 Nick
* stopped repetition of single lines
*
* 6 7/12/00 15:23 Nick
* commands now "public" and "private" classes set default access using
* these
*
* 5 30/11/00 13:47 Nick
* Uses "keyword" format. Big speed increase as we only scan files with
* "lua" in the header comment.
"""
import string,sys,re,os
class Parser:
# get comment - we are looking for "lua"
re_lua = re.compile("""
\s*? # spaces?
/\* # /* start of comment block
(.*?) # comment contents
\*/ # */ end of comment
""",re.VERBOSE | re.DOTALL)
# one line comments containing // "commands"
re_line = re.compile("""
\s*
(.*?) # anything
// # // line comment
\s* # spaces
"(\w+)" # word in brackets
\s*? # spaces?
(.*) # rest of line
$ # end of the line
""",re.VERBOSE)
# block comments containing 1st word /* "command" ... */
re_comment_cmd = re.compile("""
/\*\s+ # /*
"(\w+)" # "keyword"
\s+ # space
(.+?) # rest of contents of comment
(\*/) # */
""", re.VERBOSE | re.DOTALL)
def __init__(self):
self.includes = None
self.luacode = []
self.interface = []
self.textsize,self.nbfiles = 0,0
self.scannedsize,self.scannedfiles = 0,0
def ScanDir(self,arg,dirname,names):
# callback from walk to scan given directory and list of names
print 'Directory:',dirname,':'
size = 0
for n in names:
if n[-2:]=='.h' or n[-4:]=='.cpp':
fname = os.path.join(dirname,n)
print '%19s' % n,
try:
f = open(fname,'rt')
except IOError:
print 'Couldnt open',fname
sys.exit(-1)
txt = f.read()
self.textsize += len(txt)
self.nbfiles += 1
f.close()
hdr = Parser.re_lua.match(txt)
if hdr:
if hdr.group(1).find('"lua"')>0:
# we found "lua" in the file header comment
self.scannedfiles += 1
self.scannedsize += len(txt)
self.FindLineComments(txt)
self.FindCommentCommands(txt)
print
def FindLineComments(self,txt):
# find //"command" comments
bInClass,bClassPublic,bClassAccess = 0,0,0
bPublic = 0
for line in txt.split('\n'):
bTempPublic = 0
# removed any ..EXPORT declarations
if line.find('EXPORT')>-1:
wds = string.split(line)
if wds[1][-6:]=='EXPORT':
del wds[1]
line = string.join(wds)
# if we're in a class take not of access eg. public:
if bInClass:
# when we reach an access fn set appropriate access!
if ':' in line:
state = line[:line.index(':')]
if state=='public':
# set access to default public access of the class
bClassPublic = bClassAccess
elif state in ('private','protected'):
bClassPublic = 0
# look for: //"command"
cmnt = Parser.re_line.search(line)
if cmnt:
# found one
before,cmd,rest = cmnt.groups()
before.lstrip()
wds = string.split(line)
if cmd in ('public','private'):
# publish
if wds[0]=='class':
bInClass = 1
# set default access
bClassPublic = 0
bClassAccess = (cmd=='public')
name = wds[1]
self.interface.append('%s\n{' % before)
else:
# not a class
if before!='':
# just one line with stuff before the comment
# strip off xEXPORT if it exists
if cmd=='public':
# this is a single line // "public" comment
bTempPublic = 1
else:
if bInClass:
bClassPublic = (cmd=='public')
else:
bPublic = (cmd=='public')
else:
raise '\nUnrecognised command: %s\n%s' % (cmd,line)
if bInClass:
if len(line)>0 and line[0]=='}':
# we're at the end of a class def eg. };
bInClass = 0
self.interface.append('};\n\n')
elif bTempPublic or bClassPublic:
self.interface.append(line)
else:
if bTempPublic or bPublic:
self.interface.append(line)
def FindCommentCommands(self,txt):
# find the /* "command" */ type comments
p = 0
while p<len(txt):
inst = Parser.re_comment_cmd.search(txt,p)
if not inst:
break # no more
p = inst.end(3)+1
keyword,code,cmnt = inst.groups()
if keyword=='pkg':
self.interface.append(code)
elif keyword=='lua':
self.luacode.append(code)
elif keyword=='includes':
assert not self.includes,'Includes already set!'
self.includes = code
else:
raise '\nUnrecognised keyword: %s' % keyword
def Write(self,pkg,codefile=None):
# Write out the pkg file
try:
f = open(pkg,'wt')
except IOError:
print 'Cannot open .pkg to write:',pkg
sys.exit(-1)
f.write('\n// This file was automatically generated by genpkg.py\n')
f.write('// Any editing of this file will be lost! (Nick)\n\n')
f.write('// includes for wrapper code :-\n\n')
if self.includes:
f.write(self.includes)
else:
f.write('// No include files specified\n')
if codefile:
self.WriteCode(codefile)
else:
f.write('\n\n// Embedded Lua code :-\n\n')
for i in self.luacode:
f.write('$[\n%s\n$]' % i)
f.write('\n')
f.write('\n\n// C++ wrapper :-\n\n')
for i in self.interface:
f.write(i)
f.write('\n')
f.close()
if self.includes:
print 'Nb includes:',len(self.includes)
print 'Nb Lua code items:',len(self.luacode)
print 'Nb interface items:',len(self.interface)
print 'Nb "lua" files scanned: %d of %d (%.1f%%)' % \
(self.scannedfiles,self.nbfiles,
100.0*self.scannedfiles/self.nbfiles)
print 'Amount of text scanned: %d bytes of %d (%.1f%%)' % \
(self.scannedsize,self.textsize,
100.0*self.scannedsize/self.textsize)
def WriteCode(self,fname):
try:
f = open(fname,'wt')
except IOError:
print 'Error: Could not open',fname
sys.exit(-1)
f.write('-- This Lua file was automatically generated with output\n')
f.write('-- from gpkg. Dont bother editing it!\n\n')
for i in self.luacode:
f.write(i)
f.write('\n')
f.close()
print 'Core written to:',fname
def Scan(pkg,dirs,codefile=None):
if not pkg:
print 'No .pkg (destination) file given.'
sys.exit(-1)
if not dirs:
print 'No scan directories given'
sys.exit(-1)
pars = Parser()
print '='*79
for d in dirs:
os.path.walk(d,pars.ScanDir,None)
print '-'*79
pars.Write(pkg,codefile)
print 'Written:',pkg
def Usage():
# Note this python script is called using the batch file gpkg.bat
print 'gpkg [-code file] <destination.pkg> <source dir> [<source dir>...]'
print ' -code sends any Lua code to a file'
print ' eg. gpkg w:/blah/hat.pkg w:/up/down w:/hatstand'
print
sys.exit(0)
if __name__=='__main__':
args = sys.argv[1:]
if len(args)<2:
print 'Error: No arguments\n'
Usage()
codefile=None
if args[0]=='-code':
codefile=args[1]
args=args[2:]
pkg = args[0]
dirs = args[1:]
Scan(pkg,dirs,codefile)