/* a Node holds one node of a parse tree with several pointers to children used depending on the kind of node */ import java.awt.*; import java.util.Scanner; public class Node { public static int count = 0; // maintain unique id for each node private int id; private String kind; // non-terminal or terminal category for the node private String info; // extra information about the node such as // the actual identifier for an I // references to children in the parse tree private Node first, second, third; // memory table shared by all nodes private static MemTable table = new MemTable(); private static Scanner keys = new Scanner( System.in ); // construct a common node with no info specified public Node( String k, Node one, Node two, Node three ) { kind = k; info = ""; first = one; second = two; third = three; id = count; count++; System.out.println( this ); } // construct a node with specified info public Node( String k, String inf, Node one, Node two, Node three ) { kind = k; info = inf; first = one; second = two; third = three; id = count; count++; System.out.println( this ); } // construct a node that is essentially a token public Node( Token token ) { kind = token.getKind(); info = token.getDetails(); first = null; second = null; third = null; id = count; count++; System.out.println( this ); } public String toString() { return "#" + id + "[" + kind + "," + info + "]<" + nice(first) + " " + nice(second) + ">"; } public String nice( Node node ) { if ( node == null ) { return ""; } else { return "" + node.id; } } // produce array with the non-null children // in order private Node[] getChildren() { int count = 0; if( first != null ) count++; if( second != null ) count++; if( third != null ) count++; Node[] children = new Node[count]; int k=0; if( first != null ) { children[k] = first; k++; } if( second != null ) { children[k] = second; k++; } if( third != null ) { children[k] = third; k++; } return children; } //****************************************************** // graphical display of this node and its subtree // in given camera, with specified location (x,y) of this // node, and specified distances horizontally and vertically // to children public void draw( Camera cam, double x, double y, double h, double v ) { System.out.println("draw node " + id ); // set drawing color cam.setColor( Color.black ); String text = kind; if( ! info.equals("") ) text += "(" + info + ")"; cam.drawHorizCenteredText( text, x, y ); // positioning of children depends on how many // in a nice, uniform manner Node[] children = getChildren(); int number = children.length; System.out.println("has " + number + " children"); double top = y - 0.75*v; if( number == 0 ) { return; } else if( number == 1 ) { children[0].draw( cam, x, y-v, h/2, v ); cam.drawLine( x, y, x, top ); } else if( number == 2 ) { children[0].draw( cam, x-h/2, y-v, h/2, v ); cam.drawLine( x, y, x-h/2, top ); children[1].draw( cam, x+h/2, y-v, h/2, v ); cam.drawLine( x, y, x+h/2, top ); } else if( number == 3 ) { children[0].draw( cam, x-h, y-v, h/2, v ); cam.drawLine( x, y, x-h, top ); children[1].draw( cam, x, y-v, h/2, v ); cam.drawLine( x, y, x, top ); children[2].draw( cam, x+h, y-v, h/2, v ); cam.drawLine( x, y, x+h, top ); } else { System.out.println("no Node kind has more than 3 children???"); System.exit(1); } }// draw public static void error( String message ) { System.out.println( message ); System.exit(1); } // ask this node to execute itself // (for nodes that don't return a value) public void execute() { if ( kind.equals("stmts") ) { // insert code here for Exercise 15 } else if ( kind.equals("prtstr") ) { System.out.print( info ); } else if ( kind.equals("prtexp") ) { // insert code here for Exercise 15 } else if ( kind.equals("nl") ) { System.out.print( "\n" ); } else if ( kind.equals("sto") ) { // insert code here for Exercise 15 } else { error("Unknown kind of node [" + kind + "]"); } }// execute // compute and return value produced by this node public double evaluate() { if ( kind.equals("num") ) { return Double.parseDouble( info ); } else if ( kind.equals("var") ) { return table.retrieve( info ); } else if ( kind.equals("+") || kind.equals("-") ) { double val1 = first.evaluate(); double val2 = second.evaluate(); if (kind.equals("+")) return val1 + val2; else return val1 - val2; } else if ( kind.equals("*") || kind.equals("/") ) { double val1 = first.evaluate(); double val2 = second.evaluate(); if (kind.equals("*")) return val1 * val2; else return val1 / val2; } else if ( kind.equals("input") ) { return keys.nextDouble(); } else if ( kind.equals("sqrt") || kind.equals("cos") || kind.equals("sin") || kind.equals("atan") ) { double value = first.evaluate(); if ( kind.equals("sqrt") ) return Math.sqrt(value); else if ( kind.equals("cos") ) return Math.cos( Math.toRadians( value ) ); else if ( kind.equals("sin") ) return Math.sin( Math.toRadians( value ) ); else if ( kind.equals("atan") ) return Math.toDegrees( Math.atan( value ) ); else { error("unknown function name [" + kind + "]"); return 0; } } else if ( kind.equals("pow") ) { double val1 = first.evaluate(); double val2 = second.evaluate(); return Math.pow(val1, val2); } else if ( kind.equals("opp") ) { double val = first.evaluate(); return -val; } else { error("Unknown node kind [" + kind + "]"); return 0; } }// evaluate }// Node