Skip to content

Commit

Permalink
Python 2.6/3.0 compatibility changes
Browse files Browse the repository at this point in the history
  • Loading branch information
dabeaz committed Nov 27, 2008
1 parent c66982f commit ca5170e
Show file tree
Hide file tree
Showing 66 changed files with 608 additions and 483 deletions.
24 changes: 24 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
Version 2.6
-----------------------------
11/27/08: beazley
Numerous changes to support Python 3.0 including removal of deprecated
statements (e.g., has_key) and the additional of compatibility code
to emulate features from Python 2 that have been removed, but which
are needed. Fixed the unit testing suite to work with Python 3.0.
The code should be backwards compatible with Python 2.

11/26/08: beazley
Loosened the rules on what kind of objects can be passed in as the
"module" parameter to lex() and yacc(). Previously, you could only use
a module or an instance. Now, PLY just uses dir() to get a list of
symbols on whatever the object is without regard for its type.

11/26/08: beazley
Changed all except: statements to be compatible with Python2.x/3.x syntax.

11/26/08: beazley
Changed all raise Exception, value statements to raise Exception(value) for
forward compatibility.

11/26/08: beazley
Removed all print statements from lex and yacc, using sys.stdout and sys.stderr
directly. Preparation for Python 3.0 support.

11/04/08: beazley
Fixed a bug with referring to symbols on the the parsing stack using negative
indices.
Expand Down
4 changes: 2 additions & 2 deletions README
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PLY (Python Lex-Yacc) Version 2.5 (May 28, 2008)
PLY (Python Lex-Yacc) Version 2.6 (Alpha1)

David M. Beazley ([email protected])

Expand Down Expand Up @@ -96,7 +96,7 @@ A simple example is found at the end of this document

Requirements
============
PLY requires the use of Python 2.1 or greater. However, you should
PLY requires the use of Python 2.2 or greater. However, you should
use the latest Python release if possible. It should work on just
about any platform. PLY has been tested with both CPython and Jython.
It also seems to work with IronPython.
Expand Down
5 changes: 4 additions & 1 deletion example/BASIC/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import sys
sys.path.insert(0,"../..")

if sys.version_info[0] >= 3:
raw_input = input

import basiclex
import basparse
import basinterp
Expand Down Expand Up @@ -41,7 +44,7 @@
prog = basparse.parse(line)
if not prog: continue

keys = prog.keys()
keys = list(prog)
if keys[0] > 0:
b.add_statements(prog)
else:
Expand Down
2 changes: 1 addition & 1 deletion example/BASIC/basiclex.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def t_NEWLINE(t):
return t

def t_error(t):
print "Illegal character", t.value[0]
print("Illegal character %s" % t.value[0])
t.lexer.skip(1)

lex.lex()
Expand Down
107 changes: 54 additions & 53 deletions example/BASIC/basinterp.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ def check_end(self):
if self.prog[lineno][0] == 'END' and not has_end:
has_end = lineno
if not has_end:
print "NO END INSTRUCTION"
print("NO END INSTRUCTION")
self.error = 1
return
if has_end != lineno:
print "END IS NOT LAST"
print("END IS NOT LAST")
self.error = 1

# Check loops
Expand All @@ -60,7 +61,7 @@ def check_loops(self):
self.loopend[pc] = i
break
else:
print "FOR WITHOUT NEXT AT LINE" % self.stat[pc]
print("FOR WITHOUT NEXT AT LINE %s" % self.stat[pc])
self.error = 1

# Evaluate an expression
Expand All @@ -79,33 +80,33 @@ def eval(self,expr):
elif etype == 'VAR':
var,dim1,dim2 = expr[1]
if not dim1 and not dim2:
if self.vars.has_key(var):
if var in self.vars:
return self.vars[var]
else:
print "UNDEFINED VARIABLE", var, "AT LINE", self.stat[self.pc]
print("UNDEFINED VARIABLE %s AT LINE %s" % (var, self.stat[self.pc]))
raise RuntimeError
# May be a list lookup or a function evaluation
if dim1 and not dim2:
if self.functions.has_key(var):
if var in self.functions:
# A function
return self.functions[var](dim1)
else:
# A list evaluation
if self.lists.has_key(var):
if var in self.lists:
dim1val = self.eval(dim1)
if dim1val < 1 or dim1val > len(self.lists[var]):
print "LIST INDEX OUT OF BOUNDS AT LINE", self.stat[self.pc]
print("LIST INDEX OUT OF BOUNDS AT LINE %s" % self.stat[self.pc])
raise RuntimeError
return self.lists[var][dim1val-1]
if dim1 and dim2:
if self.tables.has_key(var):
if var in self.tables:
dim1val = self.eval(dim1)
dim2val = self.eval(dim2)
if dim1val < 1 or dim1val > len(self.tables[var]) or dim2val < 1 or dim2val > len(self.tables[var][0]):
print "TABLE INDEX OUT OUT BOUNDS AT LINE", self.stat[self.pc]
print("TABLE INDEX OUT OUT BOUNDS AT LINE %s" % self.stat[self.pc])
raise RuntimeError
return self.tables[var][dim1val-1][dim2val-1]
print "UNDEFINED VARIABLE", var, "AT LINE", self.stat[self.pc]
print("UNDEFINED VARIABLE %s AT LINE %s" % (var, self.stat[self.pc]))
raise RuntimeError

