import java.awt.*; import java.net.*; import java.awt.image.*; import java.applet.*; import java.util.Hashtable; public class Mockingbird extends Applet { Label bird1Name, bird2Name, newBirdName, newBirdLambda; Label leftArgLabel, rightArgLabel; Button play, composeArgs; Choice bird1Choice, bird2Choice; ImageButton bird1Picture, bird2Picture, newBirdPicture; static TextArea betaReduction; Image tempImage; TextField leftArg, rightArg; GridBagLayout gridbag; GridBagConstraints constraints; String bird1String, bird2String; private String keys = "abcdefghijklmnopqrstuvwxyz.*L"; static private Hashtable notes; AudioClip testSound; static TreeNode root, newRoot; static TreeNode replacementNode; static char replaceItChar; static int charIndex; static String lambda, lambda2; static boolean foundStarStart; static StringBuffer renameWork; void buildConstraints(GridBagConstraints gbc, int gx, int gy, int gw, int gh, int wx, int wy) { gbc.gridx = gx; gbc.gridy = gy; gbc.gridwidth = gw; gbc.gridheight = gh; gbc.weightx = wx; gbc.weighty = wy; } public void init() { this.setBackground(Color.white); gridbag = new GridBagLayout(); constraints = new GridBagConstraints(); setLayout(gridbag); // BIRD1 name buildConstraints(constraints, 1, 0, 1, 1, 30, 20); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.SOUTH; bird1Name = new Label("La.a"); bird1Name.setAlignment(bird1Name.CENTER); gridbag.setConstraints(bird1Name, constraints); add(bird1Name); // BIRD2 name buildConstraints(constraints, 4, 0, 1, 1, 30, 20); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.SOUTH; bird2Name = new Label("Lx.x"); bird2Name.setAlignment(bird2Name.CENTER); gridbag.setConstraints(bird2Name, constraints); add(bird2Name); // BIRD1 choice buildConstraints(constraints, 0, 1, 1, 1, 5, 30); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; bird1Choice = new Choice(); bird1Choice.addItem("Identity Bird"); bird1Choice.addItem("Mockingbird"); bird1Choice.addItem("Kestrel"); bird1Choice.addItem("Kite"); bird1Choice.addItem("Identity Bird (removed)"); bird1Choice.addItem("Thrush"); bird1Choice.addItem("Konstant Mocker"); bird1Choice.addItem("X'd Konstant Mocker"); bird1Choice.addItem("Lark"); bird1Choice.addItem("Owl"); bird1Choice.addItem("Warbler"); bird1Choice.addItem("Crossed Warbler"); bird1Choice.addItem("Cardinal"); bird1Choice.addItem("Bluebird"); gridbag.setConstraints(bird1Choice, constraints); add(bird1Choice); // BIRD1 picture buildConstraints(constraints, 1, 1, 1, 1, 30, 30); bird1Picture = new ImageButton(getCodeBase(), "images/Identity.jpg"); bird1Picture.resize(200, 200); constraints.fill = GridBagConstraints.BOTH; constraints.anchor = GridBagConstraints.CENTER; gridbag.setConstraints(bird1Picture, constraints); add(bird1Picture); // play button buildConstraints(constraints, 2, 1, 1, 1, 30, 20); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.CENTER; play = new Button("APPLY BIRDS"); gridbag.setConstraints(play, constraints); add(play); // BIRD2 choice buildConstraints(constraints, 3, 1, 1, 1, 5, 30); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; bird2Choice = new Choice(); bird2Choice.addItem("Identity Bird"); bird2Choice.addItem("Mockingbird"); bird2Choice.addItem("Kestrel"); bird2Choice.addItem("Kite"); bird2Choice.addItem("Identity Bird (removed)"); bird2Choice.addItem("Thrush"); bird2Choice.addItem("Konstant Mocker"); bird2Choice.addItem("X'd Konstant Mocker"); bird2Choice.addItem("Lark"); bird2Choice.addItem("Owl"); bird2Choice.addItem("Warbler"); bird2Choice.addItem("Crossed Warbler"); bird2Choice.addItem("Cardinal"); bird2Choice.addItem("Bluebird"); gridbag.setConstraints(bird2Choice, constraints); add(bird2Choice); // BIRD2 picture buildConstraints(constraints, 4, 1, 1, 1, 30, 30); bird2Picture = new ImageButton(getCodeBase(), "images/Identity.jpg"); bird2Picture.resize(200, 200); constraints.fill = GridBagConstraints.BOTH; constraints.anchor = GridBagConstraints.CENTER; gridbag.setConstraints(bird2Picture, constraints); add(bird2Picture); // NewBirdLambda buildConstraints(constraints, 2, 2, 1, 1, 30, 20); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.SOUTH; newBirdLambda = new Label("Lx.x"); newBirdLambda.setAlignment(newBirdLambda.CENTER); gridbag.setConstraints(newBirdLambda, constraints); add(newBirdLambda); // left arg label buildConstraints(constraints, 0, 3, 1, 1, 5, 20); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.SOUTH; leftArgLabel = new Label("Left Expression"); leftArgLabel.setAlignment(leftArgLabel.CENTER); gridbag.setConstraints(leftArgLabel, constraints); add(leftArgLabel); // right arg label buildConstraints(constraints, 1, 3, 1, 1, 5, 20); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.SOUTH; rightArgLabel = new Label("Right Expression"); rightArgLabel.setAlignment(rightArgLabel.CENTER); gridbag.setConstraints(rightArgLabel, constraints); add(rightArgLabel); // resultant bird picture buildConstraints(constraints, 2, 3, 1, 3, 30, 30); newBirdPicture = new ImageButton(getCodeBase(), "images/Identity.jpg"); newBirdPicture.resize(200, 200); constraints.fill = GridBagConstraints.BOTH; constraints.anchor = GridBagConstraints.CENTER; gridbag.setConstraints(newBirdPicture, constraints); add(newBirdPicture); // beta reduction buildConstraints(constraints, 3, 3, 2, 3, 30, 40); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; betaReduction = new TextArea("BETA REDUCTION AREA", 15, 35); betaReduction.setEditable(false); gridbag.setConstraints(betaReduction, constraints); add(betaReduction); // left arg buildConstraints(constraints, 0, 4, 1, 1, 5, 30); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.NORTH; leftArg = new TextField(12); gridbag.setConstraints(leftArg, constraints); add(leftArg); // right arg buildConstraints(constraints, 1, 4, 1, 1, 5, 30); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.NORTH; rightArg = new TextField(12); gridbag.setConstraints(rightArg, constraints); add(rightArg); // compose arg button buildConstraints(constraints, 0, 5, 2, 1, 5, 20); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.NORTH; composeArgs = new Button("APPLY EXPRESSIONS"); gridbag.setConstraints(composeArgs, constraints); add(composeArgs); // newBirdName buildConstraints(constraints, 2, 5, 1, 1, 30, 20); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.SOUTH; newBirdName = new Label("Identity Bird"); newBirdName.setAlignment(newBirdName.CENTER); gridbag.setConstraints(newBirdName, constraints); add(newBirdName); replacementNode = new TreeNode(); charIndex = 0; notes = new Hashtable(); loadSongs(); } // end init() public boolean action(Event event, Object arg) { if (event.target == bird1Choice) { if (arg.equals("Identity Bird")) { tempImage = getImage(getCodeBase(), "images/Identity.jpg"); bird1Name.setText("La.a"); } else if (arg.equals("Mockingbird")) { tempImage = getImage(getCodeBase(), "images/Mockingbird.jpg"); bird1Name.setText("La.aa"); } else if (arg.equals("Kestrel")) { tempImage = getImage(getCodeBase(), "images/Kestrel.jpg"); bird1Name.setText("La.Lb.a"); } else if (arg.equals("Kite")) { tempImage = getImage(getCodeBase(), "images/Kite.jpg"); bird1Name.setText("La.Lb.b"); } else if (arg.equals("Identity Bird (removed)")) { tempImage = getImage(getCodeBase(), "images/IdentityOnceRemoved.jpg"); bird1Name.setText("La.Lb.ab"); } else if (arg.equals("Thrush")) { tempImage = getImage(getCodeBase(), "images/Thrush.jpg"); bird1Name.setText("La.Lb.ba"); } else if (arg.equals("Konstant Mocker")) { tempImage = getImage(getCodeBase(), "images/KonstantMocker.jpg"); bird1Name.setText("La.Lb.bb"); } else if (arg.equals("X'd Konstant Mocker")) { tempImage = getImage(getCodeBase(), "images/CrossedKonstantMocker.jpg"); bird1Name.setText("La.Lb.aa"); } else if (arg.equals("Lark")) { tempImage = getImage(getCodeBase(), "images/Lark.jpg"); bird1Name.setText("La.Lb.a(bb)"); } else if (arg.equals("Owl")) { tempImage = getImage(getCodeBase(), "images/Owl.jpg"); bird1Name.setText("La.Lb.b(ab)"); } else if (arg.equals("Warbler")) { tempImage = getImage(getCodeBase(), "images/Warbler.jpg"); bird1Name.setText("La.Lb.(ab)b"); } else if (arg.equals("Crossed Warbler")) { tempImage = getImage(getCodeBase(), "images/CrossedWarbler.jpg"); bird1Name.setText("La.Lb.(ba)a"); } else if (arg.equals("Cardinal")) { tempImage = getImage(getCodeBase(), "images/Cardinal.jpg"); bird1Name.setText("La.Lb.Lc.(ac)b"); } else if (arg.equals("Bluebird")) { tempImage = getImage(getCodeBase(), "images/Bluebird.jpg"); bird1Name.setText("La.Lb.Lc.a(bc)"); } bird1Picture.setImage(tempImage); bird1Picture.grayImage = null; bird1Picture.repaint(); repaint(); return true; } else if (event.target == bird1Picture) { Character tempC; String temp = bird1Name.getText(); betaReduction.appendText("\nBird 1 is singing:\n"); for (int i = 0; i < temp.length(); i++) { tempC = new Character(temp.charAt(i)); betaReduction.appendText(tempC.toString()); play(temp.charAt(i)); try { Thread.sleep(700); } catch (InterruptedException e) { } silence(temp.charAt(i)); } return true; } else if (event.target == play) { betaReduction.appendText("\n\nBeta Reducing Birds:\n"); String str = new String(bird1Choice.getSelectedItem()); betaReduction.appendText(str); betaReduction.appendText(" and "); str = new String(bird2Choice.getSelectedItem()); betaReduction.appendText(str + "\n"); charIndex = 0; lambda = new String(bird1Name.getText()); betaReduction.appendText(lambda); try { TreeNode root = expressionTime(); charIndex = 0; lambda = new String(bird2Name.getText()); betaReduction.appendText(lambda + "\n"); TreeNode rootTwo = expressionTime(); newRoot = joinNodes(root, rootTwo); TreeNode newRootPrint, betaReducedNode; foundStarStart = false; TreeNode startNode = findStarStart(newRoot); int numBetaReduction = 0; while ((foundStarStart) && (numBetaReduction < 7)) { replacementNode = startNode.right; startNode.right = null; startNode = startNode.left; // Now do a Beta Reduction replaceItChar = startNode.left.item; if (newRoot.left == startNode) newRoot = betaReduce(startNode.right); else { betaReducedNode = betaReduce(startNode.right); startNode.item = betaReducedNode.item; startNode.left = betaReducedNode.left; startNode.right = betaReducedNode.right; } newRootPrint = copyNode(newRoot); preorderPrintWithDot(newRootPrint); betaReduction.appendText("\n"); numBetaReduction++; newRoot = collapseNullStars(newRoot); newRoot = replaceParen(newRoot); System.gc(); foundStarStart = false; startNode = findStarStart(newRoot); } // end while (foundStarStart) if (numBetaReduction >= 7) betaReduction.appendText("Beta Reduction Will Never Complete\n\n"); else betaReduction.appendText("Beta Reduction Complete\n\n"); } catch (ParseError e) { betaReduction.appendText("Sorry, Friend! Error: " + e.getMessage()); } betaReduction.appendText("Renaming to try to match a known bird . . . \n"); // put in string and rename TreeNode newRootRename = copyNode(newRoot); renameWork = new StringBuffer(); preorderFillRenameWork(newRootRename); newBirdLambda.setText(renameWork.toString()); doRenaming(); betaReduction.appendText(renameWork.toString() + "\n\n"); String imageFile = getImageFile(renameWork.toString()); tempImage = getImage(getCodeBase(), "images/" + imageFile); newBirdPicture.setImage(tempImage); newBirdPicture.grayImage = null; newBirdPicture.repaint(); repaint(); return true; } else if (event.target == bird2Choice) { if (arg.equals("Identity Bird")) { tempImage = getImage(getCodeBase(), "images/Identity.jpg"); bird2Name.setText("Lx.x"); } else if (arg.equals("Mockingbird")) { tempImage = getImage(getCodeBase(), "images/Mockingbird.jpg"); bird2Name.setText("Lx.xx"); } else if (arg.equals("Kestrel")) { tempImage = getImage(getCodeBase(), "images/Kestrel.jpg"); bird2Name.setText("Lx.Ly.x"); } else if (arg.equals("Kite")) { tempImage = getImage(getCodeBase(), "images/Kite.jpg"); bird2Name.setText("Lx.Ly.y"); } else if (arg.equals("Identity Bird (removed)")) { tempImage = getImage(getCodeBase(), "images/IdentityOnceRemoved.jpg"); bird2Name.setText("Lx.Ly.xy"); } else if (arg.equals("Thrush")) { tempImage = getImage(getCodeBase(), "images/Thrush.jpg"); bird2Name.setText("Lx.Ly.yx"); } else if (arg.equals("Konstant Mocker")) { tempImage = getImage(getCodeBase(), "images/KonstantMocker.jpg"); bird2Name.setText("Lx.Ly.yy"); } else if (arg.equals("X'd Konstant Mocker")) { tempImage = getImage(getCodeBase(), "images/CrossedKonstantMocker.jpg"); bird2Name.setText("Lx.Ly.xx"); } else if (arg.equals("Lark")) { tempImage = getImage(getCodeBase(), "images/Lark.jpg"); bird2Name.setText("Lx.Ly.x(yy)"); } else if (arg.equals("Owl")) { tempImage = getImage(getCodeBase(), "images/Owl.jpg"); bird2Name.setText("Lx.Ly.y(xy)"); } else if (arg.equals("Warbler")) { tempImage = getImage(getCodeBase(), "images/Warbler.jpg"); bird2Name.setText("Lx.Ly.(xy)y"); } else if (arg.equals("Crossed Warbler")) { tempImage = getImage(getCodeBase(), "images/CrossedWarbler.jpg"); bird2Name.setText("Lx.Ly.(yx)x"); } else if (arg.equals("Cardinal")) { tempImage = getImage(getCodeBase(), "images/Cardinal.jpg"); bird2Name.setText("Lx.Ly.Lz.(xz)y"); } else if (arg.equals("Bluebird")) { tempImage = getImage(getCodeBase(), "images/Bluebird.jpg"); bird2Name.setText("Lx.Ly.Lz.x(yz)"); } bird2Picture.setImage(tempImage); bird2Picture.grayImage = null; bird2Picture.repaint(); repaint(); return true; } else if (event.target == bird2Picture) { Character tempC; String temp = bird2Name.getText(); betaReduction.appendText("\nBird 2 is singing:\n"); for (int i = 0; i < temp.length(); i++) { tempC = new Character(temp.charAt(i)); betaReduction.appendText(tempC.toString()); play(temp.charAt(i)); try { Thread.sleep(700); } catch (InterruptedException e) { } silence(temp.charAt(i)); } return true; } else if (event.target == newBirdPicture) { betaReduction.appendText("\nThe New Bird is singing:\n"); TreeNode newRootPlay = copyNode(newRoot); preorderPlayNewBird(newRootPlay); betaReduction.appendText("\n\n"); return true; } else if (event.target == composeArgs) { TreeNode composeRoot = new TreeNode(); String temp = new String(rightArg.getText()); charIndex = 0; lambda = new String(leftArg.getText()); if ((temp.charAt(charIndex) != 'L') || (lambda.charAt(charIndex) != 'L') || (temp.length() < 4) || (lambda.length() < 4) || (temp == "") || (lambda == "")) betaReduction.appendText("\nPlease input a valid expression.\n"); else { betaReduction.appendText("\n\nBeta Reducing Expressions:\n"); betaReduction.appendText(lambda); try { TreeNode root = expressionTime(); charIndex = 0; lambda = new String(rightArg.getText()); betaReduction.appendText(lambda + "\n"); TreeNode rootTwo = expressionTime(); TreeNode newRoot = joinNodes(root, rootTwo); TreeNode newRootPrint, betaReducedNode; foundStarStart = false; TreeNode startNode = findStarStart(newRoot); int numBetaReduction = 0; while ((foundStarStart) && (numBetaReduction < 7)) { replacementNode = startNode.right; startNode.right = null; startNode = startNode.left; // Now do a Beta Reduction replaceItChar = startNode.left.item; if (newRoot.left == startNode) newRoot = betaReduce(startNode.right); else { betaReducedNode = betaReduce(startNode.right); startNode.item = betaReducedNode.item; startNode.left = betaReducedNode.left; startNode.right = betaReducedNode.right; } newRootPrint = copyNode(newRoot); preorderPrintWithDot(newRootPrint); betaReduction.appendText("\n"); numBetaReduction++; newRoot = collapseNullStars(newRoot); newRoot = replaceParen(newRoot); composeRoot = newRoot; System.gc(); foundStarStart = false; startNode = findStarStart(newRoot); } // end while (foundStarStart) if (numBetaReduction >= 7) betaReduction.appendText("Beta Reduction Will Never Complete\n\n"); else betaReduction.appendText("Beta Reduction Complete\n\n"); } catch (ParseError e) { betaReduction.appendText("Sorry, Friend! Error: " + e.getMessage()); } betaReduction.appendText("Renaming to try and match a known bird . . . \n"); if (composeRoot != null) { // put in string and rename TreeNode newRootRename = copyNode(composeRoot); renameWork = new StringBuffer(); preorderFillRenameWork(newRootRename); newBirdLambda.setText(renameWork.toString()); doRenaming(); betaReduction.appendText(renameWork.toString() + "\n\n"); String imageFile = getImageFile(renameWork.toString()); tempImage = getImage(getCodeBase(), "images/" + imageFile); newRoot = composeRoot; } else tempImage = getImage(getCodeBase(), "images/Unknown.jpg"); newBirdPicture.setImage(tempImage); newBirdPicture.grayImage = null; newBirdPicture.repaint(); repaint(); } // end else return true; } else return super.action(event, arg); } // public boolean action private String getImageFile(String bird) { if (bird.equals("La.a")) return "Identity.jpg"; else if (bird.equals("La.aa")) return "Mockingbird.jpg"; else if (bird.equals("La.aaLa.aa")) return "2Mockingbird.jpg"; else if (bird.equals("La.Lb.a")) return "Kestrel.jpg"; else if (bird.equals("La.Lb.b")) return "Kite.jpg"; else if (bird.equals("La.Lb.ab")) return "IdentityOnceRemoved.jpg"; else if (bird.equals("La.Lb.ba")) return "Thrush.jpg"; else if (bird.equals("La.Lb.bb")) return "KonstantMocker.jpg"; else if (bird.equals("La.Lb.aa")) return "CrossedKonstantMocker.jpg"; else if (bird.equals("La.Lb.a(bb)")) return "Lark.jpg"; else if (bird.equals("La.Lb.b(ab)")) return "Owl.jpg"; else if (bird.equals("La.Lb.(ab)b")) return "Warbler.jpg"; else if (bird.equals("La.Lb.(ba)a")) return "CrossedWarbler.jpg"; else if (bird.equals("La.Lb.Lc.(ac)b")) return "Cardinal.jpg"; else if (bird.equals("La.Lb.Lc.a(bc)")) return "Bluebird.jpg"; else return "Unknown.jpg"; } // end getImageFile static void doRenaming() { char c, rc, temp; int l = 0; int i = 0; int j, rn = 0; while (i < renameWork.length()) { switch(l) { case 0: rc = 'a'; break; case 1: rc = 'b'; break; case 2: rc = 'c'; break; case 3: rc = 'd'; break; case 4: rc = 'e'; break; case 5: rc = 'f'; break; default: rc = 'g'; break; } // end switch j = i; c = renameWork.charAt(j); if ((c != 'L') && (c != '.') && (c != '(') && (c != ')')) { if ((renameWork.charAt(j-1) == 'L') && (rn < 6)) { renameWork.setCharAt(j, rc); rn = 1; j++; while (j < renameWork.length()) { temp = renameWork.charAt(j); if (temp == c) { renameWork.setCharAt(j, rc); rn++; } j++; } l++; } i++; } else i++; } // end while } // end doRenaming static void preorderFillRenameWork(TreeNode top) { if (top != null ) { if (top.item == 'L') { renameWork.append(top.item); renameWork.append(top.left.item); top.left = null; renameWork.append('.'); } else if (top.item == '(') { renameWork.append('('); preorderFillRenameWork(top.left); renameWork.append(')'); top.left = null; } else if (top.item == '*') { /* print nothing */ } else renameWork.append(top.item); preorderFillRenameWork(top.left); preorderFillRenameWork(top.right); } } // end preorderFillRenameWork() private void loadSongs() { URL base = getCodeBase(); for (int i=0; i [*] * ***********************************************************/ static TreeNode expressionTime() throws ParseError { TreeNode exp; exp = simpleTime(); while ((lambda.length() > charIndex) && (lambda.charAt(charIndex) != ')')) { exp = fixLeftSideNull(exp); exp.right = fixRightSideNull(exp); } return exp; } // end expressionTime() static TreeNode fixLeftSideNull(TreeNode top) { TreeNode temp; if (top.left == null) { temp = new TreeNode(top.item); top.left = temp; top.item = '*'; top.right = null; } else top.right = fixLeftSideNull(top.right); return top; } static TreeNode fixRightSideNull(TreeNode top) { if (top.right == null) { try { top.right = expressionTime(); } catch (ParseError e) { betaReduction.appendText("Sorry! Error, Friend: " + e.getMessage()); } } else top.right = fixRightSideNull(top.right); return top.right; } /************************************************************ * * simple ::= | | () * ***********************************************************/ static TreeNode simpleTime() throws ParseError { TreeNode sim = new TreeNode(); if (lambda.charAt(charIndex) == 'L') return(lambdaTime()); else if ((lambda.charAt(charIndex) >= 'a') && (lambda.charAt(charIndex) <= 'z')) return(letterTime()); else if (lambda.charAt(charIndex) == '(') { charIndex++; sim.item = '('; sim.left = expressionTime(); if (lambda.charAt(charIndex) == ')') { charIndex++; if (lambda.length() > charIndex) sim.right = expressionTime(); else sim.right = null; return(sim); } else throw new ParseError("simpleTime looking to consume )"); } else throw new ParseError("simpleTime doesn't recognize this character"); } // end simpleTime() /************************************************************ * * lambda ::= L . * ***********************************************************/ static TreeNode lambdaTime() throws ParseError { TreeNode lam = new TreeNode(); lam.item = lambda.charAt(charIndex); charIndex++; if ((lambda.charAt(charIndex) >= 'a') && (lambda.charAt(charIndex) <= 'z')) lam.left = letterTime(); else throw new ParseError("lambdaTime looking for a letter after L"); if (lambda.charAt(charIndex) == '.') charIndex++; else throw new ParseError("lambdaTime looking to consume a ."); lam.right = expressionTime(); return lam; } // end lambdaTime() /************************************************************ * * lowercase letter ::= 'a . . . z' * ***********************************************************/ static TreeNode letterTime() throws ParseError { TreeNode let = new TreeNode(lambda.charAt(charIndex++)); return let; } // end letterTime() /************************************************************ * * Copying nodes and Joining nodes * ***********************************************************/ static TreeNode copyNode(TreeNode original) { TreeNode copy; if (original != null) { copy = new TreeNode(original.item); copy.left = copyNode(original.left); copy.right = copyNode(original.right); } else copy = null; return copy; } static TreeNode joinNodes(TreeNode bird1, TreeNode bird2) { TreeNode temp = new TreeNode('*'); temp.left = bird1; temp.right = bird2; return temp; } /************************************************************ * * Collapse any * missing the right side argument. * ***********************************************************/ static TreeNode collapseNullStars(TreeNode top) { if (top != null) { if ((top.left != null) && (top.left.item == '*') && (top.left.right == null)) top.left = top.left.left; else if ((top.item == '*') && (top.right == null) && (top.left != null) && (top.left.item == 'L')) top = top.left; top.left = collapseNullStars(top.left); top.right = collapseNullStars(top.right); } return top; } static TreeNode replaceParen(TreeNode top) { if (top != null) { if ((top.item == '(') && (top.left.item == 'L')) top.item = '*'; top.left = replaceParen(top.left); top.right = replaceParen(top.right); } return top; } static TreeNode cleanUpNull(TreeNode top) { if (top != null) { if (top.left != null) if (top.left.item == ' ') top.left = null; if (top.right != null) if (top.right.item == ' ') top.right = null; cleanUpNull(top.left); cleanUpNull(top.right); } return top; } /************************************************************ * * Find a place to do Beta Reduction * ***********************************************************/ static TreeNode findStarStart(TreeNode top) { TreeNode temp = new TreeNode(); if ((top != null) && (top.left != null)) { if ((top.item == '*') && (top.left.item == 'L')) { foundStarStart = true; return top; } else { temp = findStarStart(top.left); if (foundStarStart == false) temp = findStarStart(top.right); } } if (foundStarStart == false) temp = null; return temp; } /************************************************************ * * Now do Beta Reduction! * ***********************************************************/ static TreeNode betaReduce(TreeNode top) { if (top != null) { if (top.item == replaceItChar) { top = copyNode(replacementNode); return top; } else { top.left = betaReduce(top.left); top.right = betaReduce(top.right); } } return top; } /************************************************************ * * Print utility for the trees * ***********************************************************/ static void preorderPrintWithDot(TreeNode top) { Character temp; if (top != null ) { if (top.item == 'L') { temp = new Character(top.item); betaReduction.appendText(temp.toString()); temp = new Character(top.left.item); betaReduction.appendText(temp.toString()); top.left = null; temp = new Character('.'); betaReduction.appendText(temp.toString()); } else if (top.item == '(') { temp = new Character('('); betaReduction.appendText(temp.toString()); preorderPrintWithDot(top.left); temp = new Character(')'); betaReduction.appendText(temp.toString()); top.left = null; } else if (top.item == '*') { /* print nothing */ } else { temp = new Character(top.item); betaReduction.appendText(temp.toString()); } preorderPrintWithDot(top.left); preorderPrintWithDot(top.right); } } /************************************************************ * * Play the song for the newly created bird. * ***********************************************************/ static void preorderPlayNewBird(TreeNode top) { Character temp; if (top != null ) { if (top.item == 'L') { temp = new Character(top.item); betaReduction.appendText(temp.toString()); play(top.item); try { Thread.sleep(700); } catch (InterruptedException e) { } silence(temp.charValue()); temp = new Character(top.left.item); betaReduction.appendText(temp.toString()); play(temp.charValue()); try { Thread.sleep(700); } catch (InterruptedException e) { } silence(temp.charValue()); top.left = null; temp = new Character('.'); betaReduction.appendText(temp.toString()); play(temp.charValue()); try { Thread.sleep(700); } catch (InterruptedException e) { } silence(temp.charValue()); } else if (top.item == '(') { temp = new Character('('); betaReduction.appendText(temp.toString()); play(temp.charValue()); try { Thread.sleep(700); } catch (InterruptedException e) { } silence(temp.charValue()); preorderPlayNewBird(top.left); temp = new Character(')'); betaReduction.appendText(temp.toString()); play(temp.charValue()); try { Thread.sleep(700); } catch (InterruptedException e) { } silence(temp.charValue()); top.left = null; } else if (top.item == '*') { /* play nothing */ } else { temp = new Character(top.item); betaReduction.appendText(temp.toString()); play(temp.charValue()); try { Thread.sleep(700); } catch (InterruptedException e) { } silence(temp.charValue()); } preorderPlayNewBird(top.left); preorderPlayNewBird(top.right); } } } // end public class Mockingbird extends Applet class TreeNode { char item; // The data in this node. TreeNode left; // Pointer to left subtree. TreeNode right; // Pointer to right subtree. TreeNode() { item = ' '; left = null; right = null; }; TreeNode(char c) { item = c; left = null; right = null; }; } // end class TreeNode class Note { private AudioClip tone; private boolean playing; public Note(AudioClip sound) { playing=false; tone=sound; } public boolean isPlaying() { return playing; } public void play() { tone.loop(); playing=true; } public void stop() { tone.stop(); playing=false; } } // end public class Note class ImageButton extends Canvas { private String imageString; private int border = 0; private Color borderColor = null; private int width, height; private boolean explicitSize = false; private int explicitWidth = 0, explicitHeight = 0; private MediaTracker tracker; private static int lastTrackerID=0; private int currentTrackerID; private boolean doneLoading = false; private boolean debug = false; private Container parentContainer; protected static final int defaultBorderWidth = 4; protected static final Color defaultBorderColor = new Color(160, 160, 160); private boolean mouseIsDown = false; Image image; public ImageButton(URL imageDirectory, String file) { this(loadImage(makeURL(imageDirectory, file))); imageString = file; setBorders(); } public ImageButton(Image image) { tracker = new MediaTracker(this); setImage(image); } public void setImage(Image image) { this.image = image; currentTrackerID = lastTrackerID++; tracker.addImage(image, currentTrackerID); } public void waitForImage(boolean doLayout) { if (!doneLoading) { debug("[waitForImage] - Resizing and waiting for " + imageString); try { tracker.waitForID(currentTrackerID); } catch (InterruptedException ie) {} catch (Exception e) { System.out.println("Error loading " + imageString + ": " + e.getMessage()); e.printStackTrace(); } if (tracker.isErrorID(0)) new Throwable("Error loading image " + imageString).printStackTrace(); doneLoading = true; if (explicitWidth != 0) width = explicitWidth; else width = image.getWidth(this) + 2*border; if (explicitHeight != 0) height = explicitHeight; else height = image.getHeight(this) + 2*border; resize(width, height); debug("[waitForImage] - " + imageString + " is " + width + "x" + height + "."); if (((parentContainer = getParent()) != null) && doLayout) { setBackground(parentContainer.getBackground()); parentContainer.layout(); } } } public void centerAt(int x, int y) { debug("Placing center of " + imageString + " at (" + x + "," + y + ")"); move(x - width/2, y - height/2); } public synchronized boolean inside(int x, int y) { return((x >= 0) && (x <= width) && (y >= 0) && (y <= height)); } public void paint(Graphics g) { if (!doneLoading) waitForImage(true); else { if (explicitSize) g.drawImage(image, border, border, width-2*border, height-2*border, this); else g.drawImage(image, border, border, this); drawRect(g, 0, 0, width-1, height-1, border, borderColor); } if (grayImage == null) createGrayImage(g); drawBorder(true); } public Dimension preferredSize() { if (!doneLoading) waitForImage(false); return(super.preferredSize()); } public Dimension minimumSize() { if (!doneLoading) waitForImage(false); return(super.minimumSize()); } public void resize(int width, int height) { if (!doneLoading) { explicitSize=true; if (width > 0) explicitWidth=width; if (height > 0) explicitHeight=height; } super.resize(width, height); } public void reshape(int x, int y, int width, int height) { if (!doneLoading) { explicitSize=true; if (width > 0) explicitWidth=width; if (height > 0) explicitHeight=height; } super.reshape(x, y, width, height); } protected void drawRect(Graphics g, int left, int top, int width, int height, int lineThickness, Color rectangleColor) { g.setColor(rectangleColor); for(int i=0; i