summaryrefslogblamecommitdiff
path: root/sources/scalac/transformer/matching/NondetWordAutom.java
blob: 513a49b115ca71e4265c64fb25c69ecb6075f964 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15














                                                           

















































































































                                                                             








































                                                                       






                                                                         










                                                                              
                                                     

































































































                                                                                        
                                                                          

































                                                                              
                                                 













                                                                                                                         
                                                               




















                                                                        
                                        
                                                                   
                                                        


















                                                                       

                                                

























































                                                                                  
                                                                     














                                                             

                                            



































                                                                     
                                               






















                                                                           
package scalac.transformer.matching ;

import scalac.ApplicationError ;
import scalac.ast.Tree ;
import scalac.util.Name ;
import Tree.* ;

import java.util.* ;

//import scala.compiler.printer.TextTreePrinter ;

/** a nondeterministic word automaton.
 *  states are represented (implicitly) as Integer objects.
 */

public class NondetWordAutom  {

    // BEGIN stuff from FiniteAutom

      //final static Integer FINTAG = new Integer(0);

      /** number of states */
      protected int nstates;

      /** the 'alphabet' */
      protected HashSet labels;

      /** the set of final states, here as a TreeMap */
      protected TreeMap finals;

      /** dfa: HashMap trans: Object -> Integer
       *  nfa: HashMap trans: Object -> Vector [ Integer ]
       *
       *  nfa: Integer  ->(Object -> Vector [ Int ])
       *       [q]     |->( a |-> { q' | (q,a,q') in \deltaright } )
       *
       *  dfa: Integer  ->(Object -> Int)
       *       [q]     |->( a |-> q' | \deltaright(q,a) = q' } )
       */

      public HashMap[] deltaq;

      public Vector[]  defaultq; // this gives the default transitions

      //protected HashMap deltaq[];

      // --- accessor methods

      /** returns number of states
       */
      public int nstates() {
            return nstates;
      }

      /** returns the labels
       */
      public HashSet labels() {
            return labels;
      }

      /** returns the transitions
       */
      public HashMap deltaq( int state ) {
            return deltaq[ state ];
      }

      /** returns the transitions
       */
      public HashMap deltaq( Integer state ) {
            return deltaq[ state.intValue() ];
      }


      /** returns the transitions
       */
      public Vector defaultq( int state ) {
            return defaultq[ state ];
      }

      /** returns the transitions
       */
      public Vector defaultq( Integer state ) {
            return defaultq[ state.intValue() ];
      }


      /** returns true if the state is final
       */
      public boolean isFinal( int state ) {
            return ((finals != null)
                    && (finals.get( new Integer( state )) != null));
      }

      /** returns true if the state is final
       */
      public boolean isFinal( Integer state ) {
            return ((finals != null) && finals.containsKey( state ));
      }

      /** returns true if the state is final
       */
      public Integer finalTag( Integer state ) {
            return (Integer) finals.get( state );
      }


      public Integer finalTag( int state ) {
            return (Integer) finals.get( new Integer (state ));
      }

      /** returns true if the set of states contains at least one final state
       */
      boolean containsFinal( TreeSet Q ) {
            for( Iterator it = Q.iterator(); it.hasNext(); ) {
                  if( isFinal( (Integer) it.next()))
                        return true;
            }
            return false;
      }


      /** returns true if there are no finite states
       */
      public boolean isEmpty() {
            return finals.isEmpty();
      }

    // END stuff from FiniteAutom


      // inherited from FiniteAutom

      // set of *distinct* objects that may label transitions
      // see Object.hashCode() to see why this works

      //HashSet labels;
      //TreeMap finals;

      TreeSet initials; // ? need this ?
      // ---

      // Object deltaq -->
      // HashMap deltaq[]; // this gives the transitions of q;

      boolean leftTrans;
      boolean rightTrans;

      /** if true, this automaton behaves as a special left transducer.
       *  if a run succeeds, the result is not "true" but the entire
       *  run of the automaton as a sequence of (label,state) - pairs.
       *  used for binding variables.
       */
      public boolean producesRun() {
            return leftTrans;
      }

      public boolean consumesRun() {
            return rightTrans;
      }

      public boolean initial( Integer i ) {
            return initials.contains( i );
      }
      public Vector qbinders[];

      /** returns all states accessible from Qsrc via label.
       *  used by class DetWordAutomaton.
       */
      TreeSet getSide ( TreeSet Qsrc, Object label ) {
            TreeSet Qdest = new TreeSet();
            for( Iterator it = Qsrc.iterator(); it.hasNext(); ) {// state
                  int q = ((Integer) it.next()).intValue();
                  Vector ps = (Vector) deltaq[ q ].get( label );
                  if( ps!=null ) {
		      Qdest.addAll( ps );
                  }
                  Qdest.addAll( defaultq( q ) );
            }
            return Qdest;
      }

