CS 635: Advanced Object-Oriented Design & Programming |
---|
Code For Assignment 3 | slide # 2 |
...//Test Program | slide # 3 |
...//ExpressionParser | |
slide # 4 | |
...//Visitor | slide # 5 |
...//Node | slide # 6 |
...//External Node | slide # 7 |
...//UnaryNode | slide # 8 |
...//BinaryNode | slide # 9 |
...//NullNode | slide # 10 |
if ( token == "+" ) process the + else if ( token == "*" ) process the * etc.StringTokenizer
// Simple Test program public class Test { public static void main( String[] args ) throws IOException { String[] expressions = { "1 2 +" , "3 a", "1 2 3 + * ", " 1 2 + 3 a 4 5 * - +"}; testParsing( expressions); } public static void testParsing( String[] expressions ) throws IOException { ExpressionParser parser = new ExpressionParser(); Node expressionTree; Writer out = new OutputStreamWriter (System.out ); for (int k = 0; k < expressions.length; k++ ) { expressionTree = parser.parsePostfix( expressions[k] ); expressionTree.print( out ); } }
import java.util.*; // This class converts postfix notation into a tree structure // An example of postfix notation is "1 2 3 + *" which is the expression // (1 * ( 2 + 3 ) public class ExpressionParser { //the space character separates tokens String tokenSeparators = " "; //the space character separates operators in the string String binaryOperators = "+ - *"; String unaryOperators = "a"; //Pass this method your postFixExpression // It will return your tree public Node parsePostfix( String postFixExpression ) { Stack treeNodes = new Stack(); StringTokenizer parser = new StringTokenizer( postFixExpression, tokenSeparators ); while ( parser.hasMoreTokens() ) { String token = parser.nextToken(); if ( isUnaryOperator( token ) ) processUnaryOperator( token, treeNodes ); else if ( isBinaryOperator( token ) ) processBinaryOperator( token, treeNodes ); else processOperand( token, treeNodes ); } return (Node) treeNodes.pop(); } private void processOperand( String operand, Stack treeNodes) { int intOperand = Integer.parseInt( operand ); ExternalNode leaf = new ExternalNode( intOperand ); treeNodes.push( leaf ); } private void processBinaryOperator( String operator, Stack treeNodes) { BinaryNode nodeOperator = new BinaryNode( operator ); Node rightOperand = (Node) treeNodes.pop(); Node leftOperand = (Node) treeNodes.pop(); nodeOperator.setRightChild( rightOperand ); nodeOperator.setLeftChild( leftOperand ); treeNodes.push( nodeOperator ); } private void processUnaryOperator( String operator, Stack treeNodes) { UnaryNode nodeOperator = new UnaryNode( operator ); Node operand = (Node) treeNodes.pop(); nodeOperator.setChild( operand ); treeNodes.push( nodeOperator ); } private boolean isBinaryOperator( String operator) { return contains( binaryOperators, operator ); } private boolean isUnaryOperator( String operator) { return contains( unaryOperators, operator ); } private boolean contains( String text, String pattern ) { if ( text.indexOf( pattern ) > -1 ) return true; else return false; } }
public interface Visitor { public void visitBinaryNode( BinaryNode aNode); public void visitUnaryNode( UnaryNode aNode); public void visitExternalNode( ExternalNode aNode); }
import java.io.Writer; import java.io.IOException; // this class is the parent class of all the tree nodes public abstract class Node { private Node parentNode; // Print out the tree rooted at current node // For testing only. Does not satisfy problem 1 public abstract void print( Writer ouput) throws IOException; public abstract void accept( Visitor aVistor); // Useful in traversing trees public Node getParent() { return parentNode; } protected void setParent( Node myParent ) { parentNode = myParent; } }
import java.io.Writer; import java.io.IOException; // this class is used to store the operands (ints) in the // leaves of the tree public class ExternalNode extends Node { private int data; public ExternalNode( int data ) { setData( data ); } public int getData() { return data; } public void setData( int newData) { data = newData; } public void print( Writer output) throws IOException { // The Writer's write statement only works with // strings, so convert output.write( String.valueOf( data ) ); output.flush(); } public void accept( Visitor aVisitor) { aVisitor.visitExternalNode( this ); } }
import java.io.Writer; import java.io.IOException; // this class is used to store unary operators // In our assignment we only have one unary operator public class UnaryNode extends Node { private Node child = NullNode.getInstance(); String data; public UnaryNode( String data ) { setData( data ); } public String getData() { return data; } public void setData( String newData) { data = newData; } public Node getChild() { return child; } public void setChild( Node newChild) { child = newChild; newChild.setParent( this ); } /** * Print out the tree rooted at this node as a fully * parenthesised expression. This is for testing the * construction of the tree. This print statement does * not satisfy the requirements of the assignment */ public void print( Writer output) throws IOException { output.write( " (" ); output.write( data ); child.print( output ); output.write( ") " ); output.flush(); } /** * This accept assumes that the nodes are doing the * traversal through the structure. You will need to change this * for problem 2 */ public void accept( Visitor aVisitor) { child.accept( aVisitor ); aVisitor.visitUnaryNode( this ); } }
import java.io.Writer; import java.io.IOException; // This class in used for binary operators public class BinaryNode extends Node { private Node leftChild = NullNode.getInstance(); private Node rightChild = NullNode.getInstance(); private String data; public BinaryNode( String data ) { setData( data ); } public String getData() { return data; } public void setData( String newData) { data = newData; } public Node getLeftChild() { return leftChild; } public Node getRightChild() { return rightChild; } public void setLeftChild( Node newChild) { leftChild = newChild; newChild.setParent( this ); } public void setRightChild( Node newChild) { rightChild = newChild; newChild.setParent( this ); } /** * Print out the tree rooted at this node as a fully * parenthesised expression. This is for testing the * construction of the tree. This print statement does * not satisfy the requirements of the assignment */ public void print( Writer output) throws IOException { output.write( " (" ); leftChild.print( output ); output.write( data ); rightChild.print( output ); output.write( ") " ); output.flush(); } /** * This accept assumes that the nodes are doing the * traversal through the structure. You will need to change this * for problem 2 */ public void accept( Visitor aVisitor) { leftChild.accept( aVisitor ); aVisitor.visitBinaryNode( this ); rightChild.accept( aVisitor ); } }
import java.io.Writer; /** * NullNode does nothing. Used to replace null reference * to childern in Binary and Unary nodes. Does the * NullObject pattern make sense in this context? */ public class NullNode extends Node { // Java's static initilizers make the singleton's slightly // easier than in C++, private static NullNode singleton = new NullNode(); private NullNode() {}; public static Node getInstance() { return singleton; } public void print( Writer output) { } public void accept( Visitor aVisitor) { } }Copyright © 1998 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA
All rights reserved.visitors since 01-May-98