/*---------------------------------------------------------------------------
File:         			CFGtoPDALR.java
Package:                        JFLAP Version 3.0
Author:			        Eric Gramond 
                                
Description of Contents:	Contains class CFGtoPDALR.
				
--------------------------------------------------------------------------*/

/* 
 * 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.*;
import java.awt.*;
import java.io.*;
import java.awt.image.*;
import java.awt.event.*;



/**
 * converts a CFG into a PDA (Lr mode)
 */

public class CFGtoPDALR {

    
    /**
     * just check if there are any Z's. its a CFG :)
     */
    public static void checkGrammar(Grammar g) throws BadInputException{

	Enumeration e, e2;
	Rule ru;
	boolean foundZ = false;
	GrammarRightHandToken gt;
	String error = "\nVariables cannot be called Z.\nZ is already used as empty stack symbol \n in the PDA.";
	
	for(e = g.getRules().elements(); e.hasMoreElements(); ) {
	    ru = (Rule) e.nextElement();
	    if( ru.getLeftHand().getContents().equals("Z")) 
		throw new BadInputException(error);
	    
	    for(e2 = ru.getRightHand().elements(); e2.hasMoreElements(); ) {
		gt = (GrammarRightHandToken) e2.nextElement();
		if(gt.getContents().equals("Z")) 
		    throw new BadInputException(error);
	    }
	}

    }


/**
 * does the 3 start states.
 */

    public static void CFGtoStartPDA(Grammar cfg, Desktop d) {

	Dimension dim = d.getSize();
	State left, right, center;
	Transition trans;

	left = d.addState(dim.width/6, (5*dim.height)/6);
	center = d.addState(dim.width/2, (5*dim.height)/6);
	right = d.addState( (5*dim.width)/6, (5*dim.height)/6);
	right.isFinal =true; 

	trans = d.addTransition(left, center);
	trans.label = " , " + cfg.getStart().getContents() + "; ";

	trans = d.addTransition(center, right);
	trans.label = " , Z; ";

	d.initialState = left;
	d.modified = true;
	
	for(Enumeration e = d.theTransitions.elements(); e.hasMoreElements(); ) 
	    ((Transition) e.nextElement()).tokenizeLabel();
	
	
    }


/**
 * constructs the entire PDA 
 */

    public static void CFGtoPDA(Grammar cfg, Desktop d) {

	CFGtoStartPDA(cfg, d);
	State left, right, center;
	int i = 1;
        Enumeration e, e2;

	left = (State) d.theStates.elementAt(0);
	center = (State) d.theStates.elementAt(1);
	right = (State) d.theStates.elementAt(2);
	
	left.loopSize = Params._t_distance;
        Vector vterm = cfg.findAllTerminals();
        

	Terminal term;
	Transition trans;

	for(e = vterm.elements(); e.hasMoreElements(); ) {
          term = (Terminal) e.nextElement();
          trans = d.addTransition(left, left);
          trans.label = " " +term.getContents()+", ; " + 
            term.getContents();
          left.loopSize += 2* Params._t_distance / 3;
          trans.distance = i++;
	}
        
	Rule ru;
	String transString;
        int j;
	for(e = cfg.getRules().elements(); e.hasMoreElements(); ) {
	    ru = (Rule) e.nextElement();
	    transString = " , ";
	    for(j = ru.getRightHand().size() -1; j >= 0; j--) 
              transString += ((GrammarRightHandToken) ru.getRightHand().elementAt(j)).getContents();
            transString += "; " + ru.getLeftHand().getContents();
	    trans = d.addTransition(left, left);
	    trans.label = transString;
	    left.loopSize += 2* Params._t_distance  / 3;
	    trans.distance = i++;
	}
	
	for(e = d.theTransitions.elements(); e.hasMoreElements(); ) {
	    trans = (Transition) e.nextElement();
	    trans.tokenizeLabel();
	    if(trans.distance >= 1)
		trans.distance /= i-1;
	}
    }
}