      /** returns the transitions
       */
      public Object defaultq( Set P1 ) {
            TreeSet defTarget = new TreeSet();
            for( Iterator p1 = P1.iterator(); p1.hasNext(); ) {
                  int q1 = ((Integer) p1.next()).intValue();
                  //System.out.println("   q1:"+q1+ " defa: "+defaultq( q1 ));
                  defTarget.addAll( defaultq( q1 ) );
            }
            return defTarget;
      }


      /** first match policy: among several final states, the smallest one is
       *   chosen. used by class DetWordAutomaton
       */
      Integer finalTag( Set Q ) {

            int min = Integer.MAX_VALUE ;

            for( Iterator it = Q.iterator(); it.hasNext(); ) {
                  Integer state = (Integer) it.next();
                  Integer tag = (Integer) finals.get( state );
                  if( tag != null ) {
                        if( tag.intValue() < min )
                              min = tag.intValue();
                  }
            }

            if ( min == Integer.MAX_VALUE )
                  throw new ApplicationError( "there should be a final state ");

            return new Integer( min );
      }

      /*
      protected void tmap(int offs, TreeMap t) {
            TreeMap nt = new TreeMap();
            for(Iterator it = t.keySet().iterator(); it.hasNext(); ) {
                  Integer key = (Integer) it.next();
                  Integer newkey = new Integer( key.intValue() + offs );
                  Integer val = (Integer) t.get( key );
                  Integer newval = new Integer( val.intValue() + offs );

                  nt.put( newkey, newval );
            }
            return nt;
      }
*/
      // hashmaps, treemaps
      protected Map mapmap(Map src,
                             int offset,
                             Map dest,
                             boolean mapkeys,
                             boolean mapvals) {
            for(Iterator it = src.keySet().iterator(); it.hasNext(); ) {
                  Object key = it.next();
                  Object val = src.get( key );
                  if( mapkeys ) key = new Integer( ((Integer)key).intValue()
                                                   + offset );
                  if( mapvals ) val = vmap( offset, (Vector) val ) ;
                                      /* new Integer( ((Integer)val).intValue()
                                                   + offset );
                                      */
                  dest.put( key, val );
            }
            return dest;
      }

      protected static Vector vmap(int offs, Vector v ) {
            if( v == null )
                  return null;
            Vector res = new Vector( v.size() );

            for(Iterator it = v.iterator(); it.hasNext(); ) {
                  Integer item = (Integer) it.next();
                  res.add( new Integer( item.intValue() + offs ));
            }
            return res;

      }

      /*
      protected void relocate_defaultq( int offs, Vector   _defaultq[] ) {
            for( int i = 0; i < this.nstates; i++ ) {
                  _defaultq[ i + offset ] = vmap( offset, ((Vector[])defaultq)[ i ]);
            }
      }
      */

      /** copies the values in the fields of this object into the
       *  arguments, possibly adding an offset.
       */
      protected void relocate( int      offset,
                               TreeMap  _finals,
                               HashMap  _deltaq[],
                               Vector   _defaultq[],
                               Vector   _qbinders[] ) {

            mapmap( finals, offset, _finals, true, false);

            for( int i = 0; i < this.nstates; i++ ) {

                  _deltaq  [ i + offset ] = (HashMap) mapmap( ((HashMap[])deltaq)[ i ],
                                                    offset, new HashMap(), false, true);

                  _defaultq[ i + offset ] = vmap( offset, defaultq[ i ] );

            }
            if ((_qbinders != null) &&( qbinders != null ))
                  for( int i = 0; i < this.nstates; i++ ) {
                        //System.out.println("hallo"+qbinders);
                        //System.out.println("qbinders[ i ] :"+qbinders[ i ]);
                        assert _qbinders != null;
                        //System.out.println("_qbinders :"+_qbinders);

                        _qbinders[ i + offset ] = qbinders[ i ];
                  }
      }

      /** if there is more than one initial state, a new initial state
       *  is created, with index 0
       */
      protected void normalize( TreeSet initials, boolean reloc ) {
            //if( initials.size() == 1 )
            //      return;

            HashMap idelta   = new HashMap();
            TreeSet idefault = new TreeSet();

            Integer q0 = new Integer( 0 );

            for( Iterator it = initials.iterator(); it.hasNext(); ) {

                  Integer ostate = (Integer) it.next();

                  Integer finTag = (Integer) finals.get( ostate ) ;
                  if(( finTag != null ) && ( finals.get( q0 )  == null))
                        finals.put( q0, finTag );


                  HashMap tmp = deltaq( ostate );

                  if( reloc )
                        tmp = (HashMap) mapmap( tmp, 1, new HashMap(), false, true );

                  for( Iterator labs = tmp.keySet().iterator(); labs.hasNext(); ) {
                        Label  lab    = (Label) labs.next();
                        Vector itarget = (Vector) idelta.get( lab );
                        if( itarget == null )
                              idelta.put( lab, itarget = new Vector());
                        Vector otarget = (Vector) tmp.get( lab );
                        itarget.addAll( otarget );
                  }
                  //System.out.println( "normalize:defaultq[ "+ostate+" ] "+((Vector[]) defaultq) [ ostate.intValue() ]);
                  if( defaultq( ostate ) != null )
                        idefault.addAll( defaultq( ostate )  );
            }

            if( reloc ) {
                  int m = 1 + this.nstates;
                  TreeMap _finals     = new TreeMap();
                  HashMap _deltaq[]   = new HashMap[ m ];
                  Vector  _defaultq[] = new Vector[ m ];
                  Vector  _qbinders[] = null;

                  if( qbinders != null )
                        _qbinders = new Vector[ m ];

                  relocate( 1, _finals, _deltaq, _defaultq, _qbinders );

                  this.nstates  = m;
                  this.finals   = _finals;
                  this.deltaq   = _deltaq;
                  this.defaultq = _defaultq;
                  this.qbinders = _qbinders;
            }

            this.deltaq  [ 0 ] = idelta;
            //System.out.println("normalize:deltaq[ 0 ]"+ idelta );
            this.defaultq[ 0 ] = new Vector( idefault );

            //System.out.println("normalize:defaultq[ 0 ]"+ idefault );

            this.initials = new TreeSet();
            this.initials.add( q0 );
      }


      /** needed for NondetWordSwitch
       */
      NondetWordAutom() {}

      /** called from Berry-Sethi construction.
       */

      public NondetWordAutom(int nstates,
                             HashSet labels,
                             TreeSet initials,
                             TreeMap finals,
                             HashMap[] deltaq,
                             Vector[]  defaultq,
                             Object qbinders) {
            this.nstates = nstates;
            this.labels = labels;
            this.initials = initials;
            this.finals = finals;
            this.deltaq = deltaq;
            this.defaultq = defaultq;
            this.qbinders = (Vector[])qbinders;
            //print();
            //System.exit(0);
      }



      int offset[]; // only used if constructed from multiple

      protected void collectLabels( NondetWordAutom nfa[] ) {
            this.labels = new HashSet();
            for( int i = 0; i < nfa.length; i++ ) {
                  this.labels.addAll( nfa[ i ].labels );
            }
      }

      protected void collectOffsets( NondetWordAutom nfa[] ) {
            this.offset = new int[ nfa.length + 1 ];
            offset[ 0 ] = 1; // we have a new initial state
            for( int i = 0; i < nfa.length ; i++ )
                  offset[ i + 1 ] = nfa[ i ].nstates + offset[ i ];

      }

      /** collapses several normalized NondetWordAutom objects into one.
       */

      public NondetWordAutom( NondetWordAutom nfa[] ) {


            //this.m
            int m = nfa.length;
            //System.out.println("enter NondetWordSwitch, "
            //                   +"combining " + m + " automata");

            collectLabels( nfa );
            collectOffsets( nfa );

            this.nstates = offset[ nfa.length ]; //m - 1 ] + nfa[ m - 1 ].nstates;


            this.finals = new TreeMap();

            this.qbinders = new Vector[ nstates ];

            // new initial state gets all transitions from all initial states

            this.deltaq        = new HashMap[ nstates ];
            this.defaultq      = new Vector [ nstates ];

            //TreeSet defaultqSet = new TreeSet();
            deltaq[ 0 ] = new HashMap(); // 0 = our new initial state

            TreeSet initials = new TreeSet();


            for( int i = 0; i < m; i++ ) {
                  //System.out.println("i (current NFA):"+i);

                  NondetWordAutom n = nfa[ i ];

                  int offs = offset[ i ];

                  initials.add( new Integer( offs ));

                  n.relocate( offs,
                              this.finals,
                              this.deltaq,
                              this.defaultq,
                              (Vector[])  this.qbinders );
            }

            normalize( initials, false );

      }




      public void print() {

            System.out.print("NFA on labels "+ this.labels);

            if( offset != null ) {
                  System.out.print("offset");
                  for( int k = 0; k < offset.length; k++ ) {
                        if( k > 0)
                              System.out.print(", ");
                        System.out.print(offset[k]);
                  }
            }
            System.out.println();

            System.out.print("max state number :" + (nstates - 1)  );

            System.out.println("initials" + initials);

            System.out.println("finals" + finals);

            for( int i = 0; i < nstates; i++ ) {
                  System.out.print("state: " + i);
                  if( finals.containsKey( new Integer( i )) ){
                        System.out.print("*"); //final
                  }
                  System.out.print("  transitions: {");
                  HashMap arrows = deltaq[ i ];

                  for( Iterator it = arrows.keySet().iterator();
                       it.hasNext(); ) {
                        Object label = it.next();
                        Vector targets = (Vector) arrows.get( label );
                        for( Iterator jt = targets.iterator();
                             jt.hasNext(); ) {
                              Integer p = (Integer) jt.next();
                              System.out.print("("+label+","+p+")");
                        }
                  }

                  System.out.print("} ");
                  System.out.print(" default transitions: "+defaultq( i ));
                  if( qbinders != null )
                        System.out.println(" binders "+qbinders[ i ]);
                  System.out.println();

            }

      }

}