
/**
 * MString.java
 *  String as Matching pattern - subclass of StringTokeniser
 *  Can have variables - starting with ? - in either p or d 
 * Created: Sun Jan 14 17:58:24 2001
 *
 * @author 
 * @version
 */

import simplejava.*;  
import java.util.*;
import java.io.*;

public class MString extends StringTokenizer {
  private HashMap context; //the matching context
  public HashMap getContext() {return context;}

  public MString(String s){
    super(s);
  }
 
  //match against a string
  public boolean match(String d){
    StringTokenizer dtok=new StringTokenizer(d); 
    boolean result;

    if (this.countTokens() != dtok.countTokens())
      result=false;
    else {
      result=true;
      context=new HashMap();
      while (this.hasMoreTokens()&& result){
        String nextp=this.nextToken();
        String nextd=dtok.nextToken();

        if (!nextp.equals(nextd)){
          if (pvar(nextp))
            context.put(nextp,nextd);
          else {
            if (pvar(nextd))
              context.put(nextd,nextp);
            else result=false;
          }
        }
      }
    }
      
    return result;
  }

 //match given an initial context
  public boolean match(String d, HashMap con){
    //System.out.println("in here");
    context=con;
    StringTokenizer dtok=new StringTokenizer(d); 
    boolean result;
    //System.out.println(this);
    //System.out.println(this.countTokens());
    //System.out.println(dtok.countTokens());

    if (this.countTokens() != dtok.countTokens())
      result=false;
    else {
      result=true;
      while (this.hasMoreTokens()&& result){
        String nextp=this.nextToken();
        String nextd=dtok.nextToken();
        //System.out.println(nextp);
        //System.out.println(nextd);
        
        if (!nextp.equals(nextd)){ 
          if (pvar(nextp)){ //got an mvar in p
            String res=(String)context.get(nextp); //look it up in context
            if (res==null){ //no entry, so add new binding
              context.put(nextp,nextd);
            }
            else{  //does bound value match nextd?
              result=res.equals(nextd);
            }
          }
          else
            if (pvar(nextd)){ //got an mvar in d
              String res=(String)context.get(nextd); //look it up in context
              if (res==null){ //no entry, so add new binding
                context.put(nextd,nextp);
              }
              else{  //does bound value match nextd?
                result=res.equals(nextp);
              }
            }
            else  //neither is mvar
              result=false;
        }
      }
    }
    return result;
  }
 

   //is a string a wildcard?

  private boolean pvar(String v){
    return(v.startsWith("?"));
  }

  //Msubst - substitute back in patt from given context
  //creates new patt. Returns new patt

  String msubst(HashMap c){
    context=c;    
    String newpatt=new String();

    while (this.hasMoreTokens()){
      String np=this.nextToken();
      String res= (String) c.get(np);
      if (res==null) newpatt=newpatt.concat(np);
      else newpatt=newpatt.concat(res);
      if (this.hasMoreTokens()){
        newpatt=newpatt.concat(" ");
      } //no final space
    }
    return newpatt;
  }
}
  
 
 
 