# Evaluate a relational expression
Expand Down Expand Up @@ -145,31 +146,31 @@ def assign(self,target,value):
elif dim1 and not dim2:
# List assignment
dim1val = self.eval(dim1)
if not self.lists.has_key(var):
if not var in self.lists:
self.lists[var] = [0]*10

if dim1val > len(self.lists[var]):
print "DIMENSION TOO LARGE AT LINE", self.stat[self.pc]
print ("DIMENSION TOO LARGE AT LINE %s" % self.stat[self.pc])
raise RuntimeError
self.lists[var][dim1val-1] = self.eval(value)
elif dim1 and dim2:
dim1val = self.eval(dim1)
dim2val = self.eval(dim2)
if not self.tables.has_key(var):
if not var in self.tables:
temp = [0]*10
v = []
for i in range(10): v.append(temp[:])
self.tables[var] = v
# Variable already exists
if dim1val > len(self.tables[var]) or dim2val > len(self.tables[var][0]):
print "DIMENSION TOO LARGE AT LINE", self.stat[self.pc]
print("DIMENSION TOO LARGE AT LINE %s" % self.stat[self.pc])
raise RuntimeError
self.tables[var][dim1val-1][dim2val-1] = self.eval(value)

# Change the current line number
def goto(self,linenum):
if not self.prog.has_key(linenum):
print "UNDEFINED LINE NUMBER %d AT LINE %d" % (linenum, self.stat[self.pc])
if not linenum in self.prog:
print("UNDEFINED LINE NUMBER %d AT LINE %d" % (linenum, self.stat[self.pc]))
raise RuntimeError
self.pc = self.stat.index(linenum)

Expand All @@ -183,7 +184,7 @@ def run(self):
self.gosub = None # Gosub return point (if any)
self.error = 0 # Indicates program error

self.stat = self.prog.keys() # Ordered list of all line numbers
self.stat = list(self.prog) # Ordered list of all line numbers
self.stat.sort()
self.pc = 0 # Current program counter

Expand Down Expand Up @@ -284,29 +285,29 @@ def run(self):

elif op == 'NEXT':
if not self.loops:
print "NEXT WITHOUT FOR AT LINE",line
print("NEXT WITHOUT FOR AT LINE %s" % line)
return

nextvar = instr[1]
self.pc = self.loops[-1][0]
loopinst = self.prog[self.stat[self.pc]]
forvar = loopinst[1]
if nextvar != forvar:
print "NEXT DOESN'T MATCH FOR AT LINE", line
print("NEXT DOESN'T MATCH FOR AT LINE %s" % line)
return
continue
elif op == 'GOSUB':
newline = instr[1]
if self.gosub:
print "ALREADY IN A SUBROUTINE AT LINE", line
print("ALREADY IN A SUBROUTINE AT LINE %s" % line)
return
self.gosub = self.stat[self.pc]
self.goto(newline)
continue

elif op == 'RETURN':
if not self.gosub:
print "RETURN WITHOUT A GOSUB AT LINE",line
print("RETURN WITHOUT A GOSUB AT LINE %s" % line)
return
self.goto(self.gosub)
self.gosub = None
Expand Down Expand Up @@ -358,69 +359,69 @@ def var_str(self,var):

# Create a program listing
def list(self):
stat = self.prog.keys() # Ordered list of all line numbers
stat = list(self.prog) # Ordered list of all line numbers
stat.sort()
for line in stat:
instr = self.prog[line]
op = instr[0]
if op in ['END','STOP','RETURN']:
print line, op
print("%s %s" % (line, op))
continue
elif op == 'REM':
print line, instr[1]
print("%s %s" % (line, instr[1]))
elif op == 'PRINT':
print line, op,
_out = "%s %s " % (line, op)
first = 1
for p in instr[1]:
if not first: print ",",
if p[0] and p[1]: print '"%s"%s' % (p[0],self.expr_str(p[1])),
elif p[1]: print self.expr_str(p[1]),
else: print '"%s"' % (p[0],),
if not first: _out += ", "
if p[0] and p[1]: _out += '"%s"%s' % (p[0],self.expr_str(p[1]))
elif p[1]: _out += self.expr_str(p[1])
else: _out += '"%s"' % (p[0],)
first = 0
if instr[2]: print instr[2]
else: print
if instr[2]: _out += instr[2]
print(_out)
elif op == 'LET':
print line,"LET",self.var_str(instr[1]),"=",self.expr_str(instr[2])
print("%s LET %s = %s" % (line,self.var_str(instr[1]),self.expr_str(instr[2])))
elif op == 'READ':
print line,"READ",
_out = "%s READ " % line
first = 1
for r in instr[1]:
if not first: print ",",
print self.var_str(r),
if not first: _out += ","
_out += self.var_str(r)
first = 0
print ""
print(_out)
elif op == 'IF':
print line,"IF %s THEN %d" % (self.relexpr_str(instr[1]),instr[2])
print("%s IF %s THEN %d" % (line,self.relexpr_str(instr[1]),instr[2]))
elif op == 'GOTO' or op == 'GOSUB':
print line, op, instr[1]
print("%s %s %s" % (line, op, instr[1]))
elif op == 'FOR':
print line,"FOR %s = %s TO %s" % (instr[1],self.expr_str(instr[2]),self.expr_str(instr[3])),
if instr[4]: print "STEP %s" % (self.expr_str(instr[4])),
print
_out = "%s FOR %s = %s TO %s" % (line,instr[1],self.expr_str(instr[2]),self.expr_str(instr[3]))
if instr[4]: _out += " STEP %s" % (self.expr_str(instr[4]))
print(_out)
elif op == 'NEXT':
print line,"NEXT", instr[1]
print("%s NEXT %s" % (line, instr[1]))
elif op == 'FUNC':
print line,"DEF %s(%s) = %s" % (instr[1],instr[2],self.expr_str(instr[3]))
print("%s DEF %s(%s) = %s" % (line,instr[1],instr[2],self.expr_str(instr[3])))
elif op == 'DIM':
print line,"DIM",
_out = "%s DIM " % line
first = 1
for vname,x,y in instr[1]:
if not first: print ",",
if not first: _out += ","
first = 0
if y == 0:
print "%s(%d)" % (vname,x),
_out += "%s(%d)" % (vname,x)
else:
print "%s(%d,%d)" % (vname,x,y),
_out += "%s(%d,%d)" % (vname,x,y)

print
print(_out)
elif op == 'DATA':
print line,"DATA",
_out = "%s DATA " % line
first = 1
for v in instr[1]:
if not first: print ",",
if not first: _out += ","
first = 0
print v,
print
_out += v
print(_out)

# Erase the current program
def new(self):
Expand Down
6 changes: 3 additions & 3 deletions example/BASIC/basparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def p_program_error(p):
def p_statement(p):
'''statement : INTEGER command NEWLINE'''
if isinstance(p[2],str):
print p[2],"AT LINE", p[1]
print("%s %s %s" % (p[2],"AT LINE", p[1]))
p[0] = None
p.parser.error = 1
else:
Expand All @@ -68,7 +68,7 @@ def p_statement_blank(p):

def p_statement_bad(p):
'''statement : INTEGER error NEWLINE'''
print "MALFORMED STATEMENT AT LINE", p[1]
print("MALFORMED STATEMENT AT LINE %s" % p[1])
p[0] = None
p.parser.error = 1

Expand Down Expand Up @@ -399,7 +399,7 @@ def p_empty(p):
#### Catastrophic error handler
def p_error(p):
if not p:
print "SYNTAX ERROR AT EOF"
print("SYNTAX ERROR AT EOF")

bparser = yacc.yacc()

Expand Down
2 changes: 1 addition & 1 deletion example/ansic/clex.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def t_preprocessor(t):
t.lexer.lineno += 1

def t_error(t):
print "Illegal character %s" % repr(t.value[0])
print("Illegal character %s" % repr(t.value[0]))
t.lexer.skip(1)

lexer = lex.lex(optimize=1)
Expand Down
2 changes: 1 addition & 1 deletion example/ansic/cparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,7 @@ def p_empty(t):
pass

def p_error(t):
print "Whoa. We're hosed"
print("Whoa. We're hosed")

import profile
# Build the grammar
Expand Down
Loading

0 comments on commit ca5170e

Please sign in to comment.