STb <FuncDecl, Expr, Sort> GenerateEncoder() { var ctx = _automataCtx.Z3; Expr inputVar = _automataCtx.MkVar(0, ctx.MkBitVecSort(8)); Expr registerVar = _automataCtx.MkVar(1, _automataCtx.MkTupleSort()); Sort outputSort = ctx.BoolSort; var stb = new STb <FuncDecl, Expr, Sort>(_automataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort, _automataCtx.MkTuple(), 0); var leafPatterns = new Dictionary <byte, bool[]>(); FindLeafPatterns(leafPatterns, _tree, new Stack <bool>()); var patterns = new bool[256][]; foreach (var entry in leafPatterns) { patterns[entry.Key] = entry.Value; } Debug.Assert(patterns.Select((x, i) => patterns.Select((y, j) => i == j || x.Length != y.Length || x.Zip(y, (a, b) => Tuple.Create(a, b)).Any(z => z.Item1 != z.Item2)).All(z => z)).All(z => z)); Debug.Assert(patterns.All(x => x != null), "Internal Huffman tree is missing leaves"); stb.AssignRule(0, GetBinarySearchRule(ctx, (BitVecExpr)inputVar, registerVar, patterns, 0, patterns.Length)); stb.AssignFinalRule(0, new BaseRule <Expr>(Sequence <Expr> .Empty, registerVar, 0)); stb = stb.Compose(GenerateToBytes()); stb = stb.ExploreBools(); if (ShowGraphStages.Count > 0) { stb.ToST().ShowGraph(); } return(stb); }
STb <FuncDecl, Expr, Sort> Generate() { var name = DeclarationType.ContainingNamespace.Name + "." + (DeclarationType.ContainingType == null ? "" : DeclarationType.ContainingType.Name + ".") + DeclarationType.Name; Console.WriteLine("Regex " + name); var builder = new STbFromRegexBuilder <FuncDecl, Expr, Sort>(_automataCtx); var stb = builder.Mk(_regex, "value", _type); if ((stb.OutputSort is TupleSort || _automataCtx.IsTupleSort(stb.OutputSort)) && _automataCtx.GetTupleConstructor(stb.OutputSort).Arity == 1) { var fieldDecl = _automataCtx.GetTupleField(stb.OutputSort, 0); var reg = _automataCtx.MkTuple(); var projector = new STb <FuncDecl, Expr, Sort>(_automataCtx, "Project", stb.OutputSort, fieldDecl.Range, reg.Sort, reg, 0); projector.AssignRule(0, new BaseRule <Expr>(new Sequence <Expr>(fieldDecl.Apply(projector.InputVar)), reg, 0)); projector.AssignFinalRule(0, new BaseRule <Expr>(Sequence <Expr> .Empty, reg, 0)); stb = stb.Compose(projector).Flatten(); } if (ShowGraphStages.Count > 0) { stb.ToST().ShowGraph(); } return(stb); }
STb <FuncDecl, Expr, Sort> GenerateDecoder() { var ctx = _automataCtx.Z3; Expr inputVar = _automataCtx.MkVar(0, ctx.BoolSort); Expr registerVar = _automataCtx.MkVar(1, _automataCtx.MkTupleSort()); Sort outputSort = ctx.MkBitVecSort(8); var stb = new STb <FuncDecl, Expr, Sort>(_automataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort, _automataCtx.MkTuple(), 0); int nextState = 0; var states = new Dictionary <HuffmanDecision, int>(); PreOrder(_tree, node => { var decision = node as HuffmanDecision; if (decision != null) { states.Add(decision, nextState++); } }); Func <HuffmanNode, BaseRule <Expr> > getBaseRule = node => { var decision = node as HuffmanDecision; if (decision != null) { return(new BaseRule <Expr>(Sequence <Expr> .Empty, registerVar, states[decision])); } else { var leaf = (HuffmanLeaf)node; return(new BaseRule <Expr>(new Sequence <Expr>(ctx.MkBV(leaf.Symbol, 8)), registerVar, 0)); } }; PreOrder(_tree, node => { var decision = node as HuffmanDecision; if (decision != null) { stb.AssignRule(states[decision], new IteRule <Expr>(inputVar, getBaseRule(decision.Left), getBaseRule(decision.Right))); stb.AssignFinalRule(states[decision], new BaseRule <Expr>(Sequence <Expr> .Empty, registerVar, states[decision])); } }); if (ShowGraphStages.Count > 0) { stb.ToST().ShowGraph(); } return(stb); }
// Flatten the register structure public static STb <FuncDecl, Expr, Sort> Flatten(this STb <FuncDecl, Expr, Sort> stb) { var boolDummy = new STb <FuncDecl, Expr, Sort>(stb.Solver, "BoolDummy", stb.OutputSort, stb.OutputSort, stb.Solver.BoolSort, stb.Solver.True, 0); boolDummy.AssignRule(0, new BaseRule <Expr>(new Sequence <Expr>(boolDummy.InputVar), boolDummy.RegVar, 0)); boolDummy.AssignFinalRule(0, new BaseRule <Expr>(Sequence <Expr> .Empty, boolDummy.RegVar, 0)); var composed = stb.Compose(boolDummy); // Compose with the "dummy" to ensure there is something to eliminate composed.Name = stb.Name; var explored = composed.ExploreBools(); // Explore bools will flatten when there is something to eliminate return(explored); // TODO: implement in a less round about way }
STb <FuncDecl, Expr, Sort> GenerateToBooleans() { var ctx = _automataCtx.Z3; Expr inputVar = _automataCtx.MkVar(0, ctx.MkBitVecSort(8)); Expr registerVar = _automataCtx.MkVar(1, _automataCtx.MkTupleSort()); Sort outputSort = ctx.BoolSort; var stb = new STb <FuncDecl, Expr, Sort>(_automataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort, _automataCtx.MkTuple(), 0); var bitExprs = new Expr[8]; for (uint i = 0; i < bitExprs.Length; ++i) { bitExprs[i] = ctx.MkEq(ctx.MkExtract(i, i, (BitVecExpr)inputVar), ctx.MkBV(1, 1)); } stb.AssignRule(0, new BaseRule <Expr>(new Sequence <Expr>(bitExprs), registerVar, 0)); stb.AssignFinalRule(0, new BaseRule <Expr>(Sequence <Expr> .Empty, registerVar, 0)); return(stb); }
STb <FuncDecl, Expr, Sort> GenerateToBytes() { var ctx = _automataCtx.Z3; Expr inputVar = _automataCtx.MkVar(0, ctx.BoolSort); Expr registerVar = _automataCtx.MkVar(1, _automataCtx.MkTupleSort(ctx.MkBitVecSort(8), ctx.MkBitVecSort(32))); Sort outputSort = ctx.MkBitVecSort(8); Expr initialRegister = _automataCtx.MkTuple(ctx.MkBV(0, 8), ctx.MkBV(0, 32)); var stb = new STb <FuncDecl, Expr, Sort>(_automataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort, initialRegister, 0); BitVecExpr symbolProj = (BitVecExpr)_automataCtx.MkProj(0, registerVar); BitVecExpr counterProj = (BitVecExpr)_automataCtx.MkProj(1, registerVar); var withFalse = ctx.MkBVLSHR(symbolProj, ctx.MkBV(1, 8)); var withTrue = ctx.MkBVOR(withFalse, ctx.MkBV(0x80, 8)); var counterIncremented = ctx.MkBVAdd(counterProj, ctx.MkBV(1, 32)); var accumulateTrue = new BaseRule <Expr>(Sequence <Expr> .Empty, _automataCtx.MkTuple(withTrue, counterIncremented), 0); var accumulateFalse = new BaseRule <Expr>(Sequence <Expr> .Empty, _automataCtx.MkTuple(withFalse, counterIncremented), 0); var accumulate = new IteRule <Expr>(inputVar, accumulateTrue, accumulateFalse); var yieldTrueAndReset = new BaseRule <Expr>(new Sequence <Expr>(withTrue), initialRegister, 0); var yieldFalseAndReset = new BaseRule <Expr>(new Sequence <Expr>(withFalse), initialRegister, 0); var yieldAndReset = new IteRule <Expr>(inputVar, yieldTrueAndReset, yieldFalseAndReset); var move = new IteRule <Expr>(ctx.MkBVULT(counterProj, ctx.MkBV(7, 32)), accumulate, yieldAndReset); stb.AssignRule(0, move); STbRule <Expr> final = new BaseRule <Expr>(Sequence <Expr> .Empty, registerVar, 0); for (int i = 1; i <= 7; ++i) { var yieldRule = new BaseRule <Expr>(new Sequence <Expr>(ctx.MkBVLSHR(symbolProj, ctx.MkBV(8 - i, 8))), registerVar, 0); final = new IteRule <Expr>(ctx.MkEq(counterProj, ctx.MkBV(i, 32)), yieldRule, final); } stb.AssignFinalRule(0, final); return(stb); }
STb <F, T, S> Automaton2STb(Automaton <Pair <BDD, T> > aut, string name, S regSort, T initReg, bool isLoop) { if (isLoop) { if (aut.HasMoreThanOneFinalState || aut.GetMovesCountFrom(aut.FinalState) > 0) { throw new AutomataException(AutomataExceptionKind.FinalStateMustBeSink); } } var stb = new STb <F, T, S>(solver, name, solver.CharSort, regSort, regSort, initReg, aut.InitialState); Func <int, int> getState = (p) => { if (isLoop && aut.IsFinalState(p)) { return(aut.InitialState); } else { return(p); } }; Func <int, Sequence <T> > getYield = (p) => { if (isLoop && aut.IsFinalState(p)) { return(Sequence <T> .Empty.Append(solver.MkVar(1, regSort))); } else { return(Sequence <T> .Empty); } }; Func <int, T, T> getUpdate = (p, u) => { if (isLoop && aut.IsFinalState(p)) { return(initReg); } else { return(u); } }; if (isLoop) { foreach (var q in aut.States) { if (!aut.IsFinalState(q)) { stb.AssignRule(q, MkSTbRule(aut.GetMovesFrom(q), getState, getYield, getUpdate)); } } stb.AssignFinalRule(aut.InitialState, new BaseRule <T>(Sequence <T> .Empty, solver.UnitConst, aut.InitialState)); } else { foreach (var q in aut.States) { stb.AssignRule(q, MkSTbRule(aut.GetMovesFrom(q), getState, getYield, getUpdate)); } foreach (var f in aut.GetFinalStates()) { stb.AssignFinalRule(f, new BaseRule <T>(Sequence <T> .Empty.Append(solver.MkVar(1, regSort)), solver.UnitConst, f)); } } return(stb); }
public STb <F, T, S> Mk(string regex, params Tuple <string, STb <F, T, S> >[] args) { var K = args.Length; bool isLoop; var patternAutomataPairs = solver.CharSetProvider.ConvertCaptures(regex, out isLoop); var captureAutomata = new Dictionary <string, Automaton <BDD> >(); var stbs = new Dictionary <string, STb <F, T, S> >(); foreach (var arg in args) { if (stbs.ContainsKey(arg.Item1) || string.IsNullOrEmpty(arg.Item1)) { throw new AutomataException(AutomataExceptionKind.InvalidArguments); } stbs[arg.Item1] = arg.Item2; } foreach (var pair in patternAutomataPairs) { if (pair.Item1 != "") { captureAutomata[pair.Item1] = pair.Item2; } } var captureSortPos = new Dictionary <string, int>(); var captureSortName = new Dictionary <string, string>(); for (int i = 0; i < args.Length; i += 1) { captureSortName[args[i].Item1] = args[i].Item2.OutputSort.ToString(); captureSortPos[args[i].Item1] = i; } if (Array.Exists(patternAutomataPairs, pair => (pair.Item1 != "" && !captureSortName.ContainsKey(pair.Item1)))) { throw new AutomataException(AutomataExceptionKind.InvalidArguments); } S[] argSorts = new S[K]; for (int i = 0; i < K; i++) { if (!captureAutomata.ContainsKey(args[i].Item1)) { throw new AutomataException(AutomataExceptionKind.InvalidArguments); } if (!args[i].Item2.OutputSort.Equals(args[i].Item2.RegisterSort)) { throw new AutomataException(AutomataExceptionKind.InvalidArguments); } argSorts[i] = args[i].Item2.OutputSort; } var regSort = solver.MkTupleSort(argSorts); var regVar = solver.MkVar(1, regSort); var initReg = solver.MainSolver.FindOneMember(solver.MkEq(regVar, regVar)).Value; var inpVar = solver.MkVar(0, solver.CharSort); var stb = new STb <F, T, S>(solver, "stb", solver.CharSort, regSort, regSort, initReg, 0); var nextStateId = 0; var stateIdMap = new Dictionary <Tuple <int, int, int>, int>(); Func <int, int, int, int> MkState = (n, q1, q2) => { int p; var nq = new Tuple <int, int, int>(n, q1, q2); if (stateIdMap.TryGetValue(nq, out p)) { return(p); } else { p = nextStateId; nextStateId += 1; stateIdMap[nq] = p; return(p); } }; var resSTB = new STb <F, T, S>(solver, "STB", solver.CharSort, solver.CharSort, solver.UnitSort, solver.UnitConst, 0); resSTB.AssignRule(0, new BaseRule <T>(new Sequence <T>(solver.MkCharVar(0)), solver.UnitConst, 0)); resSTB.AssignFinalRule(0, new BaseRule <T>(Sequence <T> .Empty, solver.UnitConst, 0)); for (int i = 0; i < patternAutomataPairs.Length; i++) { var aut = patternAutomataPairs[i].Item2; if (patternAutomataPairs[i].Item1 == "") { var autSTMoves = new List <Move <Rule <T> > >(); foreach (var move in aut.GetMoves()) { //move cannot be epsilon here var cond = solver.ConvertFromCharSet(move.Label); autSTMoves.Add(Move <Rule <T> > .Create(move.SourceState, move.TargetState, Rule <T> .Mk(cond, solver.UnitConst))); } foreach (var f in aut.GetFinalStates()) { //collect guards of all moves exitingfrom f var allGuardsFromF = solver.CharSetProvider.False; foreach (var fmove in aut.GetMovesFrom(f)) { allGuardsFromF = solver.CharSetProvider.MkOr(allGuardsFromF, fmove.Label); } var elseFromF = solver.ConvertFromCharSet(solver.CharSetProvider.MkNot(allGuardsFromF)); autSTMoves.Add(Move <Rule <T> > .Create(f, f, Rule <T> .Mk(elseFromF, solver.UnitConst, solver.MkCharVar(0)))); autSTMoves.Add(Move <Rule <T> > .Create(f, f, Rule <T> .MkFinal(solver.True))); } var autST = ST <F, T, S> .Create(solver, patternAutomataPairs[i].Item1, solver.UnitConst, solver.CharSort, solver.CharSort, solver.UnitSort, aut.InitialState, autSTMoves); var autSTb = autST.ToSTb(); resSTB = resSTB.Compose(autSTb); } else { var stb1 = stbs[patternAutomataPairs[i].Item1]; if (!stb1.InputSort.Equals(solver.CharSort)) { throw new AutomataException(AutomataExceptionKind.InvalidArguments); } var autSTMoves = new List <Move <Rule <T> > >(); foreach (var move in aut.GetMoves()) { //move cannot be epsilon here var cond = solver.ConvertFromCharSet(move.Label); autSTMoves.Add(Move <Rule <T> > .Create(move.SourceState, move.TargetState, Rule <T> .Mk(cond, solver.UnitConst, inpVar))); } foreach (var f in aut.GetFinalStates()) { autSTMoves.Add(Move <Rule <T> > .Create(f, f, Rule <T> .MkFinal(solver.True))); } var autST = ST <F, T, S> .Create(solver, patternAutomataPairs[i].Item1, solver.UnitConst, solver.CharSort, solver.CharSort, solver.UnitSort, aut.InitialState, autSTMoves); var autSTb = autST.ToSTb(); var stb2 = autSTb.Compose(stb1); foreach (var f in stb.States) { var frule = stb.GetFinalRuleFrom(f); if (frule.IsNotUndef) { //var frule1 = } } } } throw new NotImplementedException(); }
public STb <FUNC, TERM, SORT> Minimize() { var s = stb.Solver; var alphaSort = s.MkOptionSort(stb.InputSort); var autoSort = s.MkTupleSort(alphaSort, stb.OutputListSort, stb.RegisterSort, stb.RegisterSort); var autoVar = s.MkVar(3, autoSort); var autoInput = s.MkProj(0, autoVar); var autoSomeInput = s.MkGetSomeValue(autoInput); var autoOutputList = s.MkProj(1, autoVar); var autoOldReg = s.MkProj(2, autoVar); var autoNewReg = s.MkProj(3, autoVar); Func <TERM, TERM> finalSubstitute = (t) => s.ApplySubstitution(t, stb.RegVar, autoOldReg); Func <TERM, TERM> nonFinalSubstitute = (t) => finalSubstitute(s.ApplySubstitution(t, stb.InputVar, autoSomeInput)); int acceptingState = stb.States.Max() + 1; int errorState = stb.States.Max() + 2; var moves = new List <Move <TERM> >(); foreach (var state in stb.States) { var nonFinalConds = new List <TERM>(); foreach (var nonFinal in st.GetNonFinalMovesFrom(state)) { var rule = nonFinal.Label; var conds = new List <TERM>(); conds.Add(s.MkIsSome(autoInput)); conds.Add(nonFinalSubstitute(rule.Guard)); var outputList = autoOutputList; foreach (var yield in rule.Output) { conds.Add(s.MkIsCons(outputList)); conds.Add(s.MkEq(s.MkFirstOfList(outputList), nonFinalSubstitute(yield))); outputList = s.MkRestOfList(outputList); } conds.Add(s.MkIsNil(outputList)); conds.Add(s.MkEq(autoNewReg, nonFinalSubstitute(rule.Update))); var cond = s.MkAnd(conds); moves.Add(Move <TERM> .Create(state, nonFinal.TargetState, cond)); nonFinalConds.Add(cond); } var finalConds = new List <TERM>(); foreach (var rule in st.GetFinalRules(state)) { var conds = new List <TERM>(); conds.Add(s.MkIsNone(autoInput)); conds.Add(finalSubstitute(rule.Guard)); var outputList = autoOutputList; foreach (var yield in rule.Output) { conds.Add(s.MkIsCons(outputList)); conds.Add(s.MkEq(s.MkFirstOfList(outputList), finalSubstitute(yield))); outputList = s.MkRestOfList(outputList); } conds.Add(s.MkIsNil(outputList)); var cond = s.MkAnd(conds); moves.Add(Move <TERM> .Create(state, acceptingState, cond)); finalConds.Add(cond); } } //moves.Add(Move<TERM>.Create(errorState, errorState, s.True)); var auto = Automaton <TERM> .Create(stb.Solver, stb.InitialState, new int[] { acceptingState }, moves); auto.CheckDeterminism(stb.Solver); var blocks = auto.BookkeepingMinimize(stb.Solver); Func <STbRule <TERM>, STbRule <TERM> > redirect = null; redirect = r => { switch (r.RuleKind) { case STbRuleKind.Undef: return(r); case STbRuleKind.Base: return(new BaseRule <TERM>(r.Yields, r.Register, blocks[r.State].GetRepresentative())); case STbRuleKind.Ite: var t = redirect(r.TrueCase); var f = redirect(r.FalseCase); return(new IteRule <TERM>(r.Condition, t, f)); default: throw new NotImplementedException(); } }; var minimized = new STb <FUNC, TERM, SORT>(stb.Solver, stb.Name + "_min", stb.InputSort, stb.OutputSort, stb.RegisterSort, stb.InitialRegister, blocks[stb.InitialState].GetRepresentative()); var representatives = new HashSet <int>(); foreach (var state in stb.States) { representatives.Add(blocks[state].GetRepresentative()); } foreach (var state in representatives) { minimized.AssignRule(state, redirect(stb.GetRuleFrom(state)).CollapseRedundantITEs(s)); minimized.AssignFinalRule(state, redirect(stb.GetFinalRuleFrom(state)).CollapseRedundantITEs(s)); } return(minimized); }
public STb <FUNC, TERM, SORT> Compose() { var stack = new SimpleStack <Tuple <int, int> >(); int stateId = 1; var stateIdMap = new Dictionary <Tuple <int, int>, int>(); var revStateIdMap = new Dictionary <int, Tuple <int, int> >(); var q0A_x_q0B = new Tuple <int, int>(A.InitialState, B.InitialState); stack.Push(q0A_x_q0B); stateIdMap[q0A_x_q0B] = 0; revStateIdMap[0] = q0A_x_q0B; Func <int, int, int> ComposeStates = (x, y) => { var xy = new Tuple <int, int>(x, y); int q; if (stateIdMap.TryGetValue(xy, out q)) { return(q); } else { q = stateId; stateId += 1; stateIdMap[xy] = q; revStateIdMap[q] = xy; stack.Push(xy); return(q); } }; var A2B = new STb <FUNC, TERM, SORT>(solver, A.Name + "2" + B.Name, A.InputSort, B.OutputSort, regSort, JoinRegs(A.InitialRegister, B.InitialRegister), 0); //create normal composed rules while (stack.IsNonempty) { var qA_x_qB = stack.Pop(); var qA = qA_x_qB.Item1; var qB = qA_x_qB.Item2; var ruleA = A.GetRuleFrom(qA); if (ruleA.IsNotUndef) { var qAB_rule = Comp(solver.True, ruleA, qB, ComposeStates, false); A2B.AssignRule(stateIdMap[qA_x_qB], qAB_rule); } else { A2B.AssignRule(stateIdMap[qA_x_qB], UndefRule <TERM> .Default); } } foreach (var qAB in A2B.States) { var qA_x_qB = revStateIdMap[qAB]; var qA = qA_x_qB.Item1; var qB = qA_x_qB.Item2; var ruleA = A.GetFinalRuleFrom(qA); if (ruleA.IsNotUndef) { var qAB_Frule = Comp(solver.True, ruleA, qB, (p, q) => qAB, true); A2B.AssignFinalRule(qAB, qAB_Frule); } } A2B.EliminateDeadends(); //Func<Rule<TERM>, Rule<TERM>> ReplaceWithEpsilon = (r) => // { // }; //var aut = A2B.ToST(true).automaton.RelpaceAllGuards(ReplaceWithEpsilon); return(A2B); }
STb <FuncDecl, Expr, Sort> Generate() { var name = DeclarationType.ContainingNamespace.Name + "." + (DeclarationType.ContainingType == null ? "" : DeclarationType.ContainingType.Name + ".") + DeclarationType.Name; Console.WriteLine("XPath " + name); var parser = new XPathParser <IXPathNode>(); IXPathNode root; try { root = parser.Parse(_xpath, new XPathNodeBuilder()); Console.WriteLine(root); } catch (XPathParserException e) { throw new TransducerCompilationException("XPath parsing failed", e); } var resultSort = _ctx.MkBitVecSort(32); var levelCounterSort = _ctx.MkBitVecSort(32); var regSort = _ctx.MkTupleSort(resultSort, levelCounterSort); var initReg = _ctx.MkTuple(_ctx.MkNumeral(0, resultSort), _ctx.MkNumeral(0, levelCounterSort)); var stb = new STb <FuncDecl, Expr, Sort>(_ctx, "stb", _ctx.CharSort, _ctx.MkBitVecSort(32), regSort, initReg, 0); int freeState = 1; Func <int> nextState = () => freeState++; var resultProj = _ctx.MkProj(0, stb.RegVar); var levelCounterProj = _ctx.MkProj(1, stb.RegVar); Func <int, IgnorerInfo> CreateIgnorer = (exitState) => { IgnorerInfo info = new IgnorerInfo(); int outsideTagState = nextState(); int freshTagState = nextState(); int openingTagState = nextState(); int standaloneTagState = nextState(); int closingTagState = nextState(); stb.AssignRule(outsideTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '<'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, freshTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, outsideTagState))); stb.AssignRule(freshTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, closingTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, openingTagState))); var counterOne = _ctx.MkNumeral(1, levelCounterSort); var levelCounterInc = _ctx.MkTuple(resultProj, _ctx.MkBvAdd(levelCounterProj, counterOne)); stb.AssignRule(openingTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterInc, outsideTagState), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, standaloneTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, openingTagState)))); var counterZero = _ctx.MkNumeral(0, levelCounterSort); var levelCounterZeroed = _ctx.MkTuple(resultProj, counterZero); stb.AssignRule(standaloneTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new IteRule <Expr>(_ctx.MkEq(levelCounterProj, counterZero), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterZeroed, exitState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, outsideTagState)), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, standaloneTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, openingTagState)))); var levelCounterDec = _ctx.MkTuple(resultProj, _ctx.MkBvSub(levelCounterProj, counterOne)); stb.AssignRule(closingTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new IteRule <Expr>(_ctx.MkEq(levelCounterProj, counterOne), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterZeroed, exitState), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterDec, outsideTagState)), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, closingTagState))); info.MoveToTagOpening = new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterZeroed, openingTagState); info.MoveToTagOpeningOrStandalone = new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterZeroed, standaloneTagState), info.MoveToTagOpening); var levelCounterSet = _ctx.MkTuple(resultProj, counterOne); info.MoveToOutsideTag = new BaseRule <Expr>(Sequence <Expr> .Empty, levelCounterSet, outsideTagState); return(info); }; var next = root; int?parentState = null; int startState = stb.InitialState; int childState = nextState(); var zeroResult = _ctx.MkTuple(_ctx.MkNumeral(0, resultSort), levelCounterProj); while (next != null) { XPathAxisNode current; var step = next as XPathStepNode; if (step != null) { current = step.Left as XPathAxisNode; next = step.Right; } else { current = next as XPathAxisNode; next = null; } if (current.Axis == XPathAxis.Root) { continue; } if (current == null) { throw new TransducerCompilationException("Unsupported XPath node type: " + next.GetType()); } if (current.Axis != XPathAxis.Child) { throw new TransducerCompilationException("Unsupported axis: " + current.Axis); } if (current.Type != System.Xml.XPath.XPathNodeType.Element) { throw new TransducerCompilationException("Unsupported node type: " + current.Type); } int freshTagState = nextState(); int closingTagState = nextState(); int standaloneMatchState = nextState(); int matchedOpeningTagState = nextState(); int matchedStandaloneTagState = nextState(); var ignorer = CreateIgnorer(startState); stb.AssignRule(startState, new IteRule <Expr>(EqualsChar(stb.InputVar, '<'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, freshTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, startState))); int matchState = freshTagState; int nextMatchState = nextState(); bool first = true; foreach (char c in current.Label) { STbRule <Expr> matchRule; if (first) { matchRule = new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, closingTagState), new IteRule <Expr>(EqualsChar(stb.InputVar, c), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, nextMatchState), new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), ignorer.MoveToOutsideTag, ignorer.MoveToTagOpening))); first = false; } else { matchRule = new IteRule <Expr>(EqualsChar(stb.InputVar, c), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, nextMatchState), new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), ignorer.MoveToOutsideTag, ignorer.MoveToTagOpeningOrStandalone)); } stb.AssignRule(matchState, matchRule); matchState = nextMatchState; nextMatchState = nextState(); } stb.AssignRule(closingTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), parentState != null ? (STbRule <Expr>) new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, parentState.Value) : new UndefRule <Expr>(), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, closingTagState))); stb.AssignRule(matchState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, zeroResult, childState), new IteRule <Expr>(EqualsChar(stb.InputVar, ' '), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedOpeningTagState), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, standaloneMatchState), ignorer.MoveToTagOpening)))); stb.AssignRule(standaloneMatchState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, startState), new UndefRule <Expr>())); stb.AssignRule(matchedOpeningTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, zeroResult, childState), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedStandaloneTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedOpeningTagState)))); stb.AssignRule(matchedStandaloneTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, startState), new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedStandaloneTagState), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, matchedOpeningTagState)))); parentState = startState; startState = childState; childState = nextState(); } Func <Expr, Expr> AddZeros = (c) => { uint k = (uint)(32 - (int)_ctx.CharSetProvider.Encoding); if (k == 0) { return(c); } else { return(_ctx.MkZeroExt(k, c)); } }; var toIntUpdate = _ctx.MkTuple( _ctx.MkBvAdd(_ctx.MkBvMul(_ctx.MkNumeral(10, resultSort), resultProj), _ctx.MkBvSub(AddZeros(stb.InputVar), _ctx.MkNumeral((int)'0', resultSort))), levelCounterProj); var expectSlashState = nextState(); var scanTagState = nextState(); stb.AssignRule(startState, new IteRule <Expr>(EqualsChar(stb.InputVar, '<'), new BaseRule <Expr>(new Sequence <Expr>(resultProj), zeroResult, expectSlashState), new BaseRule <Expr>(Sequence <Expr> .Empty, toIntUpdate, startState))); stb.AssignRule(expectSlashState, new IteRule <Expr>(EqualsChar(stb.InputVar, '/'), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, scanTagState), new UndefRule <Expr>())); stb.AssignRule(scanTagState, new IteRule <Expr>(EqualsChar(stb.InputVar, '>'), parentState != null ? (STbRule <Expr>) new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, parentState.Value) : new UndefRule <Expr>(), new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, scanTagState))); Console.WriteLine(stb.StateCount); foreach (var state in stb.States) { stb.AssignFinalRule(state, new BaseRule <Expr>(Sequence <Expr> .Empty, stb.RegVar, state)); } if (ShowGraphStages.Count > 0) { stb.ToST().ShowGraph(); } return(stb); }
STb <FuncDecl, Expr, Sort> GenerateSTb() { var name = DeclarationType.ContainingNamespace.Name + "." + (DeclarationType.ContainingType == null ? "" : DeclarationType.ContainingType.Name + ".") + DeclarationType.Name; Console.WriteLine("Exploring " + name); Expr inputVar = _info.AutomataCtx.MkVar(0, Mapper.GetSortMapping(_transducerType.TypeArguments[0]).Sort); Expr registerVar = _info.AutomataCtx.MkVar(1, Mapper.GetSortMapping(DeclarationType).Sort); Mutator register = Mapper.GetSortMapping(DeclarationType).MutatorForValue(registerVar); var methods = DeclarationType.DeclaringSyntaxReferences.Select(r => r.GetSyntax()) .SelectMany(s => s.DescendantNodes(n => !(n is MethodDeclarationSyntax))) .OfType <MethodDeclarationSyntax>().Select(Syntax => new { Syntax, Symbol = Model.GetDeclaredSymbol(Syntax) as IMethodSymbol }) .Where(x => x.Symbol != null); // Find the Update function var updateMethods = methods.Where(x => x.Symbol.MetadataName == "Update" && x.Symbol.IsOverride && x.Symbol.Parameters.Length == 1 && x.Symbol.Parameters[0].Type == InputTypeSymbol).ToArray(); if (updateMethods.Length == 0) { throw new SyntaxErrorException("No IEnumerable<" + OutputTypeSymbol + "> Update(" + InputTypeSymbol + ") method declared"); } else if (updateMethods.Length > 1) { throw new SyntaxErrorException("Multiple Update methods declared"); } var updateMethod = updateMethods[0]; // Explore the Update function var updateCfg = new ControlFlowGraph(updateMethod.Syntax.Body, Model); Dictionary <ISymbol, Mutator> parameters = updateMethod.Symbol.Parameters .ToDictionary(p => (ISymbol)p, p => Mapper.GetSortMapping(_transducerType.TypeArguments[0]).MutatorForValue(inputVar)); var updateEntryState = new MainExplorationState(_info, updateCfg.EntryPoint, register, parameters, new[] { inputVar, registerVar }); var updateRule = updateEntryState.Explore(); // Find the Finish function var finishMethods = methods.Where(x => x.Symbol.MetadataName == "Finish" && x.Symbol.IsOverride && x.Symbol.Parameters.Length == 0).ToArray(); STbRule <Expr> finishRule; if (finishMethods.Length == 0) { finishRule = new BaseRule <Expr>(Sequence <Expr> .Empty, register.CreateUpdate(), 0); } else { if (finishMethods.Length > 1) { throw new SyntaxErrorException("Multiple Finish methods declared"); } var finishMethod = finishMethods[0]; // Explore the Finish function var finishCfg = new ControlFlowGraph(finishMethod.Syntax.Body, Model); var finishEntryState = new MainExplorationState(_info, finishCfg.EntryPoint, register, new Dictionary <ISymbol, Mutator>(), new[] { registerVar }); finishRule = finishEntryState.Explore(); } var outputSort = Mapper.GetSortMapping(_transducerType.TypeArguments[1]).Sort; var stb = new STb <FuncDecl, Expr, Sort>(_info.AutomataCtx, DeclarationType.Name, inputVar.Sort, outputSort, registerVar.Sort, Mapper.GetSortMapping(DeclarationType).MutatorForDefaultValue().CreateUpdate().SafeSimplify(Ctx), 0); stb.AssignRule(0, updateRule); stb.AssignFinalRule(0, finishRule); if (ShowGraphStages.Contains(ShowGraph.Stage.UnSimplified)) { stb.ShowGraph(); } stb = stb.Flatten(); if (ShowGraphStages.Contains(ShowGraph.Stage.Simplified)) { stb.ToST().ShowGraph(); } return(stb); }