Mailing List Archive

Xbase++ preprocessor implementation in Python
This is a multi-part message in MIME format.
--------------2ECC51789D473DB99ACE3D31
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit


Attached please find a Python implementation of the Xbase++
preprocessor. It
is not yet a totally perfect rendition, but it is pretty close. By
implication, it should also be a reasonable rendition of the Clipper
preprocessor (though I have not yet tested this).

Oh, and it is *dead slow*! - hundreds of times slower I think! This is
undoubtedly partly due to me being a Python newbie, and I would greatly
appreciate any tips on how I might speed it up a bit. Any tips on how
the code could be improved would be equally welcome, particularly any
Python idioms that I have obviously not yet groked. (Error handling for
example!!)

I could not figure out how to make either KJparsing or TRAP do what I
wanted,
and I haven't yet looked at John Aylcock's stuff (but I intend to!), so
the code is built from scratch around the re module. Any comments as to
the relative (de)merits of this approach are welcomed.

I would like eventually to make this available to the Clipper/Xbase++
community. But I want to present Python in the best possible light - so
I thought it best to first release it here in the hope that it might be
further refined first.

"Why write such a program?" I hear you ask! Several reasons :

- I needed a concrete project to help me get up to speed with Python.

- I want to translate some or all of my Clipper/Xbase++ source to
Python, and I'm hoping this will help (but I'm not quite sure how!).

- the Clipper/Xbase++ preprocessor had always been a bit of a mystery
to me, so I thought this might deepen my understanding of it a bit (it
has!).

- Ditto for regular expressions!

- I have taken the opportunity to make some "improvements". Some
patterns that do not successfully translate under Xbase++, but IMHO
should, do under PRGPP.

- There are some concerns in the Xbase++ community as to
incompatibilities between the Clipper and Xbase++ preprocessors.
Hopefully, this tool might serve to clarify and/or resolve such issues.

