Skip to content

Instantly share code, notes, and snippets.

@Frimkron
Created April 19, 2013 00:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Frimkron/5417267 to your computer and use it in GitHub Desktop.
Save Frimkron/5417267 to your computer and use it in GitHub Desktop.
Quick proof-of-concept for comparing python code using the abstract syntax tree as an alternative to pattern matching . It's a little more forgiving with whitespace, comments etc. First arg is the solution file, second is the attempt
import ast
import sys
def find_difference(a,b,lastpos=(0,0)):
if isinstance(b,ast.expr) or isinstance(b,ast.stmt):
lastpos = b.lineno,b.col_offset
if type(a) != type(b): return lastpos
if isinstance(a,ast.AST):
for field in a._fields:
r = find_difference(getattr(a,field),getattr(b,field),lastpos)
if r: return r
elif isinstance(a,list) or isinstance(a,tuple):
for i,j in zip(a,b):
r = find_difference(i,j,lastpos)
if r: return r
else:
if a != b: return lastpos
def show_feedback(message,lines,ln,char):
print
print message
print
for j,line in enumerate(lines):
print str(j+1).rjust(4)+": "+line,
if j+1 != ln: continue
print " "*5 + " "*char + "^"
print " "*5 + " "*char + "'--- PROBLEM HERE"
print
print
with open(sys.argv[1],"r") as f: ex_lines = f.readlines()
ex_tree = ast.parse("".join(ex_lines),sys.argv[1])
with open(sys.argv[2],"r") as f: ac_lines = f.readlines()
try:
ac_tree = ast.parse("".join(ac_lines),sys.argv[2])
diff = find_difference(ex_tree,ac_tree)
if diff:
show_feedback("Different from solution",ac_lines,diff[0],diff[1])
else:
print "Matches solution"
except SyntaxError as e:
line,char = e.args[1][1:3]
show_feedback("Syntax is incorrect",ac_lines,line,char)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment