From 9e2b80e00562f0e98ea0791f7192a09c1707e7a9 Mon Sep 17 00:00:00 2001 From: Quinten Yearsley Date: Sat, 26 Sep 2015 10:56:16 -0700 Subject: Run autopep8 on example/ --- example/BASIC/basic.py | 46 ++- example/BASIC/basiclex.py | 71 ++-- example/BASIC/basiclog.py | 56 ++- example/BASIC/basinterp.py | 719 ++++++++++++++++++++----------------- example/BASIC/basparse.py | 290 ++++++++------- example/GardenSnake/GardenSnake.py | 160 ++++++--- example/ansic/clex.py | 132 +++---- example/ansic/cparse.py | 206 ++++++++++- example/calc/calc.py | 50 ++- example/calcdebug/calc.py | 52 ++- example/calceof/calc.py | 51 ++- example/classcalc/calc.py | 72 ++-- example/closurecalc/calc.py | 44 +-- example/hedit/hedit.py | 22 +- example/newclasscalc/calc.py | 73 ++-- example/optcalc/calc.py | 67 ++-- example/unicalc/calc.py | 66 ++-- example/yply/ylex.py | 91 ++--- example/yply/yparse.py | 153 ++++---- example/yply/yply.py | 10 +- 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=""): 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['"]).*?(?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() """ - - -- cgit v1.2.1