/*
 * [The "BSD license"]
 *  Copyright (c) 2010 Terence Parr
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *  3. 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 BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.antlr.codegen;

import java.util.ArrayList;
import org.antlr.analysis.*;
import org.antlr.misc.Utils;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroup;

import java.util.List;

public class ACyclicDFACodeGenerator {
	protected CodeGenerator parentGenerator;

	public ACyclicDFACodeGenerator(CodeGenerator parent) {
		this.parentGenerator = parent;
	}

	public ST genFixedLookaheadDecision(STGroup templates,
													DFA dfa)
	{
		return walkFixedDFAGeneratingStateMachine(templates, dfa, dfa.startState, 1);
	}

	protected ST walkFixedDFAGeneratingStateMachine(
			STGroup templates,
			DFA dfa,
			DFAState s,
			int k)
	{
		//System.out.println("walk "+s.stateNumber+" in dfa for decision "+dfa.decisionNumber);
		if ( s.isAcceptState() ) {
			ST dfaST = templates.getInstanceOf("dfaAcceptState");
			dfaST.add("alt", Utils.integer(s.getUniquelyPredictedAlt()));
			return dfaST;
		}

		// the default templates for generating a state and its edges
		// can be an if-then-else structure or a switch
		String dfaStateName = "dfaState";
		String dfaLoopbackStateName = "dfaLoopbackState";
		String dfaOptionalBlockStateName = "dfaOptionalBlockState";
		String dfaEdgeName = "dfaEdge";
		if ( parentGenerator.canGenerateSwitch(s) ) {
			dfaStateName = "dfaStateSwitch";
			dfaLoopbackStateName = "dfaLoopbackStateSwitch";
			dfaOptionalBlockStateName = "dfaOptionalBlockStateSwitch";
			dfaEdgeName = "dfaEdgeSwitch";
		}

		ST dfaST = templates.getInstanceOf(dfaStateName);
		if ( dfa.getNFADecisionStartState().decisionStateType==NFAState.LOOPBACK ) {
			dfaST = templates.getInstanceOf(dfaLoopbackStateName);
		}
		else if ( dfa.getNFADecisionStartState().decisionStateType==NFAState.OPTIONAL_BLOCK_START ) {
			dfaST = templates.getInstanceOf(dfaOptionalBlockStateName);
		}
		dfaST.add("k", Utils.integer(k));
		dfaST.add("stateNumber", Utils.integer(s.stateNumber));
		dfaST.add("semPredState", s.isResolvedWithPredicates());
		/*
		String description = dfa.getNFADecisionStartState().getDescription();
		description = parentGenerator.target.getTargetStringLiteralFromString(description);
		//System.out.println("DFA: "+description+" associated with AST "+dfa.getNFADecisionStartState());
		if ( description!=null ) {
			dfaST.add("description", description);
		}
		*/
		int EOTPredicts = NFA.INVALID_ALT_NUMBER;
		DFAState EOTTarget = null;
		//System.out.println("DFA state "+s.stateNumber);
		for (int i = 0; i < s.getNumberOfTransitions(); i++) {
			Transition edge = s.transition(i);
			//System.out.println("edge "+s.stateNumber+"-"+edge.label.toString()+"->"+edge.target.stateNumber);
			if ( edge.label.getAtom()==Label.EOT ) {
				// don't generate a real edge for EOT; track alt EOT predicts
				// generate that prediction in the else clause as default case
				EOTTarget = (DFAState)edge.target;
				EOTPredicts = EOTTarget.getUniquelyPredictedAlt();
				/*
				System.out.println("DFA s"+s.stateNumber+" EOT goes to s"+
								   edge.target.stateNumber+" predicates alt "+
								   EOTPredicts);
				*/
				continue;
			}
			ST edgeST = templates.getInstanceOf(dfaEdgeName);
			// If the template wants all the label values delineated, do that
			if ( edgeST.impl.formalArguments.get("labels")!=null ) {
				List<Integer> labels = edge.label.getSet().toList();
				List<String> targetLabels = new ArrayList<String>(labels.size());
				for (int j = 0; j < labels.size(); j++) {
					Integer vI = labels.get(j);
					String label =
						parentGenerator.getTokenTypeAsTargetLabel(vI);
					targetLabels.add(label); // rewrite List element to be name
				}
				edgeST.add("labels", targetLabels);
			}
			else { // else create an expression to evaluate (the general case)
				edgeST.add("labelExpr",
									parentGenerator.genLabelExpr(templates,edge,k));
			}

			// stick in any gated predicates for any edge if not already a pred
			if ( !edge.label.isSemanticPredicate() ) {
				DFAState target = (DFAState)edge.target;
				SemanticContext preds =
					target.getGatedPredicatesInNFAConfigurations();
				if ( preds!=null ) {
					//System.out.println("preds="+target.getGatedPredicatesInNFAConfigurations());
					ST predST = preds.genExpr(parentGenerator,
														  parentGenerator.getTemplates(),
														  dfa);
					edgeST.add("predicates", predST);
				}
			}

			ST targetST =
				walkFixedDFAGeneratingStateMachine(templates,
												   dfa,
												   (DFAState)edge.target,
												   k+1);
			edgeST.add("targetState", targetST);
			dfaST.add("edges", edgeST);
			/*
			System.out.println("back to DFA "+
							   dfa.decisionNumber+"."+s.stateNumber);
							   */
		}

		// HANDLE EOT EDGE
		if ( EOTPredicts!=NFA.INVALID_ALT_NUMBER ) {
			// EOT unique predicts an alt
			dfaST.add("eotPredictsAlt", Utils.integer(EOTPredicts));
		}
		else if ( EOTTarget!=null && EOTTarget.getNumberOfTransitions()>0 ) {
			// EOT state has transitions so must split on predicates.
			// Generate predicate else-if clauses and then generate
			// NoViableAlt exception as else clause.
			// Note: these predicates emanate from the EOT target state
			// rather than the current DFAState s so the error message
			// might be slightly misleading if you are looking at the
			// state number.  Predicates emanating from EOT targets are
			// hoisted up to the state that has the EOT edge.
			for (int i = 0; i < EOTTarget.getNumberOfTransitions(); i++) {
				Transition predEdge = EOTTarget.transition(i);
				ST edgeST = templates.getInstanceOf(dfaEdgeName);
				edgeST.add("labelExpr",
									parentGenerator.genSemanticPredicateExpr(templates,predEdge));
				// the target must be an accept state
				//System.out.println("EOT edge");
				ST targetST =
					walkFixedDFAGeneratingStateMachine(templates,
													   dfa,
													   (DFAState)predEdge.target,
													   k+1);
				edgeST.add("targetState", targetST);
				dfaST.add("edges", edgeST);
			}
		}
		return dfaST;
	}
}