- Clipper and Xbase++ are only available on Window$ :-(

- I love programming, the open-source idea, Python and the
Clipper/Xbase++/VO
languages. I would like eventually to see an open-source implementation
of a
such a language. Nuff said.

many tias,

gary



--------------2ECC51789D473DB99ACE3D31
Content-Type: text/plain; charset=us-ascii;
name="prgpp.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="prgpp.py"

"""
PRGPP.py - a Python re-implementation of the Xbase++ (Clipper) preprocessor

Released to the public domain 2-Apr-1999,

Provided as-is; use at your own risk; no warranty; no promises; enjoy!

by Gary Stephenson (garys@magna.com.au)
(who is currently underemployed <g>)

"""

import re
import sys
import glob
import string

Identifier = re.compile(r"\s*([A-Za-z_]+[A-Za-z0-9_]*)")
NumLiteral = re.compile(r"\s*([0-9]+(\.[0-9]+)?)")
StringLiteral = re.compile(r"\s*('.*?'|\".*?\")")
LogLiteral = re.compile(r"\s*(\.f\.|\.t\.)",re.I )
Operator = re.compile(r"\s*(\+\+|\+=|\+|--|-=|->|-|\*\*|\*=|\*|/=|/|,|!|\||%|\.not\.|\.or\.|\.and\.|@|:=|:|==|=|>=|>|<=|<)",re.IGNORECASE)
BlockHeader = re.compile(r"\s*\{\s*\|.*\|" )
OpenBrackets = re.compile(r"\s*(\[|\(|{)")
CloseBrackets = re.compile(r"\s*(\]|\)|})")
eol = re.compile(r"\s*$")
comma = re.compile(r"\s*,")

defStmt = re.compile( r"#\s*define\s+(?P<name>\w+)(?P<aft>.*)?", re.IGNORECASE )
ifdef = re.compile( r"#\s*ifdef\s+(?P<name>\w+)", re.IGNORECASE )
ifndef = re.compile( r"#\s*ifndef\s+(?P<name>\w+)", re.IGNORECASE )
elsedef = re.compile( r"#\s*else\s*", re.IGNORECASE )
endif = re.compile( r"#\s*endif\s*", re.IGNORECASE )
include = re.compile( r"#\s*include\s+(?P<filename>.+)",re.IGNORECASE )
undef = re.compile( r"#\s*undef\s+(?P<name>\w+)", re.IGNORECASE )
cmd = re.compile( r"#\s*command\s*(?P<srch>.+)=>(?P<repl>.*)", re.IGNORECASE )
xcmd = re.compile( r"#\s*xcommand\s+(?P<srch>.+)=>(?P<repl>.*)", re.IGNORECASE )
trans = re.compile( r"#\s*trans(late)?\s+(?P<srch>.+)=>(?P<repl>.*)", re.IGNORECASE )
xtrans = re.compile( r"#\s*xtrans(late)?\s+(?P<srch>.+)=>(?P<repl>.*)", re.IGNORECASE )
pragma = re.compile( r"#\s*pragma\s*.+", re.IGNORECASE )

matchLit = re.compile( r"\s*([^\s^\[^\]^<]+)" )
matchGrp = re.compile( r"\s*\[" )
endGrp = re.compile( r"\s*\]" )
matchMrk = re.compile( r"\s*<(.+?)>" )
DumbMrk = re.compile( r"\s*#<(.+)>" )
firstNonWhite = re.compile( r"(\s*)\S" )

defs = { "__XPP__":None }
lineno = 0
curfile = ""
curIndent = ""

def StripComment( ln="" ) :
global curIndent
n = string.find( ln, '//' )
if n <> -1 :
ln = ln[:n]
m = firstNonWhite.match(ln)
if m :
curIndent = m.group(1)
return string.strip( ln )

def splitMatch( str, lft, rght ) :
"Parses the string on balancing delimiters"
j = string.find( str, lft )
if j == -1 :
return ( str,"","" )
bef = str[:j]
i = j + 1
l = len( str )
n = 0
while i < l :
if str[i] == rght :
if n == 0 :
return ( bef, str[j+1:i], str[i+1:] )
n = n - 1
elif str[i] == lft :
n = n + 1
i = i + 1
assert 0, "Unbalanced delimiters detected"

def pseudofunc( key, str, line ) :
i = string.find( str, ")" )
srch = string.split( str[1:i], "," )
str = str[i+1:]

i = string.find( line, key )
bef = line[:i]
line = line[i+2:]
l = len( line )
n = 0
i = 0
while n < l :
c = line[n]
if c == "(" :
i = i + 1
elif c == ")" :
if i == 0 :
break
i = i - 1
n = n + 1
aft = line[n+1:]
subs = string.split( line[:n],"," )
l = len( subs )
assert l==len(srch), "Length mismatch"
for i in xrange( 0,l ) :
str = replace( str, string.strip( string.rstrip( srch[i] ) ) , string.strip( string.rstrip( subs[i] ) ) )

return bef + str + aft

def writeln( hFile ) :
hFile.write( curIndent+tline+"\n" )

def writeBlank() :
if rootfile == curfile :
hOut.write( "\n" )

def readln( hFile ) :
global lineno
while 1 :
s = hFile.readline()
lineno = lineno+1
if not s :
hFile.close()
break
s = StripComment( s )
if not s :
writeBlank()
continue
if s[0] == "*" :
writeBlank()
continue
if s[:2] != "/*" :
break
writeBlank()
while string.rstrip(s)[-2:] != "*/" :
writeBlank()
s = hFile.readline()
lineno = lineno+1
if not s :
hFile.close()
print "Error : Unclosed Multiline Comments"
sys.exit(1)

return s

def readNextLine( hFile ) :
s = readln( hFile )
while s[-1:] == ";" :
s = s[:-1] + " " + readln( hFile )
writeBlank()
return s

def defOmit( hFile ) :
while 1 :
line = readNextLine( hFile )

m = endif.match( line )
if m :
return

m = elsedef.match( line )
if m :
return

m = ifdef.match( line )
if m and not defs.has_key( m.group("name") ) :
defOmit( hFile )

m = ifndef.match( line )
if m and defs.has_key( m.group("name") ) :
defOmit( hFile )


class MatchGroup:
""" see docstring for MatchTree"""

def __init__( self ) :
global curpos
self.trees = []
while 1:
self.trees.append( MatchTree() )
m = matchGrp.match( tline, curpos )
if not m :
break
curpos = m.end()

def __repr__( self ) :
return self.pprint( 0 )

def pprint( self, ind ) :
s = ""
for t in self.trees :
s = s + t.pprint( ind+1 )
return s

def match( self ) :
while 1 :
mtch = 0
for t in self.trees :
if t.match() :
mtch = 1
break
if not mtch :
break
return 1

class MatchTree:
"""
MatchTree -> ( Literal | Marker | MatchGroup )+

MatchGroup -> ( MatchTree )+

MatchTree stores the "syntax tree" for each clause
MatchGroup is a grouping of clauses at the same "level" (i.e. contiguous in the declaration)

tline is the (global) string we are matching to
curpos is the (global) current index into tline, which the match methods increment on success!
"""

def __init__( self ) :
self.tokens = []
self.parse()

def __repr__( self ) :
return self.pprint()

def pprint( self, ind=0 ) :
s = ""
for t in self.tokens :
s = s + t.pprint( ind )
s = s + (" "*ind)+"--------------\n"
return s

def match( self ) :
global curpos
i = curpos
for m in self.tokens :
if not m.match() :
curpos = i
return 0
return 1

def search( self ) :
global curpos
i = curpos
strt = self.tokens[0].search()
if strt != -1 :
for t in self.tokens[1:] :
if not t.match() :
curpos = i
return -1
return strt

def parse( self ) :
global curpos
l = len( tline )
while curpos < l :
m = matchGrp.match( tline, curpos )
if m :
curpos = m.end()
self.tokens.append( MatchGroup() )
state = "G"
continue

m = endGrp.match( tline, curpos )
if m :
curpos = m.end()
return

m = matchMrk.match( tline,curpos )
if m:
body = m.group( 1 )
curpos = m.end()
c = body[0]
if c == "(" :
self.tokens.append( ExtendedMarker( body[1:-1] ) )
elif c == "#" : # single
self.tokens.append( SingleMarker( body[1:] ) )
elif c == "*" : # wild
self.tokens.append( WildMarker( body[1:-1] ) )
elif string.strip( body )[-3:] == "..." : # list
n = string.find( body, "," )
self.tokens.append( ListMarker( string.strip( body[:n] ) ) )
elif string.find( body, ":" ) > 0 : # restricted
self.tokens.append( RestrictedMarker( body ) )
else : # regular
self.tokens.append( RegularMarker( body ) )
state = "M"
continue

m = Identifier.match( tline,curpos )
if m :
self.tokens.append( KeyWord( m.group(1) ) )
curpos = m.end()
continue

m = matchLit.match( tline,curpos )
if m :
self.tokens.append( Literal( m.group(1) ) )
curpos = m.end()
continue

assert 0, "Error - Unable to parse : "+tline[curpos:]

def readExpression( xpos=0, expect="",commaOK = 0 ) :

prevTok = "O"
while xpos < len( tline ) :
m = BlockHeader.match( tline,xpos )
if m :
xpos = readExpression( m.end(), "}" )
prevTok = "B"
continue

m = OpenBrackets.match( tline, xpos )
if m :
c = m.group(1)
if( prevTok != "O" and prevTok != "I" ) :
return xpos
if c == "[" :
bal = "]"
elif c == "{" :
bal = "}"
else : # c == "("
bal = ")"
xpos = readExpression( m.end(), bal, 1 )
prevTok = "X"
continue

m = CloseBrackets.match( tline, xpos )
if m :
if expect :
if m.group(1) != expect :
assert 0, "Unbalanced delimiters"
return m.end()
return xpos

if not commaOK :
m = comma.match( tline,xpos )
if m :
return xpos

m = Operator.match(tline, xpos)
if m :
prevTok = "O"
xpos = m.end()
continue

m = NumLiteral.match(tline, xpos)
if not m :
m = StringLiteral.match(tline, xpos)
if not m :
m = LogLiteral.match(tline, xpos)
if m :
if prevTok != "O" :
return xpos
prevTok = "L"
xpos = m.end()
continue

m = Identifier.match(tline, xpos)
if m :
if prevTok != "O" :
return xpos
prevTok = "I"
xpos = m.end()
continue

print "Error : Unable to parse string : "+tline[xpos:]
sys.exit(1)

return xpos

def ParseExpression() :
global curpos
i = curpos
curpos = readExpression( i )
return tline[i:curpos]

class Literal :

def __init__( self, s ) :
#self.re = re.compile( r"\s*"+re.escape( s )+r"(\b|$)", re.I )
self.re = re.compile( r"\s*"+re.escape( s ), re.I )
assert s

def __repr__( self ) :
return self.pprint()

def pprint( self, ind=0 ) :
return (" ")*ind + "Literal : "+self.re.pattern+"\n"

def match( self ) :
global curpos
m = self.re.match( tline, curpos )
if m :
curpos = m.end()
return 1
return 0

def search( self ) :
global curpos
m = self.re.search( tline, curpos )
if m :
curpos = m.end()
return m.start()
return -1

class KeyWord :

def __init__( self, s ) :
self.re = re.compile( r"\s*\b"+ s +r"(\b|$)", re.I )
assert s

def __repr__( self ) :
return self.pprint()

def pprint( self, ind=0 ) :
return (" ")*ind + "Keyword : "+self.re.pattern+"\n"

def match( self ) :
global curpos
m = self.re.match( tline, curpos )
if m :
curpos = m.end()
return 1
return 0

def search( self ) :
global curpos
m = self.re.search( tline, curpos )
if m :
curpos = m.end()
return m.start()
return -1

class MatchMarker :

def __init__( self, name ) :
self.name = name
self.vals = []
if currentCmd.markers.has_key( name ) :
print "Error - marker name already present : "+name
sys.exit(1)
currentCmd.markers[name] = self

def __repr__( self ) :
return self.pprint()

def pprint( self,ind=0 ) :
assert 0, "Abstract method called"
return ""

def match( self ) :
assert 0, "Abstract method called"
return 0

def getVal( self, i=0, f=None ) :
l = len( self.vals )
if i >= l :
if l :
val = self.vals[l-1]
else :
val =""
else :
val = self.vals[i]
if f :
return apply( f, (val,) )
return val

class RegularMarker( MatchMarker ) :

def __init__( self, name ) :
MatchMarker.__init__( self,name )

def pprint( self, ind=0 ) :
return (" ")*ind + "Regular : "+self.name+"\n"

def match( self ) :
self.vals.append( ParseExpression() )
return 1

class RestrictedMarker( MatchMarker ) :

def __init__( self, body ) :
n = string.find( body, ":" )
name = string.strip( body[:n] )
MatchMarker.__init__( self, name )
self.vals = []
mstr = string.replace( body[n+1:],",","|" )
self.re = re.compile( "\s*("+string.replace( mstr, " ", "" )+")", re.I )

def pprint( self, ind=0 ) :
return (" ")*ind + "Regular : "+self.name+", "+self.re.pattern+"\n"

def match( self ) :
global curpos
m = self.re.match( tline, curpos )
if m :
self.vals.append( m.group( 1 ) )
curpos = m.end()
return 1
return 0

def search( self ) :
global curpos
m = self.re.search( tline, curpos )
if m :
self.vals.append( m.group( 1 ) )
curpos = m.end()
return m.start()
return -1

class WildMarker( MatchMarker ) :

def __init__( self, name ) :
MatchMarker.__init__( self,name )

def pprint( self, ind=0 ) :
return (" ")*ind + "Wild : "+self.name+"\n"

def match( self ) :
global curpos
self.vals.append( tline[curpos:] )
curpos = len( tline )
return 1

class SingleMarker( MatchMarker ) :

def __init__( self, name ) :
MatchMarker.__init__( self,name )
self.re = re.compile( r"\s*([^\s]*)" )

def pprint( self, ind=0 ) :
return (" ")*ind + "Single : "+self.name+"\n"

def match( self ) :
global curpos
m = self.re.match( tline, curpos )
if m :
self.vals.append( m.group(1) )
curpos = m.end()
return 1
return 0

class ExtendedMarker( MatchMarker ) :

def __init__( self, name ) :
MatchMarker.__init__( self,name )
self.reXpr = re.compile("\s*\(")

def pprint( self, ind=0 ) :
return (" ")*ind + "Extended : "+self.name+"\n"

def match( self ) :
global curpos
m = self.reXpr.match( tline, curpos )
if m :
self.vals.append( ParseExpression() )
return 1

m = StringLiteral.match( tline, curpos )
if not m :
m = Identifier.match( tline, curpos )
if m :
self.vals.append( m.group(1) )
curpos = m.end()
return 1

return 0

class ListMarker( MatchMarker ) :

def __init__( self, name ) :
MatchMarker.__init__( self,name )

def pprint( self, ind=0 ) :
return (" ")*ind + "List : "+self.name+"\n"

def match( self ) :
global curpos
val = []
self.vals.append( val )
while 1:
xpos = curpos
curpos = readExpression(curpos)
val.append( tline[xpos:curpos] )
m = comma.match( tline,curpos )
if not m:
break
curpos = m.end()
return 1

def getVal( self, i=0, f=None ) :
l = len( self.vals )
if i >= l :
if l :
val = self.vals[l-1]
else :
val = [""]
else :
val = self.vals[i]
if not val :
val.append("")
if f :
val = map( f, val )
return reduce( lambda x,y : x+","+y, val )

class ResultGroup :

def __init__( self ) :
global curpos
self.markers = []
self.prs = ""
l = len( tline )
while curpos < l :

m = matchGrp.match( tline,curpos )
if m :
self.prs = self.prs + tline[m.start():m.end()-1] + "%s"
curpos = m.end()
self.markers.append( (ResultGroup(),) )
continue

if endGrp.match( tline,curpos ) :
return

Dumb = 0
m = matchMrk.match( tline,curpos )
if not m :
Dumb = 1
m = DumbMrk.match( tline,curpos )
if m :
self.prs = self.prs + tline[curpos:m.start()]
body = m.group(1)
curpos = m.end()
c = body[0]
if Dumb :
mname = body
func = stringify
elif c == '"' :
assert body[-1] == '"', "Invalid match marker : "+body
mname = body[1:-1]
func = normstringify
elif c == "(" :
assert body[-1] == ')', "Invalid match marker : "+body
mname = body[1:-1]
func = smartstringify
elif c == "{" :
assert body[-1] == '}', "Invalid match marker : "+body
mname = body[1:-1]
func = blockify
elif c == "." :
assert body[-1] == '.', "Invalid match marker : "+body
mname = body[1:-1]
func = logify
else : # regular
mname = body
func = lambda s : s

if not currentCmd.markers.has_key( mname ) :
print "Error : match marker not found for "+mname+" at line :",lineno
print tline
print currentCmd.mtree
sys.exit(1)

self.markers.append( (currentCmd.markers[mname],func) )
self.prs = self.prs + "%s"
continue

m = matchLit.match( tline, curpos )
if m :
self.prs = self.prs + tline[m.start():m.end()]
curpos = m.end()

def expand( self, i = 0 ) :
l = []
for m in self.markers :
if len(m) == 2 :
l.append( m[0].getVal( i, m[1] ) )
else :
l.append( m[0].repexpand() )
return self.prs % tuple( l )

def repexpand( self ) : # Note : this should not have any repeating group markers!
maxlen = 0
Result = ""
for m in self.markers :
if len( m[0].vals ) > maxlen :
maxlen = len( m[0].vals )
for i in range( 0, maxlen ) :
Result = Result + self.expand( i )
return Result

class Command :

cmds = []

def __init__( self, srch, repl ) :
global currentCmd,tline,curpos
self.markers = {}
currentCmd = self
curpos = 0
tline = string.strip( srch )
self.mtree = MatchTree()
tline = string.strip( repl )
curpos = 0
self.repl = ResultGroup()
Command.cmds.insert(0,self)

def transform( self ) :
global tline
if self.mtree.match() :
tline = self.repl.expand()
t = self.markers.items()
for (n,m) in t :
m.vals = []
return 1
return 0

class Translate( Command ) :

trns = []

def __init__( self, srch, repl ) :
global currentCmd,tline,curpos
self.markers = {}
currentCmd = self
tline = string.strip( srch )
curpos = 0
self.mtree = MatchTree()
tline = repl
curpos = 0
self.repl = ResultGroup()
Translate.trns.insert(0,self)

def transform( self ) :
global tline
i = self.mtree.search()
if i != -1 :
tline = tline[:i]+ self.repl.expand()+ tline[curpos:]
t = self.markers.items()
for (n,m) in t :
m.vals = []
return 1
return 1
return 0


def stringify( s ) :
if string.lstrip( s )[0] == '"' :
return "'"+s+"'"
return '"'+s+'"'

def normstringify( s ) :
if s :
return '"'+s+'"'
return s

def smartstringify( s ) :
if not s :
return ""
s = string.strip( s )
if s[0] == "(" and s[-1:] == ")" :
return s
return '"'+s+'"'

def blockify( s ) :
if s :
return "{|| "+s+" }"
return ""

def logify( s ) :
if s :
return ".T."
return ".F."

def applydefs() :
global defs,tline
for (frm,to) in defs.items() :
i = string.find( tline, frm )
if i <> -1 :
tline = string.replace( tline, frm, to )
return 1
return 0

def applytrans() :
for c in Translate.trns :
if c.transform() :
return 1
return 0

def applycmds() :
for c in Command.cmds :
if c.transform() :
return 1
return 0

def transform( line ) :
global tline,curpos
tline = line
assert tline, "Empty string before transform"
curpos = 0
while 1 :
if applydefs() :
continue
if applytrans() :
continue
if applycmds() :
continue
break

assert tline, "Empty string after transform"
writeln( hOut )

def PreProcess( cFile ) :
global defs,hOut,lineno,curfile

hFile = open( cFile, "r" )
if not hFile :
print "Error : unable to open "+cFile
sys.exit(1)

savno = lineno
savfile = curfile
curfile = cFile
lineno = 0
while not hFile.closed :
line = readNextLine(hFile)
if not line :
continue
m = defStmt.match( line )
if m :
nam = m.group("name")
if defs.has_key( nam ) :
print "Error : : "+nam+" already defined"
sys.exit(1)
if not m.group("aft") :
defs[nam] = "" # preprocessor const
elif m.group("aft")[0] == "(" : #pseudofunction
defs[nam+"("] = m.group("aft")
else : # symbolic constant
defs[nam] = string.strip( string.rstrip( m.group("aft") ) )
continue

m = ifdef.match( line )
if m :
if not defs.has_key( m.group("name") ) :
defOmit( hFile )
continue

m = ifndef.match( line )
if m :
if defs.has_key( m.group("name") ) :
defOmit( hFile )
continue

m = elsedef.match( line )
if m :
defOmit( hFile )
continue

m = endif.match( line )
if m :
continue

m = include.match( line )
if m :
fname = string.split( m.group("filename"),'"' )[1]
IncludeFile( fname )
continue

m = undef.match( line )
if m :
if defs.has_key( m.group("name") ) :
del defs[ m.group("name") ]
continue

m = xcmd.match( line )
if m :
Command( m.group("srch"),m.group("repl") )
continue

m = cmd.match( line )
if m :
Command( m.group("srch"),m.group("repl") )
continue

m = xtrans.match( line )
if m :
Translate( m.group("srch"),m.group("repl") )
continue

m = trans.match( line )
if m :
Translate( m.group("srch"),m.group("repl") )
continue

m = pragma.match( line )
if m :
continue

transform( line )

hFile.close()
lineno = savno
curfile = savfile

def IncludeFile( fname ) :
import os
if not os.path.exists( fname ) :
if os.environ.has_key("INCLUDE") :
incpaths = string.split( os.environ["INCLUDE"], ";" )
for p in incpaths :
if os.path.exists( p + "\\" + fname ) :
hOut.write( '#line 1 "'+p+"\\"+fname+'"@"'+fname+'"\n' )
fname = p+"\\"+fname
break
else :
print "Error : unable to find : "+fname
sys.exit( 1 )
else :
print "Error : unable to find : "+fname
sys.exit( 1 )
else :
hOut.write( '#line 1 "'+fname+'"@"'+fname+'"\n' )

PreProcess( fname )
if curfile :
hOut.write( "#line "+str(lineno)+' "'+curfile+'"\n' )

def PreProcessPrg( prg, pp=None,std=None ) :
import os
global hOut,curfile,rootfile

if "." not in prg :
prg = prg+".prg"

if not pp :
pp = os.path.splitext(prg)[0]+".ppp"

hOut = open( pp, "w" )
rootfile = prg
print "Preprocessing",prg,"to",pp,"using",std
if std :
IncludeFile( std )
hOut.write( '#line 1 "'+prg+'"\n' )
curfile = prg
PreProcess( prg )

hOut.close()


if __name__ == "__main__" :
import getopt
optlist, args = getopt.getopt( sys.argv[1:], "Uu:" )
if not args or len(args) > 2 :
print "Syntax : PRGPP [-U | -u <std.ch replacement> ] <filename> [ <ppp-name> ] "
else :
if len(args) < 2 :
args.append( None )
if optlist :
if optlist[0][0] == "-U" :
PreProcessPrg( args[0], args[1] )
elif optlist[0][0] == "-u" :
PreProcessPrg( args[0], args[1], optlist[0][1] )
else :
PreProcessPrg( args[0],args[1],"std.ch" )

--------------2ECC51789D473DB99ACE3D31--
Xbase++ preprocessor implementation in Python [ In reply to ]
In article <37097A3A.F772205@magna.com.au>, garys@magna.com.au says...

>Attached please find a Python implementation of the Xbase++ preprocessor.
...
>Oh, and it is *dead slow*! - hundreds of times slower I think!
...

I do not know re's well enough to comment on whether they can be rewritten
to run faster. I believe there is a python profiler which might give
indications on where to start to speed things up.

Terry J. Reedy
Xbase++ preprocessor implementation in Python [ In reply to ]
In article <37097A3A.F772205@magna.com.au>, garys@magna.com.au says...

>Attached please find a Python implementation of the Xbase++ preprocessor.
...
>Oh, and it is *dead slow*! - hundreds of times slower I think!
...

I do not know re's well enough to comment on whether they can be rewritten
to run faster. I believe there is a python profiler which might give
indications on where to start to speed things up.

Terry J. Reedy
Xbase++ preprocessor implementation in Python [ In reply to ]
In article <37097A3A.F772205@magna.com.au>, garys@magna.com.au says...

>Attached please find a Python implementation of the Xbase++ preprocessor.
...
>Oh, and it is *dead slow*! - hundreds of times slower I think!
...

I do not know re's well enough to comment on whether they can be rewritten
to run faster. I believe there is a python profiler which might give
indications on where to start to speed things up.

Terry J. Reedy
Xbase++ preprocessor implementation in Python [ In reply to ]
Sorry for the repetition. Glitch with newssite. TJR