import sys current_line = 1 def unoop_tokenize(input): global current_line dollars = '' should_read = True while True: if should_read: ch = input.read(1) should_read = True if ch == '': yield "" break elif ch in " \n\r\t\f\v": if ch=='\n': current_line = current_line+1 elif ch == "#": while ch not in "\r\n" and ch != '': ch = input.read(1) if ch=='\n': current_line = current_line+1 if ch == '': break elif ch == "$": dollars = dollars + '$' elif ch == "'": if dollars != '': raise SyntaxError,"$'" ch = input.read(1) #if ch == '': #raise SyntaxError,"'$" if ch=='\n': current_line = current_line+1 yield "'"+ch elif ch == "`" or ch == "+": if dollars != '': raise SyntaxError,"$`" yield ch colons = 0 ch = ' ' while ch in " \n\r\t\f\v:": if ch==':': colons = colons + 1 ch = input.read(1) yield colons should_read = False else: yield dollars+ch dollars = '' # UnoopClass: {methodname:etc.,'super':super} # UnoopMethod: ([args], expr) # UnoopInstance: {'class':class,variables} unoop_classes = {} current_character = '' class UnoopExpr: def __init__(self): pass def eval(self,instance,args): raise Exception def __str__(self): return "" class DotExpr(UnoopExpr): def eval(self,instance,args): return instance def __str__(self): return "." class ArgExpr(UnoopExpr): def __init__(self,name): UnoopExpr.__init__(self) self.name = name def eval(self,instance,args): if self.name not in args: raise Exception, self.name+" not an argument in "+instance['class']['name'] return args[self.name] def __str__(self): return self.name class InstVarExpr(UnoopExpr): def __init__(self,name): UnoopExpr.__init__(self) self.name = name def eval(self,instance,args): if self.name not in instance: raise Exception, self.name+" not an instance variable of "+instance['class']['name'] return instance[self.name] def __str__(self): return '?'+self.name class AssignExpr(UnoopExpr): def __init__(self,name,expr): UnoopExpr.__init__(self) self.name = name self.expr = expr def eval(self,instance,args): instance[self.name] = self.expr.eval(instance,args) return instance[self.name] def __str__(self): return '='+self.name+str(self.expr) class CallExpr(UnoopExpr): def __init__(self,obj,name,exprs): UnoopExpr.__init__(self) self.obj = obj self.name = name self.exprs = exprs def eval(self,instance,args): obj = self.obj.eval(instance,args) if self.name not in obj["class"]: raise Exception, self.name+" is not a method of "+obj['class']['name'] method = obj["class"][self.name] newargs = {} for name,val in zip(method[0],self.exprs): newargs[name] = val.eval(instance,args) return method[1].eval(obj,newargs) def __str__(self): return '`'+self.name+str(self.obj)+str(self.exprs) class CreateExpr(UnoopExpr): def __init__(self,obj,name,exprs): UnoopExpr.__init__(self) self.obj = obj self.name = name self.exprs = exprs def eval(self,instance,args): obj = {'class':unoop_classes[self.obj]} if self.name not in obj["class"]: raise Exception, self.name+" is not a method of "+obj['class']['name'] method = obj["class"][self.name] newargs = {} for name,val in zip(method[0],self.exprs): newargs[name] = val.eval(instance,args) method[1].eval(obj,newargs) return obj def __str__(self): return self.name+str(self.obj)+str(self.exprs) class InitExpr(UnoopExpr): def __init__(self,clazz,name,exprs,expr): UnoopExpr.__init__(self) self.clazz = clazz self.name = name self.exprs = exprs self.expr = expr def eval(self,instance,args): if self.name not in unoop_classes[self.clazz]["super"]: raise Exception, self.name+" is not a method of "+unoop_classes[self.clazz]['super']['name'] method = unoop_classes[self.clazz]["super"][self.name] newargs = {} for name,val in zip(method[0],self.exprs): newargs[name] = val.eval(instance,args) method[1].eval(instance,newargs) self.expr.eval(instance,args) def __str__(self): return self.name+self.clazz+str(self.exprs)+str(self.expr) class QuitExpr(UnoopExpr): def eval(self,instance,args): exit(0) def __str__(self): return 'Q' class ReadExpr(UnoopExpr): def eval(self,instance,args): global current_char current_char = sys.stdin.read(1) return {'class':unoop_class("'"+current_char)} def __str__(self): return '@' class PrintExpr(UnoopExpr): def __init__(self,char): UnoopExpr.__init__(self) self.char = char def eval(self,instance,args): sys.stdout.write(self.char) return instance def __str__(self): return "'"+self.char class TestExpr(UnoopExpr): def __init__(self,char): UnoopExpr.__init__(self) self.char = char def eval(self,instance,args): if current_char==self.char: return args['t'] else: return args['f'] ############################################################################# # PARSER def isname(n): if "'" in n: return False if n=='': return False return n[len(n)-1] in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_@" def readExpr(it): ch = it.next() if ch=='.': return DotExpr() elif isname(ch): return ArgExpr(ch) elif ch=='?': name = it.next() if not isname(name): raise Exception("Expecting name after ?") return InstVarExpr(name) elif ch=='=': name = it.next() if not isname(name): raise Exception("Expecting name after =") expr = readExpr(it) return AssignExpr(name,expr) elif ch=='`': colons = it.next() name = it.next() if not isname(name): raise Exception("Expecting name after `, found "+name) expr1 = readExpr(it) expr2 = [] for i in xrange(colons): expr2.append(readExpr(it)) return CallExpr(expr1,(':'*colons)+name,expr2) elif ch=='+': colons = it.next() name = it.next() if not isname(name): raise Exception("Expecting name after +, found "+name) expr2 = [] for i in xrange(colons): expr2.append(readExpr(it)) return CreateExpr(name,'+'+(':'*colons),expr2) else: raise Exception("Unrecognized expression "+ch) current_class = {'name':'NO CLASS DEFINED'} def unoop_class(c,msg=''): if "'" in c: return {'name':c,'super':unoop_class('0'),'p':([],PrintExpr(c[1:])),'::q':(['t','f'],TestExpr(c[1:])),'Q':unoop_class('0')['Q'],'@':unoop_class('0')['@'],'+':([],DotExpr())} elif c in unoop_classes: return unoop_classes[c] else: raise Exception("Class not found: "+c+msg) def readUnoopIt(it): global current_class while True: ch = it.next() if isname(ch): # define class if ch in unoop_classes: print ch+" defined twice!!!" current_class = {'super':unoop_class(it.next(),' for superclass of '+ch),'name':ch} for i in current_class["super"]: if i not in ['super','name']: current_class[i] = current_class["super"][i] unoop_classes[ch] = current_class elif ch=='+': # constructor colons1 = it.next() args = [] for i in xrange(colons1): ch = it.next() if not isname(ch): raise Exception("Expected arg name for constructor, found "+ch) args.append(ch) ch = it.next() if ch!='+': raise Exception("Expected +, found "+ch) colons2 = it.next() superargs = [] for i in xrange(colons2): superargs.append(readExpr(it)) expr = readExpr(it) current_class['+'+(':'*colons1)] = (args,InitExpr(current_class['name'],'+'+(':'*colons2),superargs,expr)) elif ch=='`': colons1 = it.next() name = it.next() if not isname(name): raise Exception("Expected name, found "+name) args = [] for i in xrange(colons1): ch = it.next() if not isname(ch): raise Exception("Expected arg name for "+name+", found "+ch) args.append(ch) expr = readExpr(it) current_class[(':'*colons1)+name] = (args,expr) elif ch=='': break else: raise Exception("Unexpected toplevel "+ch+" in "+current_class['name']) def readUnoop(input): readUnoopIt(unoop_tokenize(input)) unoop_classes['0'] = {'name':'0', 'Q':([],QuitExpr()), '@':([],ReadExpr()), '+':([],DotExpr())} def run_unoop(): CreateExpr('_','+',[]).eval(None,None) if __name__=='__main__': for i in sys.argv[1:]: try: f = open(i,'r') readUnoop(f) f.close() except Exception, s: print s print current_line else: run_unoop()