/// <summary> /// Generate a transducer rooted in def from a transducer definition /// </summary> public bool AddTransducer(Def def, FastTransducerInstance fti, Dictionary<string, Def> defs) { #region Accessory variables int ruleNumb; int[][] givenExpr; Expr whereExpr; Expr toExpr; int currentState = 0; Def untdef; TransDef currentDef; LangDef currentLangDef; bool isTrans = true; //The alphabet of the transducer List<GuardedExp> cases = new List<GuardedExp>(); RankedAlphabet currentAlphabet = alphabet.alph; List<TreeRule> transducerRules = new List<TreeRule>(); List<string> exploredStates = new List<string>(); List<string> reachedStates = new List<string>(); RankedAlphabetSort outputAlphabet = null; int childPosition; String name = ""; String defName = ""; List<FastToken> children; int[][] nextStates; List<int>[] nextStatesL; #endregion List<Def> definitionQueue = new List<Def>(); //Find the output alphabet #region pick proper outputAlph if (def.kind == DefKind.Trans) { TransDef tdef = def as TransDef; defName = tdef.func.name.text; outputAlphabet = fti.alphabets[tdef.range.name.text]; } if (def.kind == DefKind.Lang) { LangDef ldef = def as LangDef; defName = ldef.func.name.text; outputAlphabet = fti.alphabets[ldef.domain.name.text]; } #endregion reachedStates.Add(defName); definitionQueue.Add(def); while (definitionQueue.Count > 0) { //remove state from the queue and mark it as explored untdef = definitionQueue.ElementAt<Def>(0); definitionQueue.RemoveAt(0); #region pick proper type for def if (untdef.kind == DefKind.Trans) { isTrans = true; currentDef = (TransDef)untdef; exploredStates.Add(currentDef.func.name.text); cases = currentDef.cases; } if (untdef.kind == DefKind.Lang) { isTrans = false; currentLangDef = (LangDef)untdef; exploredStates.Add(currentLangDef.func.name.text); cases = currentLangDef.cases; } #endregion ruleNumb = 0; List<int> unsatRules = new List<int>(); foreach (var defCase in cases) { ruleNumb++; children = defCase.pat.children; //Compute the Z3 term for the where condition whereExpr = GenerateZ3ExprFromWhereExpr(defCase.where, fti).Simplify(); if (z3p.IsSatisfiable(whereExpr)) { //Compute the termSet array corresponding to the given givenExpr = new int[children.Count][]; #region Find next states and add them to the queue and add the corresponding number to next states nextStates = new int[children.Count][]; nextStatesL = new List<int>[children.Count]; for (int i = 0; i < children.Count; i++) nextStatesL[i] = new List<int>(); foreach (var expr in defCase.given) { if (expr.kind == FExpKind.App) { name = ((AppExp)expr).func.name.text; //Add the state to the queue if it has not been reached yet if (!reachedStates.Contains(name)) { reachedStates.Add(name); var langDef = defs[name] as LangDef; definitionQueue.Add(langDef); } childPosition = 0; foreach (var child in children) { if (child.text == ((AppExp)expr).args[0].token.text) { break; } childPosition++; } nextStatesL[childPosition].Add(reachedStates.IndexOf(name)); } } #endregion //Compute the Z3 term for the to condition if (isTrans) toExpr = GenerateZ3ExprFromToExpr(defCase.to, outputAlphabet, children, currentState, reachedStates, definitionQueue, defs, fti, nextStatesL).Simplify(); else toExpr = null; //Next states will contain the outgoing states of the automata for (int i = 0; i < children.Count; i++) nextStates[i] = nextStatesL[i].ToArray(); transducerRules.Add(z3p.TT.MkTreeRule(currentAlphabet, outputAlphabet.alph, currentState, defCase.pat.symbol.text, whereExpr, toExpr, nextStates)); } else { unsatRules.Add(ruleNumb - 1); //Console.WriteLine("Rule " + ruleNumb + " is unsat in " + untdef.id.text); fti.fastLog.WriteLog(LogLevel.Normal, string.Format("Rule {0} in '{1}' is not satisfiable", +ruleNumb, untdef.id.text)); } } int removed = 0; foreach (int ind in unsatRules) { cases.RemoveAt(ind-removed); removed++; } currentState++; } //Generate transducer try { var automaton = z3p.TT.MkTreeAutomaton(0, currentAlphabet, outputAlphabet.alph, transducerRules); automaton = automaton.RemoveMultipleInitialStates(); if (def.kind == DefKind.Trans) { transducers.Add(defName, automaton); if (automaton.IsEmpty) fti.fastLog.WriteLog(LogLevel.Normal, string.Format("the transducer '{0}' is empty", defName)); } else { acceptors.Add(defName, automaton); if (automaton.IsEmpty) fti.fastLog.WriteLog(LogLevel.Normal, string.Format("the language '{0}' is empty", defName)); } } catch (AutomataException e) { Console.WriteLine(e); throw e; } return true; }
public void Add(Def def) { if (def is QueryDef) { //queries.Add((QueryDef)def); defs.Add(def); } else { if (defsMap.ContainsKey(def.id.text)) throw new FastParseException(def.id.Location, string.Format("ID '{0}' is defined twice", def.id.text)); defsMap[def.id.text] = def; defs.Add(def); } }