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 AstList
//**************************************************
public abstract class AstList extends AstNode {
public AstNode last; // reference to last node on list
public AstList() {
// initialize all the standard stuff
arg = new AstNode[1];
arg[0] = null;
last = null;
}
public Object clone() {
AstList copy;
copy = null;
try {
copy = ( AstList ) getClass().newInstance();
}
catch ( Exception e ) {
fatalError( "Can't clone "+getClass() + e.getMessage() );
}
super.initClone( copy );
initClone( copy ); // last + element up pointers
return ( copy );
}
protected void initClone( AstList copy ) {
AstNode l = copy.arg[0];
// Step 1: if the list is empty, exit
copy.last = null;
if ( l==null )
return;
// Step 2: foreach element on the list, set its up pointer
// and find the last element on the list
l.up = copy;
while ( l.right != null ) {
l.up = copy;
l = l.right;
}
// Step 3: found last element - set its up pointer and
// set last
l.up = copy;
copy.last = l;
}
// 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 AstList.printorder()" );
return ( new boolean[0] );
}
// dumpnode() displays the pointer contents (up, left, right, args, last)
// of a list and its descendents.
public void dumpnode() { // dump list head node
AstNode l;
super.dumpnode();
// if (last == null)
// ps.println("\tlast:*");
// else
// ps.println("\tlast:"+last.hashCode());
if ( arg[0] == null )
return;
for ( l=arg[0].right; l!=null; l=l.right )
l.dumpnode();
}
// Delete() will delete the list. Normally, this simply means
// discarding all elements of the list (by setting the arg[0] and last
// pointers to null. However, if the list itself is an element of
// another list, i.e., the up is an instanceof AstListNode, then up
// is deleted (i.e., that element is removed from the enclosing list).
public void Delete() { // delete the list
// Step 1: if this list is an element of list, simply delete the
// element
if ( up instanceof AstListNode ) {
( ( AstListNode ) up ).Delete();
return;
}
// Step 2: else remove all children by setting the arg[0], last
// references to null
arg[0] = null;
last = null;
}
// add(x) adds AstListNode x to the end of the list. add is generally
// called only during parsing, and typically is not called by Jakarta
// users.
// add x to end of this list
public AstList add( AstListNode x ) {
if ( x == null )
return ( AstList ) this;
// Remove x from old list, if it's on one.
if ( x.up != null )
x.Delete();
// Insert x into new list
if ( last == null ) {
// empty list
last = x;
arg[0] = x;
x.right = null;
x.left = null;
}
else {
last.right = x;
x.left = last;
last = x;
}
x.up = this;
return ( AstList ) this;
}
// same as add() below, except that a separator is introduced
// between lists.
public AstList add( AstList newList, String separator ) {
// Step 1: if newList is null do nothing
if ( ( newList == null ) || ( newList.last == null ) )
return ( AstList ) this;
// Step 2: newList isn't null -- add a separator in
// front of the list
newList.arg[0].tok = new AstTokenInterface[1];
newList.arg[0].tok[0] = new AstToken().setParms( "",separator,0 );
// Step 3: compose the lists
return add( newList );
}
public AstList add( AstList newList ) {
AstNode n;
// Test if new list empty
if ( ( newList == null ) || ( newList.last == null ) )
return ( AstList ) this;
// Change parent of inserted list nodes
for ( n = newList.arg[0]; n != null; n = n.right )
n.up = this;
if ( last == null ) {
// original list is empty
arg[0] = newList.arg[0];
}
else {
last.right = newList.arg[0];
newList.arg[0].left = last;
}
last = newList.last;
// Remove any dangling pointers from old list
newList.arg[0] = null;
newList.last = null;
return ( AstList ) this;
}
// Same as add() but adds at the head of the list.
public AstList addHead( AstListNode x ) {
x.left = null;
x.right = arg[0];
x.up = this;
arg[0] = x;
if ( last == null )
last = x;
return ( AstList ) this;
}
public AstList addHead( AstList newList ) {
AstNode n;
// Test if new list empty
if ( ( newList == null ) || ( newList.last == null ) )
return ( AstList ) this;
// Change parent of inserted list nodes
for ( n=newList.arg[0]; n != null; n = n.right )
n.up = this;
if ( last == null ) {
// original list is empty
last = newList.last;
}
else {
newList.last.right = arg[0];
arg[0].left = newList.last;
}
arg[0] = newList.arg[0];
// Remove any dangling pointers from old list
newList.arg[0] = null;
newList.last = null;
return ( AstList ) this;
}
// print() prints the list. This is a special method that overrides
// the generic method of AstNode. The same thing holds for reduce2ast()
// and the reduce2java() methods.
public void print() {
AstNode l;
// Step 1: return if the list is empty
if ( arg[0] == null )
return;
// Step 2: print the first node differently than the rest
arg[0].arg[0].print();
for ( l = arg[0].right; l != null; l = l.right ) {
l.Print_Only_Tokens();
l.arg[0].print();
}
}
public void print( AstProperties props ) {
AstNode l;
// Step 1: return if the list is empty
if ( arg[0] == null )
return;
// Step 2: print the first node differently than the rest
// Note: the following code assumes that elements of a list
// can reference null constructs - this probably is
// wrong, but we're going with it now. Probably what
// needs to be done is to normalize the list so that
// union (a,b) (c,d) is (a,b,c,d) rather than (a,b,(c,d)).
// see original version of AstList.java - it probably
// is right given that lists are normalized...
for ( l = arg[0]; l != null; l = l.right ) {
if ( l.arg[0] == null )
continue;
l.arg[0].print( props );
l = l.right;
break;
}
for ( ; l != null; l = l.right ) {
if ( l.arg[0] == null )
continue;
l.Print_Only_Tokens( props );
l.arg[0].print( props );
}
}
public void reduce2java( AstProperties props ) {
AstNode l;
// Step 1: return if the list is empty
if ( arg[0] == null )
return;
// Step 2: print the first node differently than the rest
// Note: the following code assumes that elements of a list
// can reference null constructs - this probably is
// wrong, but we're going with it now. Probably what
// needs to be done is to normalize the list so that
// union (a,b) (c,d) is (a,b,c,d) rather than (a,b,(c,d)).
// see original version of AstList.java - it probably
// is right given that lists are normalized...
for ( l = arg[0]; l != null; l = l.right ) {
if ( l.arg[0] == null )
continue;
l.arg[0].reduce2java( props );
l = l.right;
break;
}
for ( ; l != null; l = l.right ) {
if ( l.arg[0] == null )
continue;
l.Print_Only_Tokens( props );
l.arg[0].reduce2java( props );
}
}
public void PDump( String indent ) {
int i;
AstNode l;
String id;
System.out.println( indent + indent.length() + className() );
id = indent+" ";
for ( l = arg[0]; l != null; l = l.right )
l.PDump( id );
}
public AstNode addComment( String comment ) {
return ( addComment( comment, false ) );
}
public AstNode addComment( String comment, boolean replace ) {
AstNode l;
for ( l=arg[0]; l != null; l = l.right )
if ( l.arg[0] != null )
if ( l.arg[0].addComment( comment, replace ) != null )
return ( AstNode ) this;
return ( null );
}
}