/*---------------------------------------------------------------------------
File:         			TM2.java
Package:                        JFLAP Version 1.0
Author:				Magda & Octavian Procopiuc V1.0 07/15/96
                                
Description of Contents:	Contains class TM2.
				
--------------------------------------------------------------------------*/

/* 
 * Susan H. Rodger, Magda Procopiuc, Octavian Procopiuc, Eric Gramond
 * Computer Science Department
 * Duke University
 * June 1998
 * Supported by National Science Foundation DUE-9596002 and DUE-9555084.
 *
 * Copyright (c) 1998
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the author.  The name of the author may not be used to
 * endorse or promote products derived from this software without
 * specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

package flap;

import java.util.*;

/**
 * This class simulates the behavior of a 
 * two-tape Turing Machine.
 *
 * @author	Magda & Octavian Procopiuc
 * @version	1.0 15 July 1996
 */ 
public class TM2 extends TM1 {

/**
 * Creates a 2-tape TM corresponding to its desktop image.
 */
  public TM2(Desktop d) {
    super(d);
  }


  /** Places all the states for the solved DFA solution */
    public  void placeAllStates(Machine model, Machine nfa) {
    }

    /** not implemented  */
    public String checkIfDone(Machine amodel, Machine original) {
	return "function not implemented.";
    }


/*
 * Checks whether the machine is "legal" (i.e. has initial state,
 * and all transition labels are OK)
 * Overrides TM1.checkMachine()
 */
  public String checkMachine() {
    String answer = super.checkMachine();
    String message = "At least one transition has an\n incorrect label. The correct form is\n read; write, move| read; write, move\n where read and write are one letter,\n and move is R, L or S.";
 
    if (answer != null)
      if (answer.startsWith("At"))
        answer = message;
    return answer;  
  }

/*
 * Creates a new configuration starting from configuration c, according
 * to the transition rule of a 2-tape TM 
 * Overrides TM1.expand()
 */
  boolean expand(Configuration c) {
    boolean willBeValid;
    Transition t;
    Configuration cc;

    String label1, label2;

    String read1, write1, move1;
    String read2, write2, move2;
  
    Tape newTape1 = new Tape();
    Tape newTape2 = new Tape();

    willBeValid = false;
    for (Enumeration et=c.theState.transitions.elements(); et.hasMoreElements(); )   {
      t = (Transition) et.nextElement();
      StringTokenizer stk = new StringTokenizer(t.label, "|", false);
      label1 = stk.nextToken();
      label2 = stk.nextToken();

      stk = new StringTokenizer(label1, ";,", false);
      read1 = stk.nextToken().trim();
      write1 = stk.nextToken().trim();
      move1 = stk.nextToken().trim();

      stk = new StringTokenizer(label2, ";,", false);
      read2 = stk.nextToken().trim();
      write2 = stk.nextToken().trim();
      move2 = stk.nextToken().trim();

      if ((c.theString.startsWith(read1) || ("B".equals(read1) && c.theString.length() == 0)) && (c.secondString.startsWith(read2) || ("B".equals(read2) && c.secondString.length() == 0))) {
        willBeValid = true;
        executeMove(c.theStack, c.theString, newTape1, write1, move1);
        executeMove(c.secondStack, c.secondString, newTape2, write2, move2);
        cc = new Configuration(t.to, newTape1.right, newTape1.left, newTape2.right, newTape2.left, c, this);
        if (!isAlreadyIn(temp, cc)) {
          temp.addElement(cc);
          nCurrentConfigs++;
          if (cc.isAccept()) {
            acceptInput = true;
            acceptingConfig = cc;
          }
        }
      }
    }
    return willBeValid;
  }	// end of method expand

/*
 * Creates the initial configuration.  
 * Overrides TM1.initialConfig().
 */
  Configuration initialConfig() {
    StringTokenizer stk = new StringTokenizer(input, "|", false);
    String input1 = stk.nextToken().trim();
    String input2 = stk.nextToken().trim();
    return new Configuration(d.initialState, input1, "", input2, "", null, this);
  }	// end of method initialConfig

/*
 * Checks if a transition introduces non-determinism.
 * @param t	Transition to be checked.
 *        v	Vector of transitions against which t is checked.
 * @return	true if t does not introduce any non-determinism. 
 * Overrides TM1.isDeterministic().
 */

  boolean isDeterministic(Transition t, Vector v) {
    Enumeration e;
    Transition vt;
    String read1, write1, move1;
    String read2, write2, move2;
    String vread1, vwrite1, vmove1;
    String vread2, vwrite2, vmove2;
    String label1, label2;

    if (v.size() == 0) 
      return true;

    StringTokenizer stk = new StringTokenizer(t.label, "|", false);
    label1 = stk.nextToken();
    label2 = stk.nextToken();

    stk = new StringTokenizer(label1, ";,", false);
    read1 = stk.nextToken().trim();
    write1 = stk.nextToken().trim();
    move1 = stk.nextToken().trim();

    stk = new StringTokenizer(label2, ";,", false);
    read2 = stk.nextToken().trim();
    write2 = stk.nextToken().trim();
    move2 = stk.nextToken().trim();

    for (e = v.elements(); e.hasMoreElements(); ) {
      vt = (Transition) e.nextElement();
      stk = new StringTokenizer(vt.label, "|", false);
      label1 = stk.nextToken();
      label2 = stk.nextToken();
  
      stk = new StringTokenizer(label1, ";,", false);
      vread1 = stk.nextToken().trim();
      vwrite1 = stk.nextToken().trim();
      vmove1 = stk.nextToken().trim();

      stk = new StringTokenizer(label2, ";,", false);
      vread2 = stk.nextToken().trim();
      vwrite2 = stk.nextToken().trim();
      vmove2 = stk.nextToken().trim();

      if (read1.equals(vread1) && read2.equals(vread2)) 
        if ((t.to != vt.to) || (!write1.equals(vwrite1)) || (!move1.equals(vmove1)) || (!write2.equals(vwrite2)) || (!move2.equals(vmove2)))
             return false;
    } 

    return true;
  }  // end of method isDeterministic

/*
 * Checks if a label is legal (i.e. corresponds to the standard format
 * of 2-tape TM labels).  
 * Overrides TM1.checkLabel().
 */
  boolean checkLabel(String label) {
    StringTokenizer stk = new StringTokenizer(label, "|", false);
    String label1 = stk.nextToken();
    String label2 = stk.nextToken();
    boolean answer = labelOK(label1) && labelOK(label2);
    return answer;
  }	// end of method checkLabel

} // end of class TM2










