import Jakarta.util.*; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.PrintWriter; import java.io.Reader; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.io.Writer; import java.net.URI; import java.util.Hashtable; import java.util.List; import java.util.Stack; import java.util.EmptyStackException; import java.util.Vector; //************************************************** // Class AstListNode //************************************************** public abstract class AstListNode extends AstNode implements Cloneable { public AstListNode setParms( AstNode _arg1 ) { arg = new AstNode[1]; arg[0] = _arg1; up = left = right = null; // if list is empty just return if ( _arg1 == null ) return ( ( AstListNode ) this ); if ( kernelConstants.debugAST ) { if ( _arg1.up != null ) fatalError( "setParms called with non-detached argument" ); } // now update traversal pointers of child arg[0].left = null; arg[0].up = this; arg[0].right = null; return ( ( AstListNode ) this ); } public Object clone() { AstListNode copy; copy = null; try { copy = ( AstListNode ) getClass().newInstance(); } catch ( Exception e ) { e.printStackTrace( System.err ); System.err.println( "Can't clone "+getClass() ); System.exit( 1 ); } super.initClone( copy ); // copy child initClone( copy ); // copy right return ( copy ); } protected void initClone( AstListNode copy ) { if ( right != null ) { copy.right = ( AstNode ) right.clone(); copy.right.left = copy; } } // printorder() normally returns a boolean array that indicates how // tokens and arguments are to be interlaced when printing. AstList // nodes have a special printing algorithm, and thus printorder should // never be called public boolean[] printorder() { fatalError( "shouldn't call AstListNode::printorder()" ); return ( new boolean[0] ); } // Delete() the element from the list. If the list becomes empty, then // the list itself is deleted. Note that list deletion might not // entail much unless we are deleting a list that is an element of // another list (i.e., list of lists). public void Delete() { // physically remove element from list AstList head; // Step 1: fix left and right pointers if ( left != null ) left.right = right; if ( right != null ) right.left = left; // Step 2: fix parent (which is an AstList instance) head = ( AstList ) up; if ( head.last == this ) head.last = left; if ( head.arg[0] == this ) head.arg[0] = right; // Step 3: now, check to see if the list on which this element // is empty. If so, delete the list if ( head.arg[0] == null ) head.Delete(); // Clear neighbor pointers left = null; right = null; } // AddAfter(l) adds (splices) list l immediately after this node // if l is an empty list, AddAfter(l) does nothing. Upon return, // l is an empty list. public void AddAfter( AstList tree ) { AstNode nxt, fst, lst, l; AstList par = ( AstList ) up; // Step 1: ignore operation that inserts an empty tree if ( tree == null || tree.arg[0] == null ) return; // Step 2: remember references to common ptrs: next, first, last nxt = right; fst = tree.arg[0]; lst = tree.last; // Step 3: fix the up pointers on the list we are adding for ( l = fst; l != null; l = l.right ) l.up = par; // Step 4: connect links in the right direction lst.right = nxt; right = fst; // Step 5: connect links in the left direction fst.left = this; if ( nxt != null ) nxt.left = lst; // Step 6: update up.last if necessary if ( par.last == this ) par.last = lst; // Step 7: make sure that the tree is no longer // accessable tree.up = null; tree.Delete(); } // AddBefore(l) splices list l immediately before the current node // otherwise same semantics as AddAfter public void AddBefore( AstList tree ) { AstNode prv, fst, lst, l; AstList par = ( AstList ) up; // Step 1: ignore operation that inserts an empty tree if ( tree == null || tree.arg[0] == null ) return; // Step 2: remember common pointers: previous, first, last prv = left; fst = tree.arg[0]; lst = tree.last; // Step 3: fix the up pointers on the list we are adding for ( l = fst; l != null; l = l.right ) l.up = par; // Step 4: connect links in the right direction lst.right = this; if ( prv != null ) prv.right = fst; // Step 5: connect links in the left direction fst.left = prv; left = lst; // Step 6: update up.arg[0] if necessary if ( par.arg[0] == this ) par.arg[0] = fst; // Step 7: make sure that the root of tree is no longer // accessable tree.up = null; tree.Delete(); } // print() and reduce2java() should never be called. List printing // is done by AstList::print() and AstList::reduce2java(). public void print() { System.out.println( "Error - AstListNode::print should not be called" ); } public void print( AstProperties props ) { System.out.println( "Error - AstListNode::print should not be called" ); } public void reduce2java( AstProperties props ) { System.out.println( "Error - AstListNode::reduce2java should not be called" ); } // reduce2java() generates the Java code that recreates the tree // rooted at the current element. }