summaryrefslogtreecommitdiff
path: root/example
diff options
context:
space:
mode:
authorQuinten Yearsley <qyearsley@gmail.com>2015-09-26 10:56:16 -0700
committerDavid Beazley <dave@dabeaz.com>2016-08-30 15:53:46 -0500
commit9e2b80e00562f0e98ea0791f7192a09c1707e7a9 (patch)
treec4460062d17330cc167433d697ba7db511b46e69 /example
parent481413e07356a2f9b7cabd2e6fc34b43c1e791c7 (diff)
downloadply-9e2b80e00562f0e98ea0791f7192a09c1707e7a9.tar.gz
Run autopep8 on example/
Diffstat (limited to 'example')
-rw-r--r--example/BASIC/basic.py46
-rw-r--r--example/BASIC/basiclex.py71
-rw-r--r--example/BASIC/basiclog.py56
-rw-r--r--example/BASIC/basinterp.py719
-rw-r--r--example/BASIC/basparse.py290
-rw-r--r--example/GardenSnake/GardenSnake.py160
-rw-r--r--example/ansic/clex.py132
-rw-r--r--example/ansic/cparse.py206
-rw-r--r--example/calc/calc.py50
-rw-r--r--example/calcdebug/calc.py52
-rw-r--r--example/calceof/calc.py51
-rwxr-xr-xexample/classcalc/calc.py72
-rw-r--r--example/closurecalc/calc.py44
-rw-r--r--example/hedit/hedit.py22
-rwxr-xr-xexample/newclasscalc/calc.py73
-rw-r--r--example/optcalc/calc.py67
-rw-r--r--example/unicalc/calc.py66
-rw-r--r--example/yply/ylex.py91
-rw-r--r--example/yply/yparse.py153
-rwxr-xr-xexample/yply/yply.py10
20 files changed, 1448 insertions, 983 deletions
diff --git a/example/BASIC/basic.py b/example/BASIC/basic.py
index b14483d..70ac9e7 100644
--- a/example/BASIC/basic.py
+++ b/example/BASIC/basic.py
@@ -2,7 +2,7 @@
#
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
if sys.version_info[0] >= 3:
raw_input = input
@@ -17,7 +17,8 @@ import basinterp
if len(sys.argv) == 2:
data = open(sys.argv[1]).read()
prog = basparse.parse(data)
- if not prog: raise SystemExit
+ if not prog:
+ raise SystemExit
b = basinterp.BasicInterpreter(prog)
try:
b.run()
@@ -39,33 +40,26 @@ while 1:
line = raw_input("[BASIC] ")
except EOFError:
raise SystemExit
- if not line: continue
+ if not line:
+ continue
line += "\n"
prog = basparse.parse(line)
- if not prog: continue
+ if not prog:
+ continue
keys = list(prog)
if keys[0] > 0:
- b.add_statements(prog)
+ b.add_statements(prog)
else:
- stat = prog[keys[0]]
- if stat[0] == 'RUN':
- try:
- b.run()
- except RuntimeError:
- pass
- elif stat[0] == 'LIST':
- b.list()
- elif stat[0] == 'BLANK':
- b.del_line(stat[1])
- elif stat[0] == 'NEW':
- b.new()
-
-
-
-
-
-
-
-
-
+ stat = prog[keys[0]]
+ if stat[0] == 'RUN':
+ try:
+ b.run()
+ except RuntimeError:
+ pass
+ elif stat[0] == 'LIST':
+ b.list()
+ elif stat[0] == 'BLANK':
+ b.del_line(stat[1])
+ elif stat[0] == 'NEW':
+ b.new()
diff --git a/example/BASIC/basiclex.py b/example/BASIC/basiclex.py
index 3d27cde..4151f4c 100644
--- a/example/BASIC/basiclex.py
+++ b/example/BASIC/basiclex.py
@@ -3,72 +3,59 @@
from ply import *
keywords = (
- 'LET','READ','DATA','PRINT','GOTO','IF','THEN','FOR','NEXT','TO','STEP',
- 'END','STOP','DEF','GOSUB','DIM','REM','RETURN','RUN','LIST','NEW',
+ 'LET', 'READ', 'DATA', 'PRINT', 'GOTO', 'IF', 'THEN', 'FOR', 'NEXT', 'TO', 'STEP',
+ 'END', 'STOP', 'DEF', 'GOSUB', 'DIM', 'REM', 'RETURN', 'RUN', 'LIST', 'NEW',
)
tokens = keywords + (
- 'EQUALS','PLUS','MINUS','TIMES','DIVIDE','POWER',
- 'LPAREN','RPAREN','LT','LE','GT','GE','NE',
- 'COMMA','SEMI', 'INTEGER','FLOAT', 'STRING',
- 'ID','NEWLINE'
+ 'EQUALS', 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'POWER',
+ 'LPAREN', 'RPAREN', 'LT', 'LE', 'GT', 'GE', 'NE',
+ 'COMMA', 'SEMI', 'INTEGER', 'FLOAT', 'STRING',
+ 'ID', 'NEWLINE'
)
t_ignore = ' \t'
+
def t_REM(t):
r'REM .*'
return t
+
def t_ID(t):
r'[A-Z][A-Z0-9]*'
if t.value in keywords:
t.type = t.value
return t
-
-t_EQUALS = r'='
-t_PLUS = r'\+'
-t_MINUS = r'-'
-t_TIMES = r'\*'
-t_POWER = r'\^'
-t_DIVIDE = r'/'
-t_LPAREN = r'\('
-t_RPAREN = r'\)'
-t_LT = r'<'
-t_LE = r'<='
-t_GT = r'>'
-t_GE = r'>='
-t_NE = r'<>'
-t_COMMA = r'\,'
-t_SEMI = r';'
-t_INTEGER = r'\d+'
-t_FLOAT = r'((\d*\.\d+)(E[\+-]?\d+)?|([1-9]\d*E[\+-]?\d+))'
-t_STRING = r'\".*?\"'
+
+t_EQUALS = r'='
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_TIMES = r'\*'
+t_POWER = r'\^'
+t_DIVIDE = r'/'
+t_LPAREN = r'\('
+t_RPAREN = r'\)'
+t_LT = r'<'
+t_LE = r'<='
+t_GT = r'>'
+t_GE = r'>='
+t_NE = r'<>'
+t_COMMA = r'\,'
+t_SEMI = r';'
+t_INTEGER = r'\d+'
+t_FLOAT = r'((\d*\.\d+)(E[\+-]?\d+)?|([1-9]\d*E[\+-]?\d+))'
+t_STRING = r'\".*?\"'
+
def t_NEWLINE(t):
r'\n'
t.lexer.lineno += 1
return t
+
def t_error(t):
print("Illegal character %s" % t.value[0])
t.lexer.skip(1)
lex.lex(debug=0)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/example/BASIC/basiclog.py b/example/BASIC/basiclog.py
index ccfd7b9..9dcc7fe 100644
--- a/example/BASIC/basiclog.py
+++ b/example/BASIC/basiclog.py
@@ -2,16 +2,16 @@
#
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
if sys.version_info[0] >= 3:
raw_input = input
import logging
logging.basicConfig(
- level = logging.INFO,
- filename = "parselog.txt",
- filemode = "w"
+ level=logging.INFO,
+ filename="parselog.txt",
+ filemode="w"
)
log = logging.getLogger()
@@ -24,8 +24,9 @@ import basinterp
# interactive mode below
if len(sys.argv) == 2:
data = open(sys.argv[1]).read()
- prog = basparse.parse(data,debug=log)
- if not prog: raise SystemExit
+ prog = basparse.parse(data, debug=log)
+ if not prog:
+ raise SystemExit
b = basinterp.BasicInterpreter(prog)
try:
b.run()
@@ -47,33 +48,26 @@ while 1:
line = raw_input("[BASIC] ")
except EOFError:
raise SystemExit
- if not line: continue
+ if not line:
+ continue
line += "\n"
- prog = basparse.parse(line,debug=log)
- if not prog: continue
+ prog = basparse.parse(line, debug=log)
+ if not prog:
+ continue
keys = list(prog)
if keys[0] > 0:
- b.add_statements(prog)
+ b.add_statements(prog)
else:
- stat = prog[keys[0]]
- if stat[0] == 'RUN':
- try:
- b.run()
- except RuntimeError:
- pass
- elif stat[0] == 'LIST':
- b.list()
- elif stat[0] == 'BLANK':
- b.del_line(stat[1])
- elif stat[0] == 'NEW':
- b.new()
-
-
-
-
-
-
-
-
-
+ stat = prog[keys[0]]
+ if stat[0] == 'RUN':
+ try:
+ b.run()
+ except RuntimeError:
+ pass
+ elif stat[0] == 'LIST':
+ b.list()
+ elif stat[0] == 'BLANK':
+ b.del_line(stat[1])
+ elif stat[0] == 'NEW':
+ b.new()
diff --git a/example/BASIC/basinterp.py b/example/BASIC/basinterp.py
index 3e8a777..67762c7 100644
--- a/example/BASIC/basinterp.py
+++ b/example/BASIC/basinterp.py
@@ -5,141 +5,167 @@ import sys
import math
import random
+
class BasicInterpreter:
# Initialize the interpreter. prog is a dictionary
# containing (line,statement) mappings
- def __init__(self,prog):
- self.prog = prog
-
- self.functions = { # Built-in function table
- 'SIN' : lambda z: math.sin(self.eval(z)),
- 'COS' : lambda z: math.cos(self.eval(z)),
- 'TAN' : lambda z: math.tan(self.eval(z)),
- 'ATN' : lambda z: math.atan(self.eval(z)),
- 'EXP' : lambda z: math.exp(self.eval(z)),
- 'ABS' : lambda z: abs(self.eval(z)),
- 'LOG' : lambda z: math.log(self.eval(z)),
- 'SQR' : lambda z: math.sqrt(self.eval(z)),
- 'INT' : lambda z: int(self.eval(z)),
- 'RND' : lambda z: random.random()
- }
+ def __init__(self, prog):
+ self.prog = prog
+
+ self.functions = { # Built-in function table
+ 'SIN': lambda z: math.sin(self.eval(z)),
+ 'COS': lambda z: math.cos(self.eval(z)),
+ 'TAN': lambda z: math.tan(self.eval(z)),
+ 'ATN': lambda z: math.atan(self.eval(z)),
+ 'EXP': lambda z: math.exp(self.eval(z)),
+ 'ABS': lambda z: abs(self.eval(z)),
+ 'LOG': lambda z: math.log(self.eval(z)),
+ 'SQR': lambda z: math.sqrt(self.eval(z)),
+ 'INT': lambda z: int(self.eval(z)),
+ 'RND': lambda z: random.random()
+ }
# Collect all data statements
def collect_data(self):
- self.data = []
- for lineno in self.stat:
- if self.prog[lineno][0] == 'DATA':
- self.data = self.data + self.prog[lineno][1]
- self.dc = 0 # Initialize the data counter
+ self.data = []
+ for lineno in self.stat:
+ if self.prog[lineno][0] == 'DATA':
+ self.data = self.data + self.prog[lineno][1]
+ self.dc = 0 # Initialize the data counter
# Check for end statements
def check_end(self):
- has_end = 0
- for lineno in self.stat:
- if self.prog[lineno][0] == 'END' and not has_end:
- has_end = lineno
- if not has_end:
- print("NO END INSTRUCTION")
- self.error = 1
- return
- if has_end != lineno:
- print("END IS NOT LAST")
- self.error = 1
+ has_end = 0
+ for lineno in self.stat:
+ if self.prog[lineno][0] == 'END' and not has_end:
+ has_end = lineno
+ if not has_end:
+ print("NO END INSTRUCTION")
+ self.error = 1
+ return
+ if has_end != lineno:
+ print("END IS NOT LAST")
+ self.error = 1
# Check loops
def check_loops(self):
- for pc in range(len(self.stat)):
- lineno = self.stat[pc]
- if self.prog[lineno][0] == 'FOR':
- forinst = self.prog[lineno]
- loopvar = forinst[1]
- for i in range(pc+1,len(self.stat)):
- if self.prog[self.stat[i]][0] == 'NEXT':
- nextvar = self.prog[self.stat[i]][1]
- if nextvar != loopvar: continue
- self.loopend[pc] = i
- break
- else:
- print("FOR WITHOUT NEXT AT LINE %s" % self.stat[pc])
- self.error = 1
-
+ for pc in range(len(self.stat)):
+ lineno = self.stat[pc]
+ if self.prog[lineno][0] == 'FOR':
+ forinst = self.prog[lineno]
+ loopvar = forinst[1]
+ for i in range(pc + 1, len(self.stat)):
+ if self.prog[self.stat[i]][0] == 'NEXT':
+ nextvar = self.prog[self.stat[i]][1]
+ if nextvar != loopvar:
+ continue
+ self.loopend[pc] = i
+ break
+ else:
+ print("FOR WITHOUT NEXT AT LINE %s" % self.stat[pc])
+ self.error = 1
+
# Evaluate an expression
- def eval(self,expr):
+ def eval(self, expr):
etype = expr[0]
- if etype == 'NUM': return expr[1]
- elif etype == 'GROUP': return self.eval(expr[1])
+ if etype == 'NUM':
+ return expr[1]
+ elif etype == 'GROUP':
+ return self.eval(expr[1])
elif etype == 'UNARY':
- if expr[1] == '-': return -self.eval(expr[2])
+ if expr[1] == '-':
+ return -self.eval(expr[2])
elif etype == 'BINOP':
- if expr[1] == '+': return self.eval(expr[2])+self.eval(expr[3])
- elif expr[1] == '-': return self.eval(expr[2])-self.eval(expr[3])
- elif expr[1] == '*': return self.eval(expr[2])*self.eval(expr[3])
- elif expr[1] == '/': return float(self.eval(expr[2]))/self.eval(expr[3])
- elif expr[1] == '^': return abs(self.eval(expr[2]))**self.eval(expr[3])
+ if expr[1] == '+':
+ return self.eval(expr[2]) + self.eval(expr[3])
+ elif expr[1] == '-':
+ return self.eval(expr[2]) - self.eval(expr[3])
+ elif expr[1] == '*':
+ return self.eval(expr[2]) * self.eval(expr[3])
+ elif expr[1] == '/':
+ return float(self.eval(expr[2])) / self.eval(expr[3])
+ elif expr[1] == '^':
+ return abs(self.eval(expr[2]))**self.eval(expr[3])
elif etype == 'VAR':
- var,dim1,dim2 = expr[1]
- if not dim1 and not dim2:
- if var in self.vars:
- return self.vars[var]
- else:
- 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:
+ var, dim1, dim2 = expr[1]
+ if not dim1 and not dim2:
+ if var in self.vars:
+ return self.vars[var]
+ else:
+ 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 var in self.functions:
- # A function
- return self.functions[var](dim1)
+ # A function
+ return self.functions[var](dim1)
else:
- # A list evaluation
- 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 %s" % self.stat[self.pc])
- raise RuntimeError
- return self.lists[var][dim1val-1]
- if dim1 and dim2:
- 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 %s" % self.stat[self.pc])
- raise RuntimeError
- return self.tables[var][dim1val-1][dim2val-1]
- print("UNDEFINED VARIABLE %s AT LINE %s" % (var, self.stat[self.pc]))
- raise RuntimeError
+ # A list evaluation
+ 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 %s" %
+ self.stat[self.pc])
+ raise RuntimeError
+ return self.lists[var][dim1val - 1]
+ if dim1 and dim2:
+ 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 %s" %
+ self.stat[self.pc])
+ raise RuntimeError
+ return self.tables[var][dim1val - 1][dim2val - 1]
+ print("UNDEFINED VARIABLE %s AT LINE %s" %
+ (var, self.stat[self.pc]))
+ raise RuntimeError
# Evaluate a relational expression
- def releval(self,expr):
- etype = expr[1]
- lhs = self.eval(expr[2])
- rhs = self.eval(expr[3])
- if etype == '<':
- if lhs < rhs: return 1
- else: return 0
-
- elif etype == '<=':
- if lhs <= rhs: return 1
- else: return 0
-
- elif etype == '>':
- if lhs > rhs: return 1
- else: return 0
-
- elif etype == '>=':
- if lhs >= rhs: return 1
- else: return 0
-
- elif etype == '=':
- if lhs == rhs: return 1
- else: return 0
-
- elif etype == '<>':
- if lhs != rhs: return 1
- else: return 0
+ def releval(self, expr):
+ etype = expr[1]
+ lhs = self.eval(expr[2])
+ rhs = self.eval(expr[3])
+ if etype == '<':
+ if lhs < rhs:
+ return 1
+ else:
+ return 0
+
+ elif etype == '<=':
+ if lhs <= rhs:
+ return 1
+ else:
+ return 0
+
+ elif etype == '>':
+ if lhs > rhs:
+ return 1
+ else:
+ return 0
+
+ elif etype == '>=':
+ if lhs >= rhs:
+ return 1
+ else:
+ return 0
+
+ elif etype == '=':
+ if lhs == rhs:
+ return 1
+ else:
+ return 0
+
+ elif etype == '<>':
+ if lhs != rhs:
+ return 1
+ else:
+ return 0
# Assignment
- def assign(self,target,value):
+ def assign(self, target, value):
var, dim1, dim2 = target
if not dim1 and not dim2:
self.vars[var] = self.eval(value)
@@ -147,42 +173,44 @@ class BasicInterpreter:
# List assignment
dim1val = self.eval(dim1)
if not var in self.lists:
- self.lists[var] = [0]*10
+ self.lists[var] = [0] * 10
if dim1val > len(self.lists[var]):
- print ("DIMENSION TOO LARGE AT LINE %s" % self.stat[self.pc])
- raise RuntimeError
- self.lists[var][dim1val-1] = self.eval(value)
+ 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 var in self.tables:
- temp = [0]*10
- v = []
- for i in range(10): v.append(temp[:])
- self.tables[var] = v
+ 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 %s" % self.stat[self.pc])
- raise RuntimeError
- self.tables[var][dim1val-1][dim2val-1] = self.eval(value)
+ 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 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)
+ def goto(self, linenum):
+ 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)
# Run it
def run(self):
- self.vars = { } # All variables
- self.lists = { } # List variables
- self.tables = { } # Tables
- self.loops = [ ] # Currently active loops
- self.loopend= { } # Mapping saying where loops end
- self.gosub = None # Gosub return point (if any)
- self.error = 0 # Indicates program error
+ self.vars = {} # All variables
+ self.lists = {} # List variables
+ self.tables = {} # Tables
+ self.loops = [] # Currently active loops
+ self.loopend = {} # Mapping saying where loops end
+ self.gosub = None # Gosub return point (if any)
+ self.error = 0 # Indicates program error
self.stat = list(self.prog) # Ordered list of all line numbers
self.stat.sort()
@@ -194,248 +222,275 @@ class BasicInterpreter:
self.check_end()
self.check_loops()
- if self.error: raise RuntimeError
+ if self.error:
+ raise RuntimeError
while 1:
- line = self.stat[self.pc]
+ line = self.stat[self.pc]
instr = self.prog[line]
-
+
op = instr[0]
# END and STOP statements
if op == 'END' or op == 'STOP':
- break # We're done
+ break # We're done
# GOTO statement
elif op == 'GOTO':
- newline = instr[1]
- self.goto(newline)
- continue
+ newline = instr[1]
+ self.goto(newline)
+ continue
# PRINT statement
elif op == 'PRINT':
- plist = instr[1]
- out = ""
- for label,val in plist:
- if out:
- out += ' '*(15 - (len(out) % 15))
- out += label
- if val:
- if label: out += " "
- eval = self.eval(val)
- out += str(eval)
- sys.stdout.write(out)
- end = instr[2]
- if not (end == ',' or end == ';'):
- sys.stdout.write("\n")
- if end == ',': sys.stdout.write(" "*(15-(len(out) % 15)))
- if end == ';': sys.stdout.write(" "*(3-(len(out) % 3)))
-
+ plist = instr[1]
+ out = ""
+ for label, val in plist:
+ if out:
+ out += ' ' * (15 - (len(out) % 15))
+ out += label
+ if val:
+ if label:
+ out += " "
+ eval = self.eval(val)
+ out += str(eval)
+ sys.stdout.write(out)
+ end = instr[2]
+ if not (end == ',' or end == ';'):
+ sys.stdout.write("\n")
+ if end == ',':
+ sys.stdout.write(" " * (15 - (len(out) % 15)))
+ if end == ';':
+ sys.stdout.write(" " * (3 - (len(out) % 3)))
+
# LET statement
elif op == 'LET':
- target = instr[1]
- value = instr[2]
- self.assign(target,value)
+ target = instr[1]
+ value = instr[2]
+ self.assign(target, value)
# READ statement
elif op == 'READ':
- for target in instr[1]:
- if self.dc < len(self.data):
- value = ('NUM',self.data[self.dc])
- self.assign(target,value)
- self.dc += 1
- else:
- # No more data. Program ends
- return
+ for target in instr[1]:
+ if self.dc < len(self.data):
+ value = ('NUM', self.data[self.dc])
+ self.assign(target, value)
+ self.dc += 1
+ else:
+ # No more data. Program ends
+ return
elif op == 'IF':
- relop = instr[1]
- newline = instr[2]
- if (self.releval(relop)):
- self.goto(newline)
- continue
+ relop = instr[1]
+ newline = instr[2]
+ if (self.releval(relop)):
+ self.goto(newline)
+ continue
elif op == 'FOR':
- loopvar = instr[1]
- initval = instr[2]
- finval = instr[3]
- stepval = instr[4]
-
- # Check to see if this is a new loop
- if not self.loops or self.loops[-1][0] != self.pc:
- # Looks like a new loop. Make the initial assignment
- newvalue = initval
- self.assign((loopvar,None,None),initval)
- if not stepval: stepval = ('NUM',1)
- stepval = self.eval(stepval) # Evaluate step here
- self.loops.append((self.pc,stepval))
- else:
- # It's a repeat of the previous loop
- # Update the value of the loop variable according to the step
- stepval = ('NUM',self.loops[-1][1])
- newvalue = ('BINOP','+',('VAR',(loopvar,None,None)),stepval)
-
- if self.loops[-1][1] < 0: relop = '>='
- else: relop = '<='
- if not self.releval(('RELOP',relop,newvalue,finval)):
- # Loop is done. Jump to the NEXT
- self.pc = self.loopend[self.pc]
- self.loops.pop()
- else:
- self.assign((loopvar,None,None),newvalue)
+ loopvar = instr[1]
+ initval = instr[2]
+ finval = instr[3]
+ stepval = instr[4]
+
+ # Check to see if this is a new loop
+ if not self.loops or self.loops[-1][0] != self.pc:
+ # Looks like a new loop. Make the initial assignment
+ newvalue = initval
+ self.assign((loopvar, None, None), initval)
+ if not stepval:
+ stepval = ('NUM', 1)
+ stepval = self.eval(stepval) # Evaluate step here
+ self.loops.append((self.pc, stepval))
+ else:
+ # It's a repeat of the previous loop
+ # Update the value of the loop variable according to the
+ # step
+ stepval = ('NUM', self.loops[-1][1])
+ newvalue = (
+ 'BINOP', '+', ('VAR', (loopvar, None, None)), stepval)
+
+ if self.loops[-1][1] < 0:
+ relop = '>='
+ else:
+ relop = '<='
+ if not self.releval(('RELOP', relop, newvalue, finval)):
+ # Loop is done. Jump to the NEXT
+ self.pc = self.loopend[self.pc]
+ self.loops.pop()
+ else:
+ self.assign((loopvar, None, None), newvalue)
elif op == 'NEXT':
- if not self.loops:
- 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 %s" % line)
- return
- continue
+ if not self.loops:
+ 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 %s" % line)
+ return
+ continue
elif op == 'GOSUB':
- newline = instr[1]
- if self.gosub:
- print("ALREADY IN A SUBROUTINE AT LINE %s" % line)
- return
- self.gosub = self.stat[self.pc]
- self.goto(newline)
- continue
+ newline = instr[1]
+ if self.gosub:
+ 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 %s" % line)
- return
- self.goto(self.gosub)
- self.gosub = None
+ if not self.gosub:
+ print("RETURN WITHOUT A GOSUB AT LINE %s" % line)
+ return
+ self.goto(self.gosub)
+ self.gosub = None
elif op == 'FUNC':
- fname = instr[1]
- pname = instr[2]
- expr = instr[3]
- def eval_func(pvalue,name=pname,self=self,expr=expr):
- self.assign((pname,None,None),pvalue)
- return self.eval(expr)
- self.functions[fname] = eval_func
+ fname = instr[1]
+ pname = instr[2]
+ expr = instr[3]
+
+ def eval_func(pvalue, name=pname, self=self, expr=expr):
+ self.assign((pname, None, None), pvalue)
+ return self.eval(expr)
+ self.functions[fname] = eval_func
elif op == 'DIM':
- for vname,x,y in instr[1]:
- if y == 0:
- # Single dimension variable
- self.lists[vname] = [0]*x
- else:
- # Double dimension variable
- temp = [0]*y
- v = []
- for i in range(x):
- v.append(temp[:])
- self.tables[vname] = v
-
- self.pc += 1
+ for vname, x, y in instr[1]:
+ if y == 0:
+ # Single dimension variable
+ self.lists[vname] = [0] * x
+ else:
+ # Double dimension variable
+ temp = [0] * y
+ v = []
+ for i in range(x):
+ v.append(temp[:])
+ self.tables[vname] = v
+
+ self.pc += 1
# Utility functions for program listing
- def expr_str(self,expr):
+ def expr_str(self, expr):
etype = expr[0]
- if etype == 'NUM': return str(expr[1])
- elif etype == 'GROUP': return "(%s)" % self.expr_str(expr[1])
+ if etype == 'NUM':
+ return str(expr[1])
+ elif etype == 'GROUP':
+ return "(%s)" % self.expr_str(expr[1])
elif etype == 'UNARY':
- if expr[1] == '-': return "-"+str(expr[2])
+ if expr[1] == '-':
+ return "-" + str(expr[2])
elif etype == 'BINOP':
- return "%s %s %s" % (self.expr_str(expr[2]),expr[1],self.expr_str(expr[3]))
+ return "%s %s %s" % (self.expr_str(expr[2]), expr[1], self.expr_str(expr[3]))
elif etype == 'VAR':
- return self.var_str(expr[1])
+ return self.var_str(expr[1])
- def relexpr_str(self,expr):
- return "%s %s %s" % (self.expr_str(expr[2]),expr[1],self.expr_str(expr[3]))
+ def relexpr_str(self, expr):
+ return "%s %s %s" % (self.expr_str(expr[2]), expr[1], self.expr_str(expr[3]))
- def var_str(self,var):
- varname,dim1,dim2 = var
- if not dim1 and not dim2: return varname
- if dim1 and not dim2: return "%s(%s)" % (varname, self.expr_str(dim1))
- return "%s(%s,%s)" % (varname, self.expr_str(dim1),self.expr_str(dim2))
+ def var_str(self, var):
+ varname, dim1, dim2 = var
+ if not dim1 and not dim2:
+ return varname
+ if dim1 and not dim2:
+ return "%s(%s)" % (varname, self.expr_str(dim1))
+ return "%s(%s,%s)" % (varname, self.expr_str(dim1), self.expr_str(dim2))
# Create a program listing
def list(self):
- 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("%s %s" % (line, op))
- continue
- elif op == 'REM':
- print("%s %s" % (line, instr[1]))
- elif op == 'PRINT':
- _out = "%s %s " % (line, op)
- first = 1
- for p in instr[1]:
- 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]: _out += instr[2]
- print(_out)
- elif op == 'LET':
- print("%s LET %s = %s" % (line,self.var_str(instr[1]),self.expr_str(instr[2])))
- elif op == 'READ':
- _out = "%s READ " % line
- first = 1
- for r in instr[1]:
- if not first: _out += ","
- _out += self.var_str(r)
- first = 0
- print(_out)
- elif op == 'IF':
- print("%s IF %s THEN %d" % (line,self.relexpr_str(instr[1]),instr[2]))
- elif op == 'GOTO' or op == 'GOSUB':
- print("%s %s %s" % (line, op, instr[1]))
- elif op == 'FOR':
- _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("%s NEXT %s" % (line, instr[1]))
- elif op == 'FUNC':
- print("%s DEF %s(%s) = %s" % (line,instr[1],instr[2],self.expr_str(instr[3])))
- elif op == 'DIM':
- _out = "%s DIM " % line
- first = 1
- for vname,x,y in instr[1]:
- if not first: _out += ","
- first = 0
- if y == 0:
- _out += "%s(%d)" % (vname,x)
- else:
- _out += "%s(%d,%d)" % (vname,x,y)
-
- print(_out)
- elif op == 'DATA':
- _out = "%s DATA " % line
- first = 1
- for v in instr[1]:
- if not first: _out += ","
- first = 0
- _out += v
- print(_out)
+ 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("%s %s" % (line, op))
+ continue
+ elif op == 'REM':
+ print("%s %s" % (line, instr[1]))
+ elif op == 'PRINT':
+ _out = "%s %s " % (line, op)
+ first = 1
+ for p in instr[1]:
+ 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]:
+ _out += instr[2]
+ print(_out)
+ elif op == 'LET':
+ print("%s LET %s = %s" %
+ (line, self.var_str(instr[1]), self.expr_str(instr[2])))
+ elif op == 'READ':
+ _out = "%s READ " % line
+ first = 1
+ for r in instr[1]:
+ if not first:
+ _out += ","
+ _out += self.var_str(r)
+ first = 0
+ print(_out)
+ elif op == 'IF':
+ print("%s IF %s THEN %d" %
+ (line, self.relexpr_str(instr[1]), instr[2]))
+ elif op == 'GOTO' or op == 'GOSUB':
+ print("%s %s %s" % (line, op, instr[1]))
+ elif op == 'FOR':
+ _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("%s NEXT %s" % (line, instr[1]))
+ elif op == 'FUNC':
+ print("%s DEF %s(%s) = %s" %
+ (line, instr[1], instr[2], self.expr_str(instr[3])))
+ elif op == 'DIM':
+ _out = "%s DIM " % line
+ first = 1
+ for vname, x, y in instr[1]:
+ if not first:
+ _out += ","
+ first = 0
+ if y == 0:
+ _out += "%s(%d)" % (vname, x)
+ else:
+ _out += "%s(%d,%d)" % (vname, x, y)
+
+ print(_out)
+ elif op == 'DATA':
+ _out = "%s DATA " % line
+ first = 1
+ for v in instr[1]:
+ if not first:
+ _out += ","
+ first = 0
+ _out += v
+ print(_out)
# Erase the current program
def new(self):
- self.prog = {}
-
+ self.prog = {}
+
# Insert statements
- def add_statements(self,prog):
- for line,stat in prog.items():
- self.prog[line] = stat
+ def add_statements(self, prog):
+ for line, stat in prog.items():
+ self.prog[line] = stat
# Delete a statement
- def del_line(self,lineno):
- try:
- del self.prog[lineno]
- except KeyError:
- pass
-
+ def del_line(self, lineno):
+ try:
+ del self.prog[lineno]
+ except KeyError:
+ pass
diff --git a/example/BASIC/basparse.py b/example/BASIC/basparse.py
index ccdeb16..d610c7d 100644
--- a/example/BASIC/basparse.py
+++ b/example/BASIC/basparse.py
@@ -7,64 +7,72 @@ import basiclex
tokens = basiclex.tokens
precedence = (
- ('left', 'PLUS','MINUS'),
- ('left', 'TIMES','DIVIDE'),
- ('left', 'POWER'),
- ('right','UMINUS')
+ ('left', 'PLUS', 'MINUS'),
+ ('left', 'TIMES', 'DIVIDE'),
+ ('left', 'POWER'),
+ ('right', 'UMINUS')
)
-#### A BASIC program is a series of statements. We represent the program as a
-#### dictionary of tuples indexed by line number.
+# A BASIC program is a series of statements. We represent the program as a
+# dictionary of tuples indexed by line number.
+
def p_program(p):
'''program : program statement
| statement'''
if len(p) == 2 and p[1]:
- p[0] = { }
- line,stat = p[1]
- p[0][line] = stat
- elif len(p) ==3:
- p[0] = p[1]
- if not p[0]: p[0] = { }
- if p[2]:
- line,stat = p[2]
- p[0][line] = stat
-
-#### This catch-all rule is used for any catastrophic errors. In this case,
-#### we simply return nothing
+ p[0] = {}
+ line, stat = p[1]
+ p[0][line] = stat
+ elif len(p) == 3:
+ p[0] = p[1]
+ if not p[0]:
+ p[0] = {}
+ if p[2]:
+ line, stat = p[2]
+ p[0][line] = stat
+
+# This catch-all rule is used for any catastrophic errors. In this case,
+# we simply return nothing
+
def p_program_error(p):
'''program : error'''
p[0] = None
p.parser.error = 1
-#### Format of all BASIC statements.
+# Format of all BASIC statements.
+
def p_statement(p):
'''statement : INTEGER command NEWLINE'''
- if isinstance(p[2],str):
- print("%s %s %s" % (p[2],"AT LINE", p[1]))
+ if isinstance(p[2], str):
+ print("%s %s %s" % (p[2], "AT LINE", p[1]))
p[0] = None
p.parser.error = 1
else:
lineno = int(p[1])
- p[0] = (lineno,p[2])
+ p[0] = (lineno, p[2])
+
+# Interactive statements.
-#### Interactive statements.
def p_statement_interactive(p):
'''statement : RUN NEWLINE
| LIST NEWLINE
| NEW NEWLINE'''
- p[0] = (0, (p[1],0))
+ p[0] = (0, (p[1], 0))
+
+# Blank line number
+
-#### Blank line number
def p_statement_blank(p):
'''statement : INTEGER NEWLINE'''
- p[0] = (0,('BLANK',int(p[1])))
+ p[0] = (0, ('BLANK', int(p[1])))
+
+# Error handling for malformed statements
-#### Error handling for malformed statements
def p_statement_bad(p):
'''statement : INTEGER error NEWLINE'''
@@ -72,191 +80,226 @@ def p_statement_bad(p):
p[0] = None
p.parser.error = 1
-#### Blank line
+# Blank line
+
def p_statement_newline(p):
'''statement : NEWLINE'''
p[0] = None
-#### LET statement
+# LET statement
+
def p_command_let(p):
'''command : LET variable EQUALS expr'''
- p[0] = ('LET',p[2],p[4])
+ p[0] = ('LET', p[2], p[4])
+
def p_command_let_bad(p):
'''command : LET variable EQUALS error'''
p[0] = "BAD EXPRESSION IN LET"
-#### READ statement
+# READ statement
+
def p_command_read(p):
'''command : READ varlist'''
- p[0] = ('READ',p[2])
+ p[0] = ('READ', p[2])
+
def p_command_read_bad(p):
'''command : READ error'''
p[0] = "MALFORMED VARIABLE LIST IN READ"
-#### DATA statement
+# DATA statement
+
def p_command_data(p):
'''command : DATA numlist'''
- p[0] = ('DATA',p[2])
+ p[0] = ('DATA', p[2])
+
def p_command_data_bad(p):
'''command : DATA error'''
p[0] = "MALFORMED NUMBER LIST IN DATA"
-#### PRINT statement
+# PRINT statement
+
def p_command_print(p):
'''command : PRINT plist optend'''
- p[0] = ('PRINT',p[2],p[3])
+ p[0] = ('PRINT', p[2], p[3])
+
def p_command_print_bad(p):
'''command : PRINT error'''
p[0] = "MALFORMED PRINT STATEMENT"
-#### Optional ending on PRINT. Either a comma (,) or semicolon (;)
+# Optional ending on PRINT. Either a comma (,) or semicolon (;)
+
def p_optend(p):
'''optend : COMMA
| SEMI
|'''
- if len(p) == 2:
- p[0] = p[1]
+ if len(p) == 2:
+ p[0] = p[1]
else:
- p[0] = None
+ p[0] = None
+
+# PRINT statement with no arguments
-#### PRINT statement with no arguments
def p_command_print_empty(p):
'''command : PRINT'''
- p[0] = ('PRINT',[],None)
+ p[0] = ('PRINT', [], None)
+
+# GOTO statement
-#### GOTO statement
def p_command_goto(p):
'''command : GOTO INTEGER'''
- p[0] = ('GOTO',int(p[2]))
+ p[0] = ('GOTO', int(p[2]))
+
def p_command_goto_bad(p):
'''command : GOTO error'''
p[0] = "INVALID LINE NUMBER IN GOTO"
-#### IF-THEN statement
+# IF-THEN statement
+
def p_command_if(p):
'''command : IF relexpr THEN INTEGER'''
- p[0] = ('IF',p[2],int(p[4]))
+ p[0] = ('IF', p[2], int(p[4]))
+
def p_command_if_bad(p):
'''command : IF error THEN INTEGER'''
p[0] = "BAD RELATIONAL EXPRESSION"
+
def p_command_if_bad2(p):
'''command : IF relexpr THEN error'''
p[0] = "INVALID LINE NUMBER IN THEN"
-#### FOR statement
+# FOR statement
+
def p_command_for(p):
'''command : FOR ID EQUALS expr TO expr optstep'''
- p[0] = ('FOR',p[2],p[4],p[6],p[7])
+ p[0] = ('FOR', p[2], p[4], p[6], p[7])
+
def p_command_for_bad_initial(p):
'''command : FOR ID EQUALS error TO expr optstep'''
p[0] = "BAD INITIAL VALUE IN FOR STATEMENT"
+
def p_command_for_bad_final(p):
'''command : FOR ID EQUALS expr TO error optstep'''
p[0] = "BAD FINAL VALUE IN FOR STATEMENT"
+
def p_command_for_bad_step(p):
'''command : FOR ID EQUALS expr TO expr STEP error'''
p[0] = "MALFORMED STEP IN FOR STATEMENT"
-#### Optional STEP qualifier on FOR statement
+# Optional STEP qualifier on FOR statement
+
def p_optstep(p):
'''optstep : STEP expr
| empty'''
if len(p) == 3:
- p[0] = p[2]
+ p[0] = p[2]
else:
- p[0] = None
+ p[0] = None
+
+# NEXT statement
+
-#### NEXT statement
-
def p_command_next(p):
'''command : NEXT ID'''
- p[0] = ('NEXT',p[2])
+ p[0] = ('NEXT', p[2])
+
def p_command_next_bad(p):
'''command : NEXT error'''
p[0] = "MALFORMED NEXT"
-#### END statement
+# END statement
+
def p_command_end(p):
'''command : END'''
p[0] = ('END',)
-#### REM statement
+# REM statement
+
def p_command_rem(p):
'''command : REM'''
- p[0] = ('REM',p[1])
+ p[0] = ('REM', p[1])
+
+# STOP statement
-#### STOP statement
def p_command_stop(p):
'''command : STOP'''
p[0] = ('STOP',)
-#### DEF statement
+# DEF statement
+
def p_command_def(p):
'''command : DEF ID LPAREN ID RPAREN EQUALS expr'''
- p[0] = ('FUNC',p[2],p[4],p[7])
+ p[0] = ('FUNC', p[2], p[4], p[7])
+
def p_command_def_bad_rhs(p):
'''command : DEF ID LPAREN ID RPAREN EQUALS error'''
p[0] = "BAD EXPRESSION IN DEF STATEMENT"
+
def p_command_def_bad_arg(p):
'''command : DEF ID LPAREN error RPAREN EQUALS expr'''
p[0] = "BAD ARGUMENT IN DEF STATEMENT"
-#### GOSUB statement
+# GOSUB statement
+
def p_command_gosub(p):
'''command : GOSUB INTEGER'''
- p[0] = ('GOSUB',int(p[2]))
+ p[0] = ('GOSUB', int(p[2]))
+
def p_command_gosub_bad(p):
'''command : GOSUB error'''
p[0] = "INVALID LINE NUMBER IN GOSUB"
-#### RETURN statement
+# RETURN statement
+
def p_command_return(p):
'''command : RETURN'''
p[0] = ('RETURN',)
-#### DIM statement
+# DIM statement
+
def p_command_dim(p):
'''command : DIM dimlist'''
- p[0] = ('DIM',p[2])
+ p[0] = ('DIM', p[2])
+
def p_command_dim_bad(p):
'''command : DIM error'''
p[0] = "MALFORMED VARIABLE LIST IN DIM"
-#### List of variables supplied to DIM statement
+# List of variables supplied to DIM statement
+
def p_dimlist(p):
'''dimlist : dimlist COMMA dimitem
@@ -267,17 +310,20 @@ def p_dimlist(p):
else:
p[0] = [p[1]]
-#### DIM items
+# DIM items
+
def p_dimitem_single(p):
'''dimitem : ID LPAREN INTEGER RPAREN'''
- p[0] = (p[1],eval(p[3]),0)
+ p[0] = (p[1], eval(p[3]), 0)
+
def p_dimitem_double(p):
'''dimitem : ID LPAREN INTEGER COMMA INTEGER RPAREN'''
- p[0] = (p[1],eval(p[3]),eval(p[5]))
+ p[0] = (p[1], eval(p[3]), eval(p[5]))
+
+# Arithmetic expressions
-#### Arithmetic expressions
def p_expr_binary(p):
'''expr : expr PLUS expr
@@ -286,26 +332,31 @@ def p_expr_binary(p):
| expr DIVIDE expr
| expr POWER expr'''
- p[0] = ('BINOP',p[2],p[1],p[3])
+ p[0] = ('BINOP', p[2], p[1], p[3])
+
def p_expr_number(p):
'''expr : INTEGER
| FLOAT'''
- p[0] = ('NUM',eval(p[1]))
+ p[0] = ('NUM', eval(p[1]))
+
def p_expr_variable(p):
'''expr : variable'''
- p[0] = ('VAR',p[1])
+ p[0] = ('VAR', p[1])
+
def p_expr_group(p):
'''expr : LPAREN expr RPAREN'''
- p[0] = ('GROUP',p[2])
+ p[0] = ('GROUP', p[2])
+
def p_expr_unary(p):
'''expr : MINUS expr %prec UMINUS'''
- p[0] = ('UNARY','-',p[2])
+ p[0] = ('UNARY', '-', p[2])
+
+# Relational expressions
-#### Relational expressions
def p_relexpr(p):
'''relexpr : expr LT expr
@@ -314,111 +365,110 @@ def p_relexpr(p):
| expr GE expr
| expr EQUALS expr
| expr NE expr'''
- p[0] = ('RELOP',p[2],p[1],p[3])
+ p[0] = ('RELOP', p[2], p[1], p[3])
+
+# Variables
-#### Variables
def p_variable(p):
'''variable : ID
| ID LPAREN expr RPAREN
| ID LPAREN expr COMMA expr RPAREN'''
if len(p) == 2:
- p[0] = (p[1],None,None)
+ p[0] = (p[1], None, None)
elif len(p) == 5:
- p[0] = (p[1],p[3],None)
+ p[0] = (p[1], p[3], None)
else:
- p[0] = (p[1],p[3],p[5])
+ p[0] = (p[1], p[3], p[5])
+
+# Builds a list of variable targets as a Python list
-#### Builds a list of variable targets as a Python list
def p_varlist(p):
'''varlist : varlist COMMA variable
| variable'''
if len(p) > 2:
- p[0] = p[1]
- p[0].append(p[3])
+ p[0] = p[1]
+ p[0].append(p[3])
else:
- p[0] = [p[1]]
+ p[0] = [p[1]]
-#### Builds a list of numbers as a Python list
+# Builds a list of numbers as a Python list
def p_numlist(p):
'''numlist : numlist COMMA number
| number'''
if len(p) > 2:
- p[0] = p[1]
- p[0].append(p[3])
+ p[0] = p[1]
+ p[0].append(p[3])
else:
- p[0] = [p[1]]
+ p[0] = [p[1]]
+
+# A number. May be an integer or a float
-#### A number. May be an integer or a float
def p_number(p):
'''number : INTEGER
| FLOAT'''
p[0] = eval(p[1])
-#### A signed number.
+# A signed number.
+
def p_number_signed(p):
'''number : MINUS INTEGER
| MINUS FLOAT'''
- p[0] = eval("-"+p[2])
+ p[0] = eval("-" + p[2])
+
+# List of targets for a print statement
+# Returns a list of tuples (label,expr)
-#### List of targets for a print statement
-#### Returns a list of tuples (label,expr)
def p_plist(p):
'''plist : plist COMMA pitem
| pitem'''
if len(p) > 3:
- p[0] = p[1]
- p[0].append(p[3])
+ p[0] = p[1]
+ p[0].append(p[3])
else:
- p[0] = [p[1]]
+ p[0] = [p[1]]
+
def p_item_string(p):
'''pitem : STRING'''
- p[0] = (p[1][1:-1],None)
+ p[0] = (p[1][1:-1], None)
+
def p_item_string_expr(p):
'''pitem : STRING expr'''
- p[0] = (p[1][1:-1],p[2])
+ p[0] = (p[1][1:-1], p[2])
+
def p_item_expr(p):
'''pitem : expr'''
- p[0] = ("",p[1])
+ p[0] = ("", p[1])
+
+# Empty
+
-#### Empty
-
def p_empty(p):
'''empty : '''
-#### Catastrophic error handler
+# Catastrophic error handler
+
+
def p_error(p):
if not p:
print("SYNTAX ERROR AT EOF")
bparser = yacc.yacc()
-def parse(data,debug=0):
+
+def parse(data, debug=0):
bparser.error = 0
- p = bparser.parse(data,debug=debug)
- if bparser.error: return None
+ p = bparser.parse(data, debug=debug)
+ if bparser.error:
+ return None
return p
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/example/GardenSnake/GardenSnake.py b/example/GardenSnake/GardenSnake.py
index 2a7f45e..8b493b4 100644
--- a/example/GardenSnake/GardenSnake.py
+++ b/example/GardenSnake/GardenSnake.py
@@ -37,7 +37,7 @@
# Modifications for inclusion in PLY distribution
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
from ply import *
##### Lexer ######
@@ -69,18 +69,21 @@ tokens = (
'INDENT',
'DEDENT',
'ENDMARKER',
- )
+)
#t_NUMBER = r'\d+'
# taken from decmial.py but without the leading sign
+
+
def t_NUMBER(t):
r"""(\d+(\.\d*)?|\.\d+)([eE][-+]? \d+)?"""
t.value = decimal.Decimal(t.value)
return t
+
def t_STRING(t):
r"'([^\\']+|\\'|\\\\)*'" # I think this is right ...
- t.value=t.value[1:-1].decode("string-escape") # .swapcase() # for fun
+ t.value = t.value[1:-1].decode("string-escape") # .swapcase() # for fun
return t
t_COLON = r':'
@@ -98,10 +101,11 @@ t_SEMICOLON = r';'
# Ply nicely documented how to do this.
RESERVED = {
- "def": "DEF",
- "if": "IF",
- "return": "RETURN",
- }
+ "def": "DEF",
+ "if": "IF",
+ "return": "RETURN",
+}
+
def t_NAME(t):
r'[a-zA-Z_][a-zA-Z0-9_]*'
@@ -111,6 +115,8 @@ def t_NAME(t):
# Putting this before t_WS let it consume lines with only comments in
# them so the latter code never sees the WS part. Not consuming the
# newline. Needed for "if 1: #comment"
+
+
def t_comment(t):
r"[ ]*\043[^\n]*" # \043 is '#'
pass
@@ -125,6 +131,8 @@ def t_WS(t):
# Don't generate newline tokens when inside of parenthesis, eg
# a = (1,
# 2, 3)
+
+
def t_newline(t):
r'\n+'
t.lexer.lineno += len(t.value)
@@ -132,11 +140,13 @@ def t_newline(t):
if t.lexer.paren_count == 0:
return t
+
def t_LPAR(t):
r'\('
t.lexer.paren_count += 1
return t
+
def t_RPAR(t):
r'\)'
# check for underflow? should be the job of the parser
@@ -149,7 +159,7 @@ def t_error(t):
print "Skipping", repr(t.value[0])
t.lexer.skip(1)
-## I implemented INDENT / DEDENT generation as a post-processing filter
+# I implemented INDENT / DEDENT generation as a post-processing filter
# The original lex token stream contains WS and NEWLINE characters.
# WS will only occur before any other tokens on a line.
@@ -169,6 +179,8 @@ MAY_INDENT = 1
MUST_INDENT = 2
# only care about whitespace at the start of a line
+
+
def track_tokens_filter(lexer, tokens):
lexer.at_line_start = at_line_start = True
indent = NO_INDENT
@@ -180,7 +192,7 @@ def track_tokens_filter(lexer, tokens):
at_line_start = False
indent = MAY_INDENT
token.must_indent = False
-
+
elif token.type == "NEWLINE":
at_line_start = True
if indent == MAY_INDENT:
@@ -204,6 +216,7 @@ def track_tokens_filter(lexer, tokens):
yield token
lexer.at_line_start = at_line_start
+
def _new_token(type, lineno):
tok = lex.LexToken()
tok.type = type
@@ -212,10 +225,14 @@ def _new_token(type, lineno):
return tok
# Synthesize a DEDENT tag
+
+
def DEDENT(lineno):
return _new_token("DEDENT", lineno)
# Synthesize an INDENT tag
+
+
def INDENT(lineno):
return _new_token("INDENT", lineno)
@@ -228,14 +245,14 @@ def indentation_filter(tokens):
depth = 0
prev_was_ws = False
for token in tokens:
-## if 1:
-## print "Process", token,
-## if token.at_line_start:
-## print "at_line_start",
-## if token.must_indent:
-## print "must_indent",
-## print
-
+ # if 1:
+ # print "Process", token,
+ # if token.at_line_start:
+ # print "at_line_start",
+ # if token.must_indent:
+ # print "must_indent",
+ # print
+
# WS only occurs at the start of the line
# There may be WS followed by NEWLINE so
# only track the depth here. Don't indent/dedent
@@ -274,14 +291,15 @@ def indentation_filter(tokens):
# At the same level
pass
elif depth > levels[-1]:
- raise IndentationError("indentation increase but not in new block")
+ raise IndentationError(
+ "indentation increase but not in new block")
else:
# Back up; but only if it matches a previous level
try:
i = levels.index(depth)
except ValueError:
raise IndentationError("inconsistent indentation")
- for _ in range(i+1, len(levels)):
+ for _ in range(i + 1, len(levels)):
yield DEDENT(token.lineno)
levels.pop()
@@ -294,11 +312,11 @@ def indentation_filter(tokens):
assert token is not None
for _ in range(1, len(levels)):
yield DEDENT(token.lineno)
-
+
# The top-level filter adds an ENDMARKER, if requested.
# Python's grammar uses it.
-def filter(lexer, add_endmarker = True):
+def filter(lexer, add_endmarker=True):
token = None
tokens = iter(lexer.token, None)
tokens = track_tokens_filter(lexer, tokens)
@@ -313,14 +331,19 @@ def filter(lexer, add_endmarker = True):
# Combine Ply and my filters into a new lexer
+
class IndentLexer(object):
+
def __init__(self, debug=0, optimize=0, lextab='lextab', reflags=0):
- self.lexer = lex.lex(debug=debug, optimize=optimize, lextab=lextab, reflags=reflags)
+ self.lexer = lex.lex(debug=debug, optimize=optimize,
+ lextab=lextab, reflags=reflags)
self.token_stream = None
+
def input(self, s, add_endmarker=True):
self.lexer.paren_count = 0
self.lexer.input(s)
self.token_stream = filter(self.lexer, add_endmarker)
+
def token(self):
try:
return self.token_stream.next()
@@ -336,6 +359,8 @@ class IndentLexer(object):
from compiler import ast
# Helper function
+
+
def Assign(left, right):
names = []
if isinstance(left, ast.Name):
@@ -356,35 +381,39 @@ def Assign(left, right):
# The grammar comments come from Python's Grammar/Grammar file
-## NB: compound_stmt in single_input is followed by extra NEWLINE!
+# NB: compound_stmt in single_input is followed by extra NEWLINE!
# file_input: (NEWLINE | stmt)* ENDMARKER
def p_file_input_end(p):
"""file_input_end : file_input ENDMARKER"""
p[0] = ast.Stmt(p[1])
+
+
def p_file_input(p):
"""file_input : file_input NEWLINE
| file_input stmt
| NEWLINE
| stmt"""
- if isinstance(p[len(p)-1], basestring):
+ if isinstance(p[len(p) - 1], basestring):
if len(p) == 3:
p[0] = p[1]
else:
- p[0] = [] # p == 2 --> only a blank line
+ p[0] = [] # p == 2 --> only a blank line
else:
if len(p) == 3:
p[0] = p[1] + p[2]
else:
p[0] = p[1]
-
+
# funcdef: [decorators] 'def' NAME parameters ':' suite
# ignoring decorators
def p_funcdef(p):
"funcdef : DEF NAME parameters COLON suite"
p[0] = ast.Function(None, p[2], tuple(p[3]), (), 0, None, p[5])
-
+
# parameters: '(' [varargslist] ')'
+
+
def p_parameters(p):
"""parameters : LPAR RPAR
| LPAR varargslist RPAR"""
@@ -392,9 +421,9 @@ def p_parameters(p):
p[0] = []
else:
p[0] = p[2]
-
-# varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) |
+
+# varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) |
# highly simplified
def p_varargslist(p):
"""varargslist : varargslist COMMA NAME
@@ -405,21 +434,27 @@ def p_varargslist(p):
p[0] = [p[1]]
# stmt: simple_stmt | compound_stmt
+
+
def p_stmt_simple(p):
"""stmt : simple_stmt"""
# simple_stmt is a list
p[0] = p[1]
-
+
+
def p_stmt_compound(p):
"""stmt : compound_stmt"""
p[0] = [p[1]]
# simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
+
+
def p_simple_stmt(p):
"""simple_stmt : small_stmts NEWLINE
| small_stmts SEMICOLON NEWLINE"""
p[0] = p[1]
+
def p_small_stmts(p):
"""small_stmts : small_stmts SEMICOLON small_stmt
| small_stmt"""
@@ -430,6 +465,8 @@ def p_small_stmts(p):
# small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt |
# import_stmt | global_stmt | exec_stmt | assert_stmt
+
+
def p_small_stmt(p):
"""small_stmt : flow_stmt
| expr_stmt"""
@@ -439,6 +476,8 @@ def p_small_stmt(p):
# ('=' (yield_expr|testlist))*)
# augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
# '<<=' | '>>=' | '**=' | '//=')
+
+
def p_expr_stmt(p):
"""expr_stmt : testlist ASSIGN testlist
| testlist """
@@ -448,11 +487,14 @@ def p_expr_stmt(p):
else:
p[0] = Assign(p[1], p[3])
+
def p_flow_stmt(p):
"flow_stmt : return_stmt"
p[0] = p[1]
# return_stmt: 'return' [testlist]
+
+
def p_return_stmt(p):
"return_stmt : RETURN testlist"
p[0] = ast.Return(p[2])
@@ -463,10 +505,12 @@ def p_compound_stmt(p):
| funcdef"""
p[0] = p[1]
+
def p_if_stmt(p):
'if_stmt : IF test COLON suite'
p[0] = ast.If([(p[2], p[4])], None)
+
def p_suite(p):
"""suite : simple_stmt
| NEWLINE INDENT stmts DEDENT"""
@@ -474,7 +518,7 @@ def p_suite(p):
p[0] = ast.Stmt(p[1])
else:
p[0] = ast.Stmt(p[3])
-
+
def p_stmts(p):
"""stmts : stmts stmt
@@ -484,7 +528,7 @@ def p_stmts(p):
else:
p[0] = p[1]
-## No using Python's approach because Ply supports precedence
+# No using Python's approach because Ply supports precedence
# comparison: expr (comp_op expr)*
# arith_expr: term (('+'|'-') term)*
@@ -492,12 +536,17 @@ def p_stmts(p):
# factor: ('+'|'-'|'~') factor | power
# comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
+
def make_lt_compare((left, right)):
- return ast.Compare(left, [('<', right),])
+ return ast.Compare(left, [('<', right), ])
+
+
def make_gt_compare((left, right)):
- return ast.Compare(left, [('>', right),])
+ return ast.Compare(left, [('>', right), ])
+
+
def make_eq_compare((left, right)):
- return ast.Compare(left, [('==', right),])
+ return ast.Compare(left, [('==', right), ])
binary_ops = {
@@ -512,12 +561,13 @@ binary_ops = {
unary_ops = {
"+": ast.UnaryAdd,
"-": ast.UnarySub,
- }
+}
precedence = (
("left", "EQ", "GT", "LT"),
("left", "PLUS", "MINUS"),
("left", "MULT", "DIV"),
- )
+)
+
def p_comparison(p):
"""comparison : comparison PLUS comparison
@@ -536,10 +586,12 @@ def p_comparison(p):
p[0] = unary_ops[p[1]](p[2])
else:
p[0] = p[1]
-
+
# power: atom trailer* ['**' factor]
# trailers enables function calls. I only allow one level of calls
# so this is 'trailer'
+
+
def p_power(p):
"""power : atom
| atom trailer"""
@@ -551,26 +603,33 @@ def p_power(p):
else:
raise AssertionError("not implemented")
+
def p_atom_name(p):
"""atom : NAME"""
p[0] = ast.Name(p[1])
+
def p_atom_number(p):
"""atom : NUMBER
| STRING"""
p[0] = ast.Const(p[1])
+
def p_atom_tuple(p):
"""atom : LPAR testlist RPAR"""
p[0] = p[2]
# trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
+
+
def p_trailer(p):
"trailer : LPAR arglist RPAR"
p[0] = ("CALL", p[2])
# testlist: test (',' test)* [',']
# Contains shift/reduce error
+
+
def p_testlist(p):
"""testlist : testlist_multi COMMA
| testlist_multi """
@@ -586,6 +645,7 @@ def p_testlist(p):
if isinstance(p[0], list):
p[0] = ast.Tuple(p[0])
+
def p_testlist_multi(p):
"""testlist_multi : testlist_multi COMMA test
| test"""
@@ -605,7 +665,6 @@ def p_testlist_multi(p):
def p_test(p):
"test : comparison"
p[0] = p[1]
-
# arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test)
@@ -619,17 +678,21 @@ def p_arglist(p):
p[0] = [p[1]]
# argument: test [gen_for] | test '=' test # Really [keyword '='] test
+
+
def p_argument(p):
"argument : test"
p[0] = p[1]
+
def p_error(p):
- #print "Error!", repr(p)
+ # print "Error!", repr(p)
raise SyntaxError(p)
class GardenSnakeParser(object):
- def __init__(self, lexer = None):
+
+ def __init__(self, lexer=None):
if lexer is None:
lexer = IndentLexer()
self.lexer = lexer
@@ -637,20 +700,23 @@ class GardenSnakeParser(object):
def parse(self, code):
self.lexer.input(code)
- result = self.parser.parse(lexer = self.lexer)
+ result = self.parser.parse(lexer=self.lexer)
return ast.Module(None, result)
###### Code generation ######
-
+
from compiler import misc, syntax, pycodegen
+
class GardenSnakeCompiler(object):
+
def __init__(self):
self.parser = GardenSnakeParser()
+
def compile(self, code, filename="<string>"):
tree = self.parser.parse(code)
- #print tree
+ # print tree
misc.set_filename(filename, tree)
syntax.check(tree)
gen = pycodegen.ModuleCodeGenerator(tree)
@@ -658,7 +724,7 @@ class GardenSnakeCompiler(object):
return code
####### Test code #######
-
+
compile = GardenSnakeCompiler().compile
code = r"""
@@ -698,8 +764,10 @@ print('BIG DECIMAL', 1.234567891234567e12345)
"""
# Set up the GardenSnake run-time environment
+
+
def print_(*args):
- print "-->", " ".join(map(str,args))
+ print "-->", " ".join(map(str, args))
globals()["print"] = print_
diff --git a/example/ansic/clex.py b/example/ansic/clex.py
index 407757d..4bde1d7 100644
--- a/example/ansic/clex.py
+++ b/example/ansic/clex.py
@@ -5,7 +5,7 @@
# ----------------------------------------------------------------------
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
import ply.lex as lex
@@ -15,10 +15,11 @@ reserved = (
'ELSE', 'ENUM', 'EXTERN', 'FLOAT', 'FOR', 'GOTO', 'IF', 'INT', 'LONG', 'REGISTER',
'RETURN', 'SHORT', 'SIGNED', 'SIZEOF', 'STATIC', 'STRUCT', 'SWITCH', 'TYPEDEF',
'UNION', 'UNSIGNED', 'VOID', 'VOLATILE', 'WHILE',
- )
+)
tokens = reserved + (
- # Literals (identifier, integer constant, float constant, string constant, char const)
+ # Literals (identifier, integer constant, float constant, string constant,
+ # char const)
'ID', 'TYPEID', 'ICONST', 'FCONST', 'SCONST', 'CCONST',
# Operators (+,-,*,/,%,|,&,~,^,<<,>>, ||, &&, !, <, <=, >, >=, ==, !=)
@@ -26,10 +27,10 @@ tokens = reserved + (
'OR', 'AND', 'NOT', 'XOR', 'LSHIFT', 'RSHIFT',
'LOR', 'LAND', 'LNOT',
'LT', 'LE', 'GT', 'GE', 'EQ', 'NE',
-
+
# Assignment (=, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=)
'EQUALS', 'TIMESEQUAL', 'DIVEQUAL', 'MODEQUAL', 'PLUSEQUAL', 'MINUSEQUAL',
- 'LSHIFTEQUAL','RSHIFTEQUAL', 'ANDEQUAL', 'XOREQUAL', 'OREQUAL',
+ 'LSHIFTEQUAL', 'RSHIFTEQUAL', 'ANDEQUAL', 'XOREQUAL', 'OREQUAL',
# Increment/decrement (++,--)
'PLUSPLUS', 'MINUSMINUS',
@@ -39,7 +40,7 @@ tokens = reserved + (
# Conditional operator (?)
'CONDOP',
-
+
# Delimeters ( ) [ ] { } , . ; :
'LPAREN', 'RPAREN',
'LBRACKET', 'RBRACKET',
@@ -48,84 +49,87 @@ tokens = reserved + (
# Ellipsis (...)
'ELLIPSIS',
- )
+)
# Completely ignored characters
-t_ignore = ' \t\x0c'
+t_ignore = ' \t\x0c'
# Newlines
+
+
def t_NEWLINE(t):
r'\n+'
t.lexer.lineno += t.value.count("\n")
-
+
# Operators
-t_PLUS = r'\+'
-t_MINUS = r'-'
-t_TIMES = r'\*'
-t_DIVIDE = r'/'
-t_MOD = r'%'
-t_OR = r'\|'
-t_AND = r'&'
-t_NOT = r'~'
-t_XOR = r'\^'
-t_LSHIFT = r'<<'
-t_RSHIFT = r'>>'
-t_LOR = r'\|\|'
-t_LAND = r'&&'
-t_LNOT = r'!'
-t_LT = r'<'
-t_GT = r'>'
-t_LE = r'<='
-t_GE = r'>='
-t_EQ = r'=='
-t_NE = r'!='
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_TIMES = r'\*'
+t_DIVIDE = r'/'
+t_MOD = r'%'
+t_OR = r'\|'
+t_AND = r'&'
+t_NOT = r'~'
+t_XOR = r'\^'
+t_LSHIFT = r'<<'
+t_RSHIFT = r'>>'
+t_LOR = r'\|\|'
+t_LAND = r'&&'
+t_LNOT = r'!'
+t_LT = r'<'
+t_GT = r'>'
+t_LE = r'<='
+t_GE = r'>='
+t_EQ = r'=='
+t_NE = r'!='
# Assignment operators
-t_EQUALS = r'='
-t_TIMESEQUAL = r'\*='
-t_DIVEQUAL = r'/='
-t_MODEQUAL = r'%='
-t_PLUSEQUAL = r'\+='
-t_MINUSEQUAL = r'-='
-t_LSHIFTEQUAL = r'<<='
-t_RSHIFTEQUAL = r'>>='
-t_ANDEQUAL = r'&='
-t_OREQUAL = r'\|='
-t_XOREQUAL = r'\^='
+t_EQUALS = r'='
+t_TIMESEQUAL = r'\*='
+t_DIVEQUAL = r'/='
+t_MODEQUAL = r'%='
+t_PLUSEQUAL = r'\+='
+t_MINUSEQUAL = r'-='
+t_LSHIFTEQUAL = r'<<='
+t_RSHIFTEQUAL = r'>>='
+t_ANDEQUAL = r'&='
+t_OREQUAL = r'\|='
+t_XOREQUAL = r'\^='
# Increment/decrement
-t_PLUSPLUS = r'\+\+'
-t_MINUSMINUS = r'--'
+t_PLUSPLUS = r'\+\+'
+t_MINUSMINUS = r'--'
# ->
-t_ARROW = r'->'
+t_ARROW = r'->'
# ?
-t_CONDOP = r'\?'
+t_CONDOP = r'\?'
# Delimeters
-t_LPAREN = r'\('
-t_RPAREN = r'\)'
-t_LBRACKET = r'\['
-t_RBRACKET = r'\]'
-t_LBRACE = r'\{'
-t_RBRACE = r'\}'
-t_COMMA = r','
-t_PERIOD = r'\.'
-t_SEMI = r';'
-t_COLON = r':'
-t_ELLIPSIS = r'\.\.\.'
+t_LPAREN = r'\('
+t_RPAREN = r'\)'
+t_LBRACKET = r'\['
+t_RBRACKET = r'\]'
+t_LBRACE = r'\{'
+t_RBRACE = r'\}'
+t_COMMA = r','
+t_PERIOD = r'\.'
+t_SEMI = r';'
+t_COLON = r':'
+t_ELLIPSIS = r'\.\.\.'
# Identifiers and reserved words
-reserved_map = { }
+reserved_map = {}
for r in reserved:
reserved_map[r.lower()] = r
+
def t_ID(t):
r'[A-Za-z_][\w_]*'
- t.type = reserved_map.get(t.value,"ID")
+ t.type = reserved_map.get(t.value, "ID")
return t
# Integer literal
@@ -141,24 +145,24 @@ t_SCONST = r'\"([^\\\n]|(\\.))*?\"'
t_CCONST = r'(L)?\'([^\\\n]|(\\.))*?\''
# Comments
+
+
def t_comment(t):
r'/\*(.|\n)*?\*/'
t.lexer.lineno += t.value.count('\n')
# Preprocessor directive (ignored)
+
+
def t_preprocessor(t):
r'\#(.)*?\n'
t.lexer.lineno += 1
-
+
+
def t_error(t):
print("Illegal character %s" % repr(t.value[0]))
t.lexer.skip(1)
-
+
lexer = lex.lex()
if __name__ == "__main__":
lex.runmain(lexer)
-
-
-
-
-
diff --git a/example/ansic/cparse.py b/example/ansic/cparse.py
index 5c6932c..5fe9bce 100644
--- a/example/ansic/cparse.py
+++ b/example/ansic/cparse.py
@@ -13,88 +13,109 @@ tokens = clex.tokens
# translation-unit:
+
def p_translation_unit_1(t):
'translation_unit : external_declaration'
pass
+
def p_translation_unit_2(t):
'translation_unit : translation_unit external_declaration'
pass
# external-declaration:
+
def p_external_declaration_1(t):
'external_declaration : function_definition'
pass
+
def p_external_declaration_2(t):
'external_declaration : declaration'
pass
# function-definition:
+
def p_function_definition_1(t):
'function_definition : declaration_specifiers declarator declaration_list compound_statement'
pass
+
def p_function_definition_2(t):
'function_definition : declarator declaration_list compound_statement'
pass
+
def p_function_definition_3(t):
'function_definition : declarator compound_statement'
pass
+
def p_function_definition_4(t):
'function_definition : declaration_specifiers declarator compound_statement'
pass
# declaration:
+
def p_declaration_1(t):
'declaration : declaration_specifiers init_declarator_list SEMI'
pass
+
def p_declaration_2(t):
'declaration : declaration_specifiers SEMI'
pass
# declaration-list:
+
def p_declaration_list_1(t):
'declaration_list : declaration'
pass
+
def p_declaration_list_2(t):
'declaration_list : declaration_list declaration '
pass
# declaration-specifiers
+
+
def p_declaration_specifiers_1(t):
'declaration_specifiers : storage_class_specifier declaration_specifiers'
pass
+
def p_declaration_specifiers_2(t):
'declaration_specifiers : type_specifier declaration_specifiers'
pass
+
def p_declaration_specifiers_3(t):
'declaration_specifiers : type_qualifier declaration_specifiers'
pass
+
def p_declaration_specifiers_4(t):
'declaration_specifiers : storage_class_specifier'
pass
+
def p_declaration_specifiers_5(t):
'declaration_specifiers : type_specifier'
pass
+
def p_declaration_specifiers_6(t):
'declaration_specifiers : type_qualifier'
pass
# storage-class-specifier
+
+
def p_storage_class_specifier(t):
'''storage_class_specifier : AUTO
| REGISTER
@@ -105,6 +126,8 @@ def p_storage_class_specifier(t):
pass
# type-specifier:
+
+
def p_type_specifier(t):
'''type_specifier : VOID
| CHAR
@@ -122,6 +145,8 @@ def p_type_specifier(t):
pass
# type-qualifier:
+
+
def p_type_qualifier(t):
'''type_qualifier : CONST
| VOLATILE'''
@@ -129,19 +154,24 @@ def p_type_qualifier(t):
# struct-or-union-specifier
+
def p_struct_or_union_specifier_1(t):
'struct_or_union_specifier : struct_or_union ID LBRACE struct_declaration_list RBRACE'
pass
+
def p_struct_or_union_specifier_2(t):
'struct_or_union_specifier : struct_or_union LBRACE struct_declaration_list RBRACE'
pass
+
def p_struct_or_union_specifier_3(t):
'struct_or_union_specifier : struct_or_union ID'
pass
# struct-or-union:
+
+
def p_struct_or_union(t):
'''struct_or_union : STRUCT
| UNION
@@ -150,221 +180,273 @@ def p_struct_or_union(t):
# struct-declaration-list:
+
def p_struct_declaration_list_1(t):
'struct_declaration_list : struct_declaration'
pass
+
def p_struct_declaration_list_2(t):
'struct_declaration_list : struct_declaration_list struct_declaration'
pass
# init-declarator-list:
+
def p_init_declarator_list_1(t):
'init_declarator_list : init_declarator'
pass
+
def p_init_declarator_list_2(t):
'init_declarator_list : init_declarator_list COMMA init_declarator'
pass
# init-declarator
+
def p_init_declarator_1(t):
'init_declarator : declarator'
pass
+
def p_init_declarator_2(t):
'init_declarator : declarator EQUALS initializer'
pass
# struct-declaration:
+
def p_struct_declaration(t):
'struct_declaration : specifier_qualifier_list struct_declarator_list SEMI'
pass
# specifier-qualifier-list:
+
def p_specifier_qualifier_list_1(t):
'specifier_qualifier_list : type_specifier specifier_qualifier_list'
pass
+
def p_specifier_qualifier_list_2(t):
'specifier_qualifier_list : type_specifier'
pass
+
def p_specifier_qualifier_list_3(t):
'specifier_qualifier_list : type_qualifier specifier_qualifier_list'
pass
+
def p_specifier_qualifier_list_4(t):
'specifier_qualifier_list : type_qualifier'
pass
# struct-declarator-list:
+
def p_struct_declarator_list_1(t):
'struct_declarator_list : struct_declarator'
pass
+
def p_struct_declarator_list_2(t):
'struct_declarator_list : struct_declarator_list COMMA struct_declarator'
pass
# struct-declarator:
+
def p_struct_declarator_1(t):
'struct_declarator : declarator'
pass
+
def p_struct_declarator_2(t):
'struct_declarator : declarator COLON constant_expression'
pass
+
def p_struct_declarator_3(t):
'struct_declarator : COLON constant_expression'
pass
# enum-specifier:
+
def p_enum_specifier_1(t):
'enum_specifier : ENUM ID LBRACE enumerator_list RBRACE'
pass
+
def p_enum_specifier_2(t):
'enum_specifier : ENUM LBRACE enumerator_list RBRACE'
pass
+
def p_enum_specifier_3(t):
'enum_specifier : ENUM ID'
pass
# enumerator_list:
+
+
def p_enumerator_list_1(t):
'enumerator_list : enumerator'
pass
+
def p_enumerator_list_2(t):
'enumerator_list : enumerator_list COMMA enumerator'
pass
# enumerator:
+
+
def p_enumerator_1(t):
'enumerator : ID'
pass
+
def p_enumerator_2(t):
'enumerator : ID EQUALS constant_expression'
pass
# declarator:
+
def p_declarator_1(t):
'declarator : pointer direct_declarator'
pass
+
def p_declarator_2(t):
'declarator : direct_declarator'
pass
# direct-declarator:
+
def p_direct_declarator_1(t):
'direct_declarator : ID'
pass
+
def p_direct_declarator_2(t):
'direct_declarator : LPAREN declarator RPAREN'
pass
+
def p_direct_declarator_3(t):
'direct_declarator : direct_declarator LBRACKET constant_expression_opt RBRACKET'
pass
+
def p_direct_declarator_4(t):
'direct_declarator : direct_declarator LPAREN parameter_type_list RPAREN '
pass
+
def p_direct_declarator_5(t):
'direct_declarator : direct_declarator LPAREN identifier_list RPAREN '
pass
+
def p_direct_declarator_6(t):
'direct_declarator : direct_declarator LPAREN RPAREN '
pass
# pointer:
+
+
def p_pointer_1(t):
'pointer : TIMES type_qualifier_list'
pass
+
def p_pointer_2(t):
'pointer : TIMES'
pass
+
def p_pointer_3(t):
'pointer : TIMES type_qualifier_list pointer'
pass
+
def p_pointer_4(t):
'pointer : TIMES pointer'
pass
# type-qualifier-list:
+
def p_type_qualifier_list_1(t):
'type_qualifier_list : type_qualifier'
pass
+
def p_type_qualifier_list_2(t):
'type_qualifier_list : type_qualifier_list type_qualifier'
pass
# parameter-type-list:
+
def p_parameter_type_list_1(t):
'parameter_type_list : parameter_list'
pass
+
def p_parameter_type_list_2(t):
'parameter_type_list : parameter_list COMMA ELLIPSIS'
pass
# parameter-list:
+
def p_parameter_list_1(t):
'parameter_list : parameter_declaration'
pass
+
def p_parameter_list_2(t):
'parameter_list : parameter_list COMMA parameter_declaration'
pass
# parameter-declaration:
+
+
def p_parameter_declaration_1(t):
'parameter_declaration : declaration_specifiers declarator'
pass
+
def p_parameter_declaration_2(t):
'parameter_declaration : declaration_specifiers abstract_declarator_opt'
pass
# identifier-list:
+
+
def p_identifier_list_1(t):
'identifier_list : ID'
pass
+
def p_identifier_list_2(t):
'identifier_list : identifier_list COMMA ID'
pass
# initializer:
+
def p_initializer_1(t):
'initializer : assignment_expression'
pass
+
def p_initializer_2(t):
'''initializer : LBRACE initializer_list RBRACE
| LBRACE initializer_list COMMA RBRACE'''
@@ -372,84 +454,102 @@ def p_initializer_2(t):
# initializer-list:
+
def p_initializer_list_1(t):
'initializer_list : initializer'
pass
+
def p_initializer_list_2(t):
'initializer_list : initializer_list COMMA initializer'
pass
# type-name:
+
def p_type_name(t):
'type_name : specifier_qualifier_list abstract_declarator_opt'
pass
+
def p_abstract_declarator_opt_1(t):
'abstract_declarator_opt : empty'
pass
+
def p_abstract_declarator_opt_2(t):
'abstract_declarator_opt : abstract_declarator'
pass
# abstract-declarator:
+
def p_abstract_declarator_1(t):
'abstract_declarator : pointer '
pass
+
def p_abstract_declarator_2(t):
'abstract_declarator : pointer direct_abstract_declarator'
pass
+
def p_abstract_declarator_3(t):
'abstract_declarator : direct_abstract_declarator'
pass
# direct-abstract-declarator:
+
def p_direct_abstract_declarator_1(t):
'direct_abstract_declarator : LPAREN abstract_declarator RPAREN'
pass
+
def p_direct_abstract_declarator_2(t):
'direct_abstract_declarator : direct_abstract_declarator LBRACKET constant_expression_opt RBRACKET'
pass
+
def p_direct_abstract_declarator_3(t):
'direct_abstract_declarator : LBRACKET constant_expression_opt RBRACKET'
pass
+
def p_direct_abstract_declarator_4(t):
'direct_abstract_declarator : direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN'
pass
+
def p_direct_abstract_declarator_5(t):
'direct_abstract_declarator : LPAREN parameter_type_list_opt RPAREN'
pass
# Optional fields in abstract declarators
+
def p_constant_expression_opt_1(t):
'constant_expression_opt : empty'
pass
+
def p_constant_expression_opt_2(t):
'constant_expression_opt : constant_expression'
pass
+
def p_parameter_type_list_opt_1(t):
'parameter_type_list_opt : empty'
pass
+
def p_parameter_type_list_opt_2(t):
'parameter_type_list_opt : parameter_type_list'
pass
# statement:
+
def p_statement(t):
'''
statement : labeled_statement
@@ -463,124 +563,155 @@ def p_statement(t):
# labeled-statement:
+
def p_labeled_statement_1(t):
'labeled_statement : ID COLON statement'
pass
+
def p_labeled_statement_2(t):
'labeled_statement : CASE constant_expression COLON statement'
pass
+
def p_labeled_statement_3(t):
'labeled_statement : DEFAULT COLON statement'
pass
# expression-statement:
+
+
def p_expression_statement(t):
'expression_statement : expression_opt SEMI'
pass
# compound-statement:
+
def p_compound_statement_1(t):
'compound_statement : LBRACE declaration_list statement_list RBRACE'
pass
+
def p_compound_statement_2(t):
'compound_statement : LBRACE statement_list RBRACE'
pass
+
def p_compound_statement_3(t):
'compound_statement : LBRACE declaration_list RBRACE'
pass
+
def p_compound_statement_4(t):
'compound_statement : LBRACE RBRACE'
pass
# statement-list:
+
def p_statement_list_1(t):
'statement_list : statement'
pass
+
def p_statement_list_2(t):
'statement_list : statement_list statement'
pass
# selection-statement
+
def p_selection_statement_1(t):
'selection_statement : IF LPAREN expression RPAREN statement'
pass
+
def p_selection_statement_2(t):
'selection_statement : IF LPAREN expression RPAREN statement ELSE statement '
pass
+
def p_selection_statement_3(t):
'selection_statement : SWITCH LPAREN expression RPAREN statement '
pass
# iteration_statement:
+
def p_iteration_statement_1(t):
'iteration_statement : WHILE LPAREN expression RPAREN statement'
pass
+
def p_iteration_statement_2(t):
'iteration_statement : FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement '
pass
+
def p_iteration_statement_3(t):
'iteration_statement : DO statement WHILE LPAREN expression RPAREN SEMI'
pass
# jump_statement:
+
def p_jump_statement_1(t):
'jump_statement : GOTO ID SEMI'
pass
+
def p_jump_statement_2(t):
'jump_statement : CONTINUE SEMI'
pass
+
def p_jump_statement_3(t):
'jump_statement : BREAK SEMI'
pass
+
def p_jump_statement_4(t):
'jump_statement : RETURN expression_opt SEMI'
pass
+
def p_expression_opt_1(t):
'expression_opt : empty'
pass
+
def p_expression_opt_2(t):
'expression_opt : expression'
pass
# expression:
+
+
def p_expression_1(t):
'expression : assignment_expression'
pass
+
def p_expression_2(t):
'expression : expression COMMA assignment_expression'
pass
# assigment_expression:
+
+
def p_assignment_expression_1(t):
'assignment_expression : conditional_expression'
pass
+
def p_assignment_expression_2(t):
'assignment_expression : unary_expression assignment_operator assignment_expression'
pass
# assignment_operator:
+
+
def p_assignment_operator(t):
'''
assignment_operator : EQUALS
@@ -598,66 +729,80 @@ def p_assignment_operator(t):
pass
# conditional-expression
+
+
def p_conditional_expression_1(t):
'conditional_expression : logical_or_expression'
pass
+
def p_conditional_expression_2(t):
'conditional_expression : logical_or_expression CONDOP expression COLON conditional_expression '
pass
# constant-expression
+
def p_constant_expression(t):
'constant_expression : conditional_expression'
pass
# logical-or-expression
+
def p_logical_or_expression_1(t):
'logical_or_expression : logical_and_expression'
pass
+
def p_logical_or_expression_2(t):
'logical_or_expression : logical_or_expression LOR logical_and_expression'
pass
# logical-and-expression
+
def p_logical_and_expression_1(t):
'logical_and_expression : inclusive_or_expression'
pass
+
def p_logical_and_expression_2(t):
'logical_and_expression : logical_and_expression LAND inclusive_or_expression'
pass
# inclusive-or-expression:
+
def p_inclusive_or_expression_1(t):
'inclusive_or_expression : exclusive_or_expression'
pass
+
def p_inclusive_or_expression_2(t):
'inclusive_or_expression : inclusive_or_expression OR exclusive_or_expression'
pass
# exclusive-or-expression:
+
def p_exclusive_or_expression_1(t):
'exclusive_or_expression : and_expression'
pass
+
def p_exclusive_or_expression_2(t):
'exclusive_or_expression : exclusive_or_expression XOR and_expression'
pass
# AND-expression
+
def p_and_expression_1(t):
'and_expression : equality_expression'
pass
+
def p_and_expression_2(t):
'and_expression : and_expression AND equality_expression'
pass
@@ -668,10 +813,12 @@ def p_equality_expression_1(t):
'equality_expression : relational_expression'
pass
+
def p_equality_expression_2(t):
'equality_expression : equality_expression EQ relational_expression'
pass
+
def p_equality_expression_3(t):
'equality_expression : equality_expression NE relational_expression'
pass
@@ -682,104 +829,129 @@ def p_relational_expression_1(t):
'relational_expression : shift_expression'
pass
+
def p_relational_expression_2(t):
'relational_expression : relational_expression LT shift_expression'
pass
+
def p_relational_expression_3(t):
'relational_expression : relational_expression GT shift_expression'
pass
+
def p_relational_expression_4(t):
'relational_expression : relational_expression LE shift_expression'
pass
+
def p_relational_expression_5(t):
'relational_expression : relational_expression GE shift_expression'
pass
# shift-expression
+
def p_shift_expression_1(t):
'shift_expression : additive_expression'
pass
+
def p_shift_expression_2(t):
'shift_expression : shift_expression LSHIFT additive_expression'
pass
+
def p_shift_expression_3(t):
'shift_expression : shift_expression RSHIFT additive_expression'
pass
# additive-expression
+
def p_additive_expression_1(t):
'additive_expression : multiplicative_expression'
pass
+
def p_additive_expression_2(t):
'additive_expression : additive_expression PLUS multiplicative_expression'
pass
+
def p_additive_expression_3(t):
'additive_expression : additive_expression MINUS multiplicative_expression'
pass
# multiplicative-expression
+
def p_multiplicative_expression_1(t):
'multiplicative_expression : cast_expression'
pass
+
def p_multiplicative_expression_2(t):
'multiplicative_expression : multiplicative_expression TIMES cast_expression'
pass
+
def p_multiplicative_expression_3(t):
'multiplicative_expression : multiplicative_expression DIVIDE cast_expression'
pass
+
def p_multiplicative_expression_4(t):
'multiplicative_expression : multiplicative_expression MOD cast_expression'
pass
# cast-expression:
+
def p_cast_expression_1(t):
'cast_expression : unary_expression'
pass
+
def p_cast_expression_2(t):
'cast_expression : LPAREN type_name RPAREN cast_expression'
pass
# unary-expression:
+
+
def p_unary_expression_1(t):
'unary_expression : postfix_expression'
pass
+
def p_unary_expression_2(t):
'unary_expression : PLUSPLUS unary_expression'
pass
+
def p_unary_expression_3(t):
'unary_expression : MINUSMINUS unary_expression'
pass
+
def p_unary_expression_4(t):
'unary_expression : unary_operator cast_expression'
pass
+
def p_unary_expression_5(t):
'unary_expression : SIZEOF unary_expression'
pass
+
def p_unary_expression_6(t):
'unary_expression : SIZEOF LPAREN type_name RPAREN'
pass
-
-#unary-operator
+
+# unary-operator
+
+
def p_unary_operator(t):
'''unary_operator : AND
| TIMES
@@ -790,39 +962,50 @@ def p_unary_operator(t):
pass
# postfix-expression:
+
+
def p_postfix_expression_1(t):
'postfix_expression : primary_expression'
pass
+
def p_postfix_expression_2(t):
'postfix_expression : postfix_expression LBRACKET expression RBRACKET'
pass
+
def p_postfix_expression_3(t):
'postfix_expression : postfix_expression LPAREN argument_expression_list RPAREN'
pass
+
def p_postfix_expression_4(t):
'postfix_expression : postfix_expression LPAREN RPAREN'
pass
+
def p_postfix_expression_5(t):
'postfix_expression : postfix_expression PERIOD ID'
pass
+
def p_postfix_expression_6(t):
'postfix_expression : postfix_expression ARROW ID'
pass
+
def p_postfix_expression_7(t):
'postfix_expression : postfix_expression PLUSPLUS'
pass
+
def p_postfix_expression_8(t):
'postfix_expression : postfix_expression MINUSMINUS'
pass
# primary-expression:
+
+
def p_primary_expression(t):
'''primary_expression : ID
| constant
@@ -831,23 +1014,28 @@ def p_primary_expression(t):
pass
# argument-expression-list:
+
+
def p_argument_expression_list(t):
'''argument_expression_list : assignment_expression
| argument_expression_list COMMA assignment_expression'''
pass
# constant:
-def p_constant(t):
- '''constant : ICONST
- | FCONST
- | CCONST'''
- pass
+
+
+def p_constant(t):
+ '''constant : ICONST
+ | FCONST
+ | CCONST'''
+ pass
def p_empty(t):
'empty : '
pass
+
def p_error(t):
print("Whoa. We're hosed")
@@ -858,7 +1046,3 @@ yacc.yacc()
#yacc.yacc(method='LALR',write_tables=False,debug=False)
#profile.run("yacc.yacc(method='LALR')")
-
-
-
-
diff --git a/example/calc/calc.py b/example/calc/calc.py
index b923780..824c3d7 100644
--- a/example/calc/calc.py
+++ b/example/calc/calc.py
@@ -6,20 +6,21 @@
# -----------------------------------------------------------------------------
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
if sys.version_info[0] >= 3:
raw_input = input
tokens = (
- 'NAME','NUMBER',
- )
+ 'NAME', 'NUMBER',
+)
-literals = ['=','+','-','*','/', '(',')']
+literals = ['=', '+', '-', '*', '/', '(', ')']
# Tokens
-t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+
def t_NUMBER(t):
r'\d+'
@@ -28,14 +29,16 @@ def t_NUMBER(t):
t_ignore = " \t"
+
def t_newline(t):
r'\n+'
t.lexer.lineno += t.value.count("\n")
-
+
+
def t_error(t):
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
-
+
# Build the lexer
import ply.lex as lex
lex.lex()
@@ -43,44 +46,55 @@ lex.lex()
# Parsing rules
precedence = (
- ('left','+','-'),
- ('left','*','/'),
- ('right','UMINUS'),
- )
+ ('left', '+', '-'),
+ ('left', '*', '/'),
+ ('right', 'UMINUS'),
+)
# dictionary of names
-names = { }
+names = {}
+
def p_statement_assign(p):
'statement : NAME "=" expression'
names[p[1]] = p[3]
+
def p_statement_expr(p):
'statement : expression'
print(p[1])
+
def p_expression_binop(p):
'''expression : expression '+' expression
| expression '-' expression
| expression '*' expression
| expression '/' expression'''
- if p[2] == '+' : p[0] = p[1] + p[3]
- elif p[2] == '-': p[0] = p[1] - p[3]
- elif p[2] == '*': p[0] = p[1] * p[3]
- elif p[2] == '/': p[0] = p[1] / p[3]
+ if p[2] == '+':
+ p[0] = p[1] + p[3]
+ elif p[2] == '-':
+ p[0] = p[1] - p[3]
+ elif p[2] == '*':
+ p[0] = p[1] * p[3]
+ elif p[2] == '/':
+ p[0] = p[1] / p[3]
+
def p_expression_uminus(p):
"expression : '-' expression %prec UMINUS"
p[0] = -p[2]
+
def p_expression_group(p):
"expression : '(' expression ')'"
p[0] = p[2]
+
def p_expression_number(p):
"expression : NUMBER"
p[0] = p[1]
+
def p_expression_name(p):
"expression : NAME"
try:
@@ -89,6 +103,7 @@ def p_expression_name(p):
print("Undefined name '%s'" % p[1])
p[0] = 0
+
def p_error(p):
if p:
print("Syntax error at '%s'" % p.value)
@@ -103,5 +118,6 @@ while 1:
s = raw_input('calc > ')
except EOFError:
break
- if not s: continue
+ if not s:
+ continue
yacc.parse(s)
diff --git a/example/calcdebug/calc.py b/example/calcdebug/calc.py
index 6732f9f..06831e2 100644
--- a/example/calcdebug/calc.py
+++ b/example/calcdebug/calc.py
@@ -6,20 +6,21 @@
# -----------------------------------------------------------------------------
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
if sys.version_info[0] >= 3:
raw_input = input
tokens = (
- 'NAME','NUMBER',
- )
+ 'NAME', 'NUMBER',
+)
-literals = ['=','+','-','*','/', '(',')']
+literals = ['=', '+', '-', '*', '/', '(', ')']
# Tokens
-t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+
def t_NUMBER(t):
r'\d+'
@@ -28,14 +29,16 @@ def t_NUMBER(t):
t_ignore = " \t"
+
def t_newline(t):
r'\n+'
t.lexer.lineno += t.value.count("\n")
-
+
+
def t_error(t):
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
-
+
# Build the lexer
import ply.lex as lex
lex.lex()
@@ -43,44 +46,55 @@ lex.lex()
# Parsing rules
precedence = (
- ('left','+','-'),
- ('left','*','/'),
- ('right','UMINUS'),
- )
+ ('left', '+', '-'),
+ ('left', '*', '/'),
+ ('right', 'UMINUS'),
+)
# dictionary of names
-names = { }
+names = {}
+
def p_statement_assign(p):
'statement : NAME "=" expression'
names[p[1]] = p[3]
+
def p_statement_expr(p):
'statement : expression'
print(p[1])
+
def p_expression_binop(p):
'''expression : expression '+' expression
| expression '-' expression
| expression '*' expression
| expression '/' expression'''
- if p[2] == '+' : p[0] = p[1] + p[3]
- elif p[2] == '-': p[0] = p[1] - p[3]
- elif p[2] == '*': p[0] = p[1] * p[3]
- elif p[2] == '/': p[0] = p[1] / p[3]
+ if p[2] == '+':
+ p[0] = p[1] + p[3]
+ elif p[2] == '-':
+ p[0] = p[1] - p[3]
+ elif p[2] == '*':
+ p[0] = p[1] * p[3]
+ elif p[2] == '/':
+ p[0] = p[1] / p[3]
+
def p_expression_uminus(p):
"expression : '-' expression %prec UMINUS"
p[0] = -p[2]
+
def p_expression_group(p):
"expression : '(' expression ')'"
p[0] = p[2]
+
def p_expression_number(p):
"expression : NUMBER"
p[0] = p[1]
+
def p_expression_name(p):
"expression : NAME"
try:
@@ -89,6 +103,7 @@ def p_expression_name(p):
print("Undefined name '%s'" % p[1])
p[0] = 0
+
def p_error(p):
if p:
print("Syntax error at '%s'" % p.value)
@@ -109,5 +124,6 @@ while 1:
s = raw_input('calc > ')
except EOFError:
break
- if not s: continue
- yacc.parse(s,debug=logging.getLogger())
+ if not s:
+ continue
+ yacc.parse(s, debug=logging.getLogger())
diff --git a/example/calceof/calc.py b/example/calceof/calc.py
index 4a880fb..22b39a4 100644
--- a/example/calceof/calc.py
+++ b/example/calceof/calc.py
@@ -6,20 +6,21 @@
# -----------------------------------------------------------------------------
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
if sys.version_info[0] >= 3:
raw_input = input
tokens = (
- 'NAME','NUMBER',
- )
+ 'NAME', 'NUMBER',
+)
-literals = ['=','+','-','*','/', '(',')']
+literals = ['=', '+', '-', '*', '/', '(', ')']
# Tokens
-t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+
def t_NUMBER(t):
r'\d+'
@@ -28,10 +29,12 @@ def t_NUMBER(t):
t_ignore = " \t"
+
def t_newline(t):
r'\n+'
t.lexer.lineno += t.value.count("\n")
+
def t_eof(t):
more = raw_input('... ')
if more:
@@ -40,10 +43,11 @@ def t_eof(t):
else:
return None
+
def t_error(t):
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
-
+
# Build the lexer
import ply.lex as lex
lex.lex()
@@ -51,44 +55,55 @@ lex.lex()
# Parsing rules
precedence = (
- ('left','+','-'),
- ('left','*','/'),
- ('right','UMINUS'),
- )
+ ('left', '+', '-'),
+ ('left', '*', '/'),
+ ('right', 'UMINUS'),
+)
# dictionary of names
-names = { }
+names = {}
+
def p_statement_assign(p):
'statement : NAME "=" expression'
names[p[1]] = p[3]
+
def p_statement_expr(p):
'statement : expression'
print(p[1])
+
def p_expression_binop(p):
'''expression : expression '+' expression
| expression '-' expression
| expression '*' expression
| expression '/' expression'''
- if p[2] == '+' : p[0] = p[1] + p[3]
- elif p[2] == '-': p[0] = p[1] - p[3]
- elif p[2] == '*': p[0] = p[1] * p[3]
- elif p[2] == '/': p[0] = p[1] / p[3]
+ if p[2] == '+':
+ p[0] = p[1] + p[3]
+ elif p[2] == '-':
+ p[0] = p[1] - p[3]
+ elif p[2] == '*':
+ p[0] = p[1] * p[3]
+ elif p[2] == '/':
+ p[0] = p[1] / p[3]
+
def p_expression_uminus(p):
"expression : '-' expression %prec UMINUS"
p[0] = -p[2]
+
def p_expression_group(p):
"expression : '(' expression ')'"
p[0] = p[2]
+
def p_expression_number(p):
"expression : NUMBER"
p[0] = p[1]
+
def p_expression_name(p):
"expression : NAME"
try:
@@ -97,6 +112,7 @@ def p_expression_name(p):
print("Undefined name '%s'" % p[1])
p[0] = 0
+
def p_error(p):
if p:
print("Syntax error at '%s'" % p.value)
@@ -111,5 +127,6 @@ while 1:
s = raw_input('calc > ')
except EOFError:
break
- if not s: continue
- yacc.parse(s+'\n')
+ if not s:
+ continue
+ yacc.parse(s + '\n')
diff --git a/example/classcalc/calc.py b/example/classcalc/calc.py
index bf0d065..ada4afd 100755
--- a/example/classcalc/calc.py
+++ b/example/classcalc/calc.py
@@ -10,7 +10,7 @@
# -----------------------------------------------------------------------------
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
if sys.version_info[0] >= 3:
raw_input = input
@@ -19,6 +19,7 @@ import ply.lex as lex
import ply.yacc as yacc
import os
+
class Parser:
"""
Base class for a lexer/parser that has the rules defined as methods
@@ -28,14 +29,15 @@ class Parser:
def __init__(self, **kw):
self.debug = kw.get('debug', 0)
- self.names = { }
+ self.names = {}
try:
- modname = os.path.split(os.path.splitext(__file__)[0])[1] + "_" + self.__class__.__name__
+ modname = os.path.split(os.path.splitext(__file__)[0])[
+ 1] + "_" + self.__class__.__name__
except:
- modname = "parser"+"_"+self.__class__.__name__
+ modname = "parser" + "_" + self.__class__.__name__
self.debugfile = modname + ".dbg"
self.tabmodule = modname + "_" + "parsetab"
- #print self.debugfile, self.tabmodule
+ # print self.debugfile, self.tabmodule
# Build the lexer and parser
lex.lex(module=self, debug=self.debug)
@@ -50,29 +52,30 @@ class Parser:
s = raw_input('calc > ')
except EOFError:
break
- if not s: continue
+ if not s:
+ continue
yacc.parse(s)
-
+
class Calc(Parser):
tokens = (
- 'NAME','NUMBER',
- 'PLUS','MINUS','EXP', 'TIMES','DIVIDE','EQUALS',
- 'LPAREN','RPAREN',
- )
+ 'NAME', 'NUMBER',
+ 'PLUS', 'MINUS', 'EXP', 'TIMES', 'DIVIDE', 'EQUALS',
+ 'LPAREN', 'RPAREN',
+ )
# Tokens
- t_PLUS = r'\+'
- t_MINUS = r'-'
- t_EXP = r'\*\*'
- t_TIMES = r'\*'
- t_DIVIDE = r'/'
- t_EQUALS = r'='
- t_LPAREN = r'\('
- t_RPAREN = r'\)'
- t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+ t_PLUS = r'\+'
+ t_MINUS = r'-'
+ t_EXP = r'\*\*'
+ t_TIMES = r'\*'
+ t_DIVIDE = r'/'
+ t_EQUALS = r'='
+ t_LPAREN = r'\('
+ t_RPAREN = r'\)'
+ t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
def t_NUMBER(self, t):
r'\d+'
@@ -81,7 +84,7 @@ class Calc(Parser):
except ValueError:
print("Integer value too large %s" % t.value)
t.value = 0
- #print "parsed number %s" % repr(t.value)
+ # print "parsed number %s" % repr(t.value)
return t
t_ignore = " \t"
@@ -89,7 +92,7 @@ class Calc(Parser):
def t_newline(self, t):
r'\n+'
t.lexer.lineno += t.value.count("\n")
-
+
def t_error(self, t):
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
@@ -97,11 +100,11 @@ class Calc(Parser):
# Parsing rules
precedence = (
- ('left','PLUS','MINUS'),
- ('left','TIMES','DIVIDE'),
+ ('left', 'PLUS', 'MINUS'),
+ ('left', 'TIMES', 'DIVIDE'),
('left', 'EXP'),
- ('right','UMINUS'),
- )
+ ('right', 'UMINUS'),
+ )
def p_statement_assign(self, p):
'statement : NAME EQUALS expression'
@@ -119,12 +122,17 @@ class Calc(Parser):
| expression DIVIDE expression
| expression EXP expression
"""
- #print [repr(p[i]) for i in range(0,4)]
- if p[2] == '+' : p[0] = p[1] + p[3]
- elif p[2] == '-': p[0] = p[1] - p[3]
- elif p[2] == '*': p[0] = p[1] * p[3]
- elif p[2] == '/': p[0] = p[1] / p[3]
- elif p[2] == '**': p[0] = p[1] ** p[3]
+ # print [repr(p[i]) for i in range(0,4)]
+ if p[2] == '+':
+ p[0] = p[1] + p[3]
+ elif p[2] == '-':
+ p[0] = p[1] - p[3]
+ elif p[2] == '*':
+ p[0] = p[1] * p[3]
+ elif p[2] == '/':
+ p[0] = p[1] / p[3]
+ elif p[2] == '**':
+ p[0] = p[1] ** p[3]
def p_expression_uminus(self, p):
'expression : MINUS expression %prec UMINUS'
diff --git a/example/closurecalc/calc.py b/example/closurecalc/calc.py
index 6598f58..6031b05 100644
--- a/example/closurecalc/calc.py
+++ b/example/closurecalc/calc.py
@@ -2,37 +2,38 @@
# calc.py
#
# A calculator parser that makes use of closures. The function make_calculator()
-# returns a function that accepts an input string and returns a result. All
+# returns a function that accepts an input string and returns a result. All
# lexing rules, parsing rules, and internal state are held inside the function.
# -----------------------------------------------------------------------------
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
if sys.version_info[0] >= 3:
raw_input = input
# Make a calculator function
+
def make_calculator():
import ply.lex as lex
import ply.yacc as yacc
# ------- Internal calculator state
- variables = { } # Dictionary of stored variables
+ variables = {} # Dictionary of stored variables
# ------- Calculator tokenizing rules
tokens = (
- 'NAME','NUMBER',
+ 'NAME', 'NUMBER',
)
- literals = ['=','+','-','*','/', '(',')']
+ literals = ['=', '+', '-', '*', '/', '(', ')']
t_ignore = " \t"
- t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+ t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
def t_NUMBER(t):
r'\d+'
@@ -42,20 +43,20 @@ def make_calculator():
def t_newline(t):
r'\n+'
t.lexer.lineno += t.value.count("\n")
-
+
def t_error(t):
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
-
+
# Build the lexer
lexer = lex.lex()
# ------- Calculator parsing rules
precedence = (
- ('left','+','-'),
- ('left','*','/'),
- ('right','UMINUS'),
+ ('left', '+', '-'),
+ ('left', '*', '/'),
+ ('right', 'UMINUS'),
)
def p_statement_assign(p):
@@ -72,10 +73,14 @@ def make_calculator():
| expression '-' expression
| expression '*' expression
| expression '/' expression'''
- if p[2] == '+' : p[0] = p[1] + p[3]
- elif p[2] == '-': p[0] = p[1] - p[3]
- elif p[2] == '*': p[0] = p[1] * p[3]
- elif p[2] == '/': p[0] = p[1] / p[3]
+ if p[2] == '+':
+ p[0] = p[1] + p[3]
+ elif p[2] == '-':
+ p[0] = p[1] - p[3]
+ elif p[2] == '*':
+ p[0] = p[1] * p[3]
+ elif p[2] == '/':
+ p[0] = p[1] / p[3]
def p_expression_uminus(p):
"expression : '-' expression %prec UMINUS"
@@ -103,14 +108,13 @@ def make_calculator():
else:
print("Syntax error at EOF")
-
# Build the parser
parser = yacc.yacc()
- # ------- Input function
-
+ # ------- Input function
+
def input(text):
- result = parser.parse(text,lexer=lexer)
+ result = parser.parse(text, lexer=lexer)
return result
return input
@@ -126,5 +130,3 @@ while True:
r = calc(s)
if r:
print(r)
-
-
diff --git a/example/hedit/hedit.py b/example/hedit/hedit.py
index 2e80675..32da745 100644
--- a/example/hedit/hedit.py
+++ b/example/hedit/hedit.py
@@ -15,34 +15,34 @@
# -----------------------------------------------------------------------------
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
tokens = (
'H_EDIT_DESCRIPTOR',
- )
+)
# Tokens
t_ignore = " \t\n"
+
def t_H_EDIT_DESCRIPTOR(t):
r"\d+H.*" # This grabs all of the remaining text
i = t.value.index('H')
n = eval(t.value[:i])
-
+
# Adjust the tokenizing position
- t.lexer.lexpos -= len(t.value) - (i+1+n)
-
- t.value = t.value[i+1:i+1+n]
- return t
-
+ t.lexer.lexpos -= len(t.value) - (i + 1 + n)
+
+ t.value = t.value[i + 1:i + 1 + n]
+ return t
+
+
def t_error(t):
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
-
+
# Build the lexer
import ply.lex as lex
lex.lex()
lex.runmain()
-
-
diff --git a/example/newclasscalc/calc.py b/example/newclasscalc/calc.py
index a12e498..43c9506 100755
--- a/example/newclasscalc/calc.py
+++ b/example/newclasscalc/calc.py
@@ -12,7 +12,7 @@
# -----------------------------------------------------------------------------
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
if sys.version_info[0] >= 3:
raw_input = input
@@ -21,6 +21,7 @@ import ply.lex as lex
import ply.yacc as yacc
import os
+
class Parser(object):
"""
Base class for a lexer/parser that has the rules defined as methods
@@ -28,17 +29,17 @@ class Parser(object):
tokens = ()
precedence = ()
-
def __init__(self, **kw):
self.debug = kw.get('debug', 0)
- self.names = { }
+ self.names = {}
try:
- modname = os.path.split(os.path.splitext(__file__)[0])[1] + "_" + self.__class__.__name__
+ modname = os.path.split(os.path.splitext(__file__)[0])[
+ 1] + "_" + self.__class__.__name__
except:
- modname = "parser"+"_"+self.__class__.__name__
+ modname = "parser" + "_" + self.__class__.__name__
self.debugfile = modname + ".dbg"
self.tabmodule = modname + "_" + "parsetab"
- #print self.debugfile, self.tabmodule
+ # print self.debugfile, self.tabmodule
# Build the lexer and parser
lex.lex(module=self, debug=self.debug)
@@ -53,29 +54,30 @@ class Parser(object):
s = raw_input('calc > ')
except EOFError:
break
- if not s: continue
+ if not s:
+ continue
yacc.parse(s)
-
+
class Calc(Parser):
tokens = (
- 'NAME','NUMBER',
- 'PLUS','MINUS','EXP', 'TIMES','DIVIDE','EQUALS',
- 'LPAREN','RPAREN',
- )
+ 'NAME', 'NUMBER',
+ 'PLUS', 'MINUS', 'EXP', 'TIMES', 'DIVIDE', 'EQUALS',
+ 'LPAREN', 'RPAREN',
+ )
# Tokens
- t_PLUS = r'\+'
- t_MINUS = r'-'
- t_EXP = r'\*\*'
- t_TIMES = r'\*'
- t_DIVIDE = r'/'
- t_EQUALS = r'='
- t_LPAREN = r'\('
- t_RPAREN = r'\)'
- t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+ t_PLUS = r'\+'
+ t_MINUS = r'-'
+ t_EXP = r'\*\*'
+ t_TIMES = r'\*'
+ t_DIVIDE = r'/'
+ t_EQUALS = r'='
+ t_LPAREN = r'\('
+ t_RPAREN = r'\)'
+ t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
def t_NUMBER(self, t):
r'\d+'
@@ -84,7 +86,7 @@ class Calc(Parser):
except ValueError:
print("Integer value too large %s" % t.value)
t.value = 0
- #print "parsed number %s" % repr(t.value)
+ # print "parsed number %s" % repr(t.value)
return t
t_ignore = " \t"
@@ -92,7 +94,7 @@ class Calc(Parser):
def t_newline(self, t):
r'\n+'
t.lexer.lineno += t.value.count("\n")
-
+
def t_error(self, t):
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
@@ -100,11 +102,11 @@ class Calc(Parser):
# Parsing rules
precedence = (
- ('left','PLUS','MINUS'),
- ('left','TIMES','DIVIDE'),
+ ('left', 'PLUS', 'MINUS'),
+ ('left', 'TIMES', 'DIVIDE'),
('left', 'EXP'),
- ('right','UMINUS'),
- )
+ ('right', 'UMINUS'),
+ )
def p_statement_assign(self, p):
'statement : NAME EQUALS expression'
@@ -122,12 +124,17 @@ class Calc(Parser):
| expression DIVIDE expression
| expression EXP expression
"""
- #print [repr(p[i]) for i in range(0,4)]
- if p[2] == '+' : p[0] = p[1] + p[3]
- elif p[2] == '-': p[0] = p[1] - p[3]
- elif p[2] == '*': p[0] = p[1] * p[3]
- elif p[2] == '/': p[0] = p[1] / p[3]
- elif p[2] == '**': p[0] = p[1] ** p[3]
+ # print [repr(p[i]) for i in range(0,4)]
+ if p[2] == '+':
+ p[0] = p[1] + p[3]
+ elif p[2] == '-':
+ p[0] = p[1] - p[3]
+ elif p[2] == '*':
+ p[0] = p[1] * p[3]
+ elif p[2] == '/':
+ p[0] = p[1] / p[3]
+ elif p[2] == '**':
+ p[0] = p[1] ** p[3]
def p_expression_uminus(self, p):
'expression : MINUS expression %prec UMINUS'
diff --git a/example/optcalc/calc.py b/example/optcalc/calc.py
index dd83351..0c223e5 100644
--- a/example/optcalc/calc.py
+++ b/example/optcalc/calc.py
@@ -6,27 +6,28 @@
# -----------------------------------------------------------------------------
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
if sys.version_info[0] >= 3:
raw_input = input
tokens = (
- 'NAME','NUMBER',
- 'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
- 'LPAREN','RPAREN',
- )
+ 'NAME', 'NUMBER',
+ 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'EQUALS',
+ 'LPAREN', 'RPAREN',
+)
# Tokens
-t_PLUS = r'\+'
-t_MINUS = r'-'
-t_TIMES = r'\*'
-t_DIVIDE = r'/'
-t_EQUALS = r'='
-t_LPAREN = r'\('
-t_RPAREN = r'\)'
-t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+t_PLUS = r'\+'
+t_MINUS = r'-'
+t_TIMES = r'\*'
+t_DIVIDE = r'/'
+t_EQUALS = r'='
+t_LPAREN = r'\('
+t_RPAREN = r'\)'
+t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
+
def t_NUMBER(t):
r'\d+'
@@ -39,14 +40,16 @@ def t_NUMBER(t):
t_ignore = " \t"
+
def t_newline(t):
r'\n+'
t.lexer.lineno += t.value.count("\n")
-
+
+
def t_error(t):
print("Illegal character '%s'" % t.value[0])
t.lexer.skip(1)
-
+
# Build the lexer
import ply.lex as lex
lex.lex(optimize=1)
@@ -54,45 +57,57 @@ lex.lex(optimize=1)
# Parsing rules
precedence = (
- ('left','PLUS','MINUS'),
- ('left','TIMES','DIVIDE'),
- ('right','UMINUS'),
- )
+ ('left', 'PLUS', 'MINUS'),
+ ('left', 'TIMES', 'DIVIDE'),
+ ('right', 'UMINUS'),
+)
# dictionary of names
-names = { }
+names = {}
+
def p_statement_assign(t):
'statement : NAME EQUALS expression'
names[t[1]] = t[3]
+
def p_statement_expr(t):
'statement : expression'
print(t[1])
+
def p_expression_binop(t):
'''expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression'''
- if t[2] == '+' : t[0] = t[1] + t[3]
- elif t[2] == '-': t[0] = t[1] - t[3]
- elif t[2] == '*': t[0] = t[1] * t[3]
- elif t[2] == '/': t[0] = t[1] / t[3]
- elif t[2] == '<': t[0] = t[1] < t[3]
+ if t[2] == '+':
+ t[0] = t[1] + t[3]
+ elif t[2] == '-':
+ t[0] = t[1] - t[3]
+ elif t[2] == '*':
+ t[0] = t[1] * t[3]
+ elif t[2] == '/':
+ t[0] = t[1] / t[3]
+ elif t[2] == '<':
+ t[0] = t[1] < t[3]
+
def p_expression_uminus(t):
'expression : MINUS expression %prec UMINUS'
t[0] = -t[2]
+
def p_expression_group(t):
'expression : LPAREN expression RPAREN'
t[0] = t[2]
+
def p_expression_number(t):
'expression : NUMBER'
t[0] = t[1]
+
def p_expression_name(t):
'expression : NAME'
try:
@@ -101,6 +116,7 @@ def p_expression_name(t):
print("Undefined name '%s'" % t[1])
t[0] = 0
+
def p_error(t):
if t:
print("Syntax error at '%s'" % t.value)
@@ -116,4 +132,3 @@ while 1:
except EOFError:
break
yacc.parse(s)
-
diff --git a/example/unicalc/calc.py b/example/unicalc/calc.py
index 55fb48d..901c4b9 100644
--- a/example/unicalc/calc.py
+++ b/example/unicalc/calc.py
@@ -8,24 +8,25 @@
# -----------------------------------------------------------------------------
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
tokens = (
- 'NAME','NUMBER',
- 'PLUS','MINUS','TIMES','DIVIDE','EQUALS',
- 'LPAREN','RPAREN',
- )
+ 'NAME', 'NUMBER',
+ 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'EQUALS',
+ 'LPAREN', 'RPAREN',
+)
# Tokens
-t_PLUS = ur'\+'
-t_MINUS = ur'-'
-t_TIMES = ur'\*'
-t_DIVIDE = ur'/'
-t_EQUALS = ur'='
-t_LPAREN = ur'\('
-t_RPAREN = ur'\)'
-t_NAME = ur'[a-zA-Z_][a-zA-Z0-9_]*'
+t_PLUS = ur'\+'
+t_MINUS = ur'-'
+t_TIMES = ur'\*'
+t_DIVIDE = ur'/'
+t_EQUALS = ur'='
+t_LPAREN = ur'\('
+t_RPAREN = ur'\)'
+t_NAME = ur'[a-zA-Z_][a-zA-Z0-9_]*'
+
def t_NUMBER(t):
ur'\d+'
@@ -38,14 +39,16 @@ def t_NUMBER(t):
t_ignore = u" \t"
+
def t_newline(t):
ur'\n+'
t.lexer.lineno += t.value.count("\n")
-
+
+
def t_error(t):
print "Illegal character '%s'" % t.value[0]
t.lexer.skip(1)
-
+
# Build the lexer
import ply.lex as lex
lex.lex()
@@ -53,44 +56,55 @@ lex.lex()
# Parsing rules
precedence = (
- ('left','PLUS','MINUS'),
- ('left','TIMES','DIVIDE'),
- ('right','UMINUS'),
- )
+ ('left', 'PLUS', 'MINUS'),
+ ('left', 'TIMES', 'DIVIDE'),
+ ('right', 'UMINUS'),
+)
# dictionary of names
-names = { }
+names = {}
+
def p_statement_assign(p):
'statement : NAME EQUALS expression'
names[p[1]] = p[3]
+
def p_statement_expr(p):
'statement : expression'
print p[1]
+
def p_expression_binop(p):
'''expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression'''
- if p[2] == u'+' : p[0] = p[1] + p[3]
- elif p[2] == u'-': p[0] = p[1] - p[3]
- elif p[2] == u'*': p[0] = p[1] * p[3]
- elif p[2] == u'/': p[0] = p[1] / p[3]
+ if p[2] == u'+':
+ p[0] = p[1] + p[3]
+ elif p[2] == u'-':
+ p[0] = p[1] - p[3]
+ elif p[2] == u'*':
+ p[0] = p[1] * p[3]
+ elif p[2] == u'/':
+ p[0] = p[1] / p[3]
+
def p_expression_uminus(p):
'expression : MINUS expression %prec UMINUS'
p[0] = -p[2]
+
def p_expression_group(p):
'expression : LPAREN expression RPAREN'
p[0] = p[2]
+
def p_expression_number(p):
'expression : NUMBER'
p[0] = p[1]
+
def p_expression_name(p):
'expression : NAME'
try:
@@ -99,6 +113,7 @@ def p_expression_name(p):
print "Undefined name '%s'" % p[1]
p[0] = 0
+
def p_error(p):
if p:
print "Syntax error at '%s'" % p.value
@@ -113,5 +128,6 @@ while 1:
s = raw_input('calc > ')
except EOFError:
break
- if not s: continue
+ if not s:
+ continue
yacc.parse(unicode(s))
diff --git a/example/yply/ylex.py b/example/yply/ylex.py
index 84f2f7a..a3efe8e 100644
--- a/example/yply/ylex.py
+++ b/example/yply/ylex.py
@@ -9,91 +9,105 @@ sys.path.append("../..")
from ply import *
tokens = (
- 'LITERAL','SECTION','TOKEN','LEFT','RIGHT','PREC','START','TYPE','NONASSOC','UNION','CODE',
- 'ID','QLITERAL','NUMBER',
+ 'LITERAL', 'SECTION', 'TOKEN', 'LEFT', 'RIGHT', 'PREC', 'START', 'TYPE', 'NONASSOC', 'UNION', 'CODE',
+ 'ID', 'QLITERAL', 'NUMBER',
)
-states = (('code','exclusive'),)
+states = (('code', 'exclusive'),)
-literals = [ ';', ',', '<', '>', '|',':' ]
+literals = [';', ',', '<', '>', '|', ':']
t_ignore = ' \t'
-t_TOKEN = r'%token'
-t_LEFT = r'%left'
-t_RIGHT = r'%right'
-t_NONASSOC = r'%nonassoc'
-t_PREC = r'%prec'
-t_START = r'%start'
-t_TYPE = r'%type'
-t_UNION = r'%union'
-t_ID = r'[a-zA-Z_][a-zA-Z_0-9]*'
+t_TOKEN = r'%token'
+t_LEFT = r'%left'
+t_RIGHT = r'%right'
+t_NONASSOC = r'%nonassoc'
+t_PREC = r'%prec'
+t_START = r'%start'
+t_TYPE = r'%type'
+t_UNION = r'%union'
+t_ID = r'[a-zA-Z_][a-zA-Z_0-9]*'
t_QLITERAL = r'''(?P<quote>['"]).*?(?P=quote)'''
-t_NUMBER = r'\d+'
+t_NUMBER = r'\d+'
+
def t_SECTION(t):
r'%%'
- if getattr(t.lexer,"lastsection",0):
- t.value = t.lexer.lexdata[t.lexpos+2:]
- t.lexer.lexpos = len(t.lexer.lexdata)
+ if getattr(t.lexer, "lastsection", 0):
+ t.value = t.lexer.lexdata[t.lexpos + 2:]
+ t.lexer.lexpos = len(t.lexer.lexdata)
else:
- t.lexer.lastsection = 0
+ t.lexer.lastsection = 0
return t
# Comments
+
+
def t_ccomment(t):
r'/\*(.|\n)*?\*/'
t.lexer.lineno += t.value.count('\n')
t_ignore_cppcomment = r'//.*'
+
def t_LITERAL(t):
- r'%\{(.|\n)*?%\}'
- t.lexer.lineno += t.value.count("\n")
- return t
+ r'%\{(.|\n)*?%\}'
+ t.lexer.lineno += t.value.count("\n")
+ return t
+
def t_NEWLINE(t):
- r'\n'
- t.lexer.lineno += 1
+ r'\n'
+ t.lexer.lineno += 1
+
def t_code(t):
- r'\{'
- t.lexer.codestart = t.lexpos
- t.lexer.level = 1
- t.lexer.begin('code')
+ r'\{'
+ t.lexer.codestart = t.lexpos
+ t.lexer.level = 1
+ t.lexer.begin('code')
+
def t_code_ignore_string(t):
r'\"([^\\\n]|(\\.))*?\"'
+
def t_code_ignore_char(t):
r'\'([^\\\n]|(\\.))*?\''
+
def t_code_ignore_comment(t):
- r'/\*(.|\n)*?\*/'
+ r'/\*(.|\n)*?\*/'
+
def t_code_ignore_cppcom(t):
- r'//.*'
+ r'//.*'
+
def t_code_lbrace(t):
r'\{'
t.lexer.level += 1
+
def t_code_rbrace(t):
r'\}'
t.lexer.level -= 1
if t.lexer.level == 0:
- t.type = 'CODE'
- t.value = t.lexer.lexdata[t.lexer.codestart:t.lexpos+1]
- t.lexer.begin('INITIAL')
- t.lexer.lineno += t.value.count('\n')
- return t
+ t.type = 'CODE'
+ t.value = t.lexer.lexdata[t.lexer.codestart:t.lexpos + 1]
+ t.lexer.begin('INITIAL')
+ t.lexer.lineno += t.value.count('\n')
+ return t
-t_code_ignore_nonspace = r'[^\s\}\'\"\{]+'
+t_code_ignore_nonspace = r'[^\s\}\'\"\{]+'
t_code_ignore_whitespace = r'\s+'
t_code_ignore = ""
+
def t_code_error(t):
raise RuntimeError
+
def t_error(t):
print "%d: Illegal character '%s'" % (t.lexer.lineno, t.value[0])
print t.value
@@ -103,10 +117,3 @@ lex.lex()
if __name__ == '__main__':
lex.runmain()
-
-
-
-
-
-
-
diff --git a/example/yply/yparse.py b/example/yply/yparse.py
index ab5b884..fff887a 100644
--- a/example/yply/yparse.py
+++ b/example/yply/yparse.py
@@ -9,13 +9,15 @@ tokens = ylex.tokens
from ply import *
tokenlist = []
-preclist = []
+preclist = []
emit_code = 1
+
def p_yacc(p):
'''yacc : defsection rulesection'''
+
def p_defsection(p):
'''defsection : definitions SECTION
| SECTION'''
@@ -25,37 +27,43 @@ def p_defsection(p):
print "precedence = ", repr(preclist)
print
print "# -------------- RULES ----------------"
- print
+ print
+
def p_rulesection(p):
'''rulesection : rules SECTION'''
print "# -------------- RULES END ----------------"
- print_code(p[2],0)
+ print_code(p[2], 0)
+
def p_definitions(p):
'''definitions : definitions definition
| definition'''
+
def p_definition_literal(p):
'''definition : LITERAL'''
- print_code(p[1],0)
+ print_code(p[1], 0)
+
def p_definition_start(p):
'''definition : START ID'''
print "start = '%s'" % p[2]
+
def p_definition_token(p):
'''definition : toktype opttype idlist optsemi '''
for i in p[3]:
- if i[0] not in "'\"":
- tokenlist.append(i)
+ if i[0] not in "'\"":
+ tokenlist.append(i)
if p[1] == '%left':
preclist.append(('left',) + tuple(p[3]))
elif p[1] == '%right':
preclist.append(('right',) + tuple(p[3]))
elif p[1] == '%nonassoc':
- preclist.append(('nonassoc',)+ tuple(p[3]))
+ preclist.append(('nonassoc',) + tuple(p[3]))
+
def p_toktype(p):
'''toktype : TOKEN
@@ -64,10 +72,12 @@ def p_toktype(p):
| NONASSOC'''
p[0] = p[1]
+
def p_opttype(p):
'''opttype : '<' ID '>'
| empty'''
+
def p_idlist(p):
'''idlist : idlist optcomma tokenid
| tokenid'''
@@ -77,141 +87,158 @@ def p_idlist(p):
p[0] = p[1]
p[1].append(p[3])
+
def p_tokenid(p):
'''tokenid : ID
| ID NUMBER
| QLITERAL
| QLITERAL NUMBER'''
p[0] = p[1]
-
+
+
def p_optsemi(p):
'''optsemi : ';'
| empty'''
+
def p_optcomma(p):
'''optcomma : ','
| empty'''
+
def p_definition_type(p):
'''definition : TYPE '<' ID '>' namelist optsemi'''
# type declarations are ignored
+
def p_namelist(p):
'''namelist : namelist optcomma ID
| ID'''
+
def p_definition_union(p):
'''definition : UNION CODE optsemi'''
# Union declarations are ignored
+
def p_rules(p):
'''rules : rules rule
| rule'''
if len(p) == 2:
- rule = p[1]
+ rule = p[1]
else:
- rule = p[2]
+ rule = p[2]
# Print out a Python equivalent of this rule
- embedded = [ ] # Embedded actions (a mess)
+ embedded = [] # Embedded actions (a mess)
embed_count = 0
rulename = rule[0]
rulecount = 1
for r in rule[1]:
# r contains one of the rule possibilities
- print "def p_%s_%d(p):" % (rulename,rulecount)
+ print "def p_%s_%d(p):" % (rulename, rulecount)
prod = []
prodcode = ""
for i in range(len(r)):
- item = r[i]
- if item[0] == '{': # A code block
- if i == len(r) - 1:
- prodcode = item
- break
- else:
- # an embedded action
- embed_name = "_embed%d_%s" % (embed_count,rulename)
- prod.append(embed_name)
- embedded.append((embed_name,item))
- embed_count += 1
- else:
- prod.append(item)
+ item = r[i]
+ if item[0] == '{': # A code block
+ if i == len(r) - 1:
+ prodcode = item
+ break
+ else:
+ # an embedded action
+ embed_name = "_embed%d_%s" % (embed_count, rulename)
+ prod.append(embed_name)
+ embedded.append((embed_name, item))
+ embed_count += 1
+ else:
+ prod.append(item)
print " '''%s : %s'''" % (rulename, " ".join(prod))
# Emit code
- print_code(prodcode,4)
+ print_code(prodcode, 4)
print
rulecount += 1
- for e,code in embedded:
+ for e, code in embedded:
print "def p_%s(p):" % e
print " '''%s : '''" % e
- print_code(code,4)
+ print_code(code, 4)
print
+
def p_rule(p):
- '''rule : ID ':' rulelist ';' '''
- p[0] = (p[1],[p[3]])
+ '''rule : ID ':' rulelist ';' '''
+ p[0] = (p[1], [p[3]])
+
def p_rule2(p):
- '''rule : ID ':' rulelist morerules ';' '''
- p[4].insert(0,p[3])
- p[0] = (p[1],p[4])
+ '''rule : ID ':' rulelist morerules ';' '''
+ p[4].insert(0, p[3])
+ p[0] = (p[1], p[4])
+
def p_rule_empty(p):
- '''rule : ID ':' ';' '''
- p[0] = (p[1],[[]])
+ '''rule : ID ':' ';' '''
+ p[0] = (p[1], [[]])
+
def p_rule_empty2(p):
- '''rule : ID ':' morerules ';' '''
-
- p[3].insert(0,[])
- p[0] = (p[1],p[3])
+ '''rule : ID ':' morerules ';' '''
+
+ p[3].insert(0, [])
+ p[0] = (p[1], p[3])
+
def p_morerules(p):
- '''morerules : morerules '|' rulelist
- | '|' rulelist
- | '|' '''
-
- if len(p) == 2:
- p[0] = [[]]
- elif len(p) == 3:
- p[0] = [p[2]]
- else:
- p[0] = p[1]
- p[0].append(p[3])
+ '''morerules : morerules '|' rulelist
+ | '|' rulelist
+ | '|' '''
+
+ if len(p) == 2:
+ p[0] = [[]]
+ elif len(p) == 3:
+ p[0] = [p[2]]
+ else:
+ p[0] = p[1]
+ p[0].append(p[3])
# print "morerules", len(p), p[0]
+
def p_rulelist(p):
- '''rulelist : rulelist ruleitem
- | ruleitem'''
+ '''rulelist : rulelist ruleitem
+ | ruleitem'''
- if len(p) == 2:
+ if len(p) == 2:
p[0] = [p[1]]
- else:
+ else:
p[0] = p[1]
p[1].append(p[2])
+
def p_ruleitem(p):
- '''ruleitem : ID
- | QLITERAL
- | CODE
- | PREC'''
- p[0] = p[1]
+ '''ruleitem : ID
+ | QLITERAL
+ | CODE
+ | PREC'''
+ p[0] = p[1]
+
def p_empty(p):
'''empty : '''
+
def p_error(p):
pass
yacc.yacc(debug=0)
-def print_code(code,indent):
- if not emit_code: return
+
+def print_code(code, indent):
+ if not emit_code:
+ return
codelines = code.splitlines()
for c in codelines:
- print "%s# %s" % (" "*indent,c)
-
+ print "%s# %s" % (" " * indent, c)
diff --git a/example/yply/yply.py b/example/yply/yply.py
index a439817..1aa24c3 100755
--- a/example/yply/yply.py
+++ b/example/yply/yply.py
@@ -21,7 +21,7 @@
#
import sys
-sys.path.insert(0,"../..")
+sys.path.insert(0, "../..")
import ylex
import yparse
@@ -34,10 +34,10 @@ if len(sys.argv) == 1:
if len(sys.argv) == 3:
if sys.argv[1] == '-nocode':
- yparse.emit_code = 0
+ yparse.emit_code = 0
else:
- print "Unknown option '%s'" % sys.argv[1]
- raise SystemExit
+ print "Unknown option '%s'" % sys.argv[1]
+ raise SystemExit
filename = sys.argv[2]
else:
filename = sys.argv[1]
@@ -49,5 +49,3 @@ if __name__ == '__main__':
from ply import *
yacc.yacc()
"""
-
-