# drawing figures with natural language commands # presupposes 'gf -make DrawEng.gf (DrawSwe.gf ...)' import pgf from graphics import * import sys from random import randrange # we assume this abstract syntax absmodule = "Draw" # change this to change input language langname = absmodule + "Eng" # the size of canvas hsize, vsize = 1000,1000 # the mid point of the canvas midpoint = (hsize/2,vsize/2) # unit size granularity sizeunit = hsize//10 # big and small size factors bigsize = 2 smallsize = 0.2 # limits of radius and diameter/2 maxradius = sizeunit minradius = sizeunit/2 # distance of movement distunit = 2*sizeunit def execute(command,win): "top level: execute a Command in a window (given in main)" fun,args = command.unpack() if fun == "drawCommand": obj = shape(args[0]) obj.draw(win) return str(args[0]),obj,fun if fun == "removeCommand": key = reference(args[0]) return key,None,fun if fun == "moveCommand": key = reference(args[0]) return key,direction(args[1]),fun def reference(objectref): fun,args = objectref.unpack() if fun == "theObjectRef": return(str(args[0])) else: return(str(objectref)) def shape(obj): "draw a Shape of random size and position, possibly with colour and rough size specified" fun,args = obj.unpack() sz,xx = args[0].unpack() if sz == "big_Size": factor = bigsize elif sz == "small_Size": factor = smallsize else: factor = 1 midx,midy = midpoint x1 = midx + randrange(int(-midx),int(midx),1) y1 = midy + randrange(int(-midy),int(midy),1) r = factor * randrange(int(minradius), int(maxradius), 1) d = 2 * r x2 = x1 + d y2 = y1 + d sh,xx = args[2].unpack() if sh == "circle_Shape": shap = Circle(Point(x1,y1),r) elif sh == "square_Shape": shap = Rectangle(Point(x1,y1),Point(x2,y2)) else: shap = None co,xx = args[1].unpack() if co == "green_Colour": shap.setFill('green') elif co == "red_Colour": shap.setFill('red') elif co == "blue_Colour": shap.setFill('blue') elif co == "yellow_Colour": shap.setFill('yellow') else: pass return shap def direction(place): fun,args = place.unpack() if fun == "upPlace": return 0,-distunit if fun == "downPlace": return 0,distunit if fun == "leftPlace": return -distunit,0 if fun == "rightPlace": return distunit,0 else: return randrange(-2*distunit,2*distunit,1),randrange(-2*distunit,2*distunit,1) def addRef(ref,obj,refs): "adds a reference and object to the top of the stack" return [(ref,obj)] + refs def lookupRef(ref,refs): "return the first value and index of ref in a list of pairs refs" i = 0 for ro in refs: r,obj = ro if matchRef(ref,r): return r,obj,i else: i = i + 1 return None,None,None def removeRef(ref,refs): "remove the first pair matching ref in refs" r,obj,i = lookupRef(ref,refs) refs.pop(i) return refs def matchRef(ref,r): if ref == "itObjectRef": return True else: refws = ref.split() rws = r.split() m = True for i in range(1,4): if (refws[i][0:2] != "no") and (refws[i] != rws[i]): return False return m def main(): "initialize with a window, process Command input line by line; optional language argument" win = GraphWin("GF Draw", hsize, vsize) refs = [] latest = "it" gr = pgf.readPGF(absmodule + ".pgf") lang = langname if len(sys.argv) > 1: lang = absmodule + sys.argv[1] eng = gr.languages[lang] while True: try: line = input("") except EOFError: break if not(line): pass else: try: px = eng.parse(line.lower()) p,tree = px.__next__() key,obj,co = execute(tree,win) if co == "drawCommand": refs = addRef(key,obj,refs) elif co == "removeCommand": ref,sh,i = lookupRef(key,refs) if sh is None: print("no such object") else: sh.undraw() refs = removeRef(key,refs) elif co == "moveCommand": x,y = obj ref,sh,i = lookupRef(key,refs) if sh is None: print("no such object") else: sh.move(x,y) refs = [(ref,sh)] + refs[:i] + refs[i+1:] else: print("nothing else can be done") print(refs) ## debugging except pgf.ParseError: print("# NO PARSE", line) main()