/// <summary> /// Add a transition to the NState. /// Assert: if the symbol ordinals are packed /// the mapping has already been performed /// </summary> /// <param name="ord">The symbol index</param> /// <param name="nxt">The destination state</param> private void AddRawTransition(int ord, NState nxt) { if (GetNext(ord) == null) SetNext(ord, nxt); else // state must have overlapping alternatives { NState temp = myNfaInst.MkState(); this.AddEpsTrns(temp); temp.AddRawTransition(ord, nxt); } }
internal void SetNext(int sym, NState dstState) { uint key = (this.serialNumber << 16) + (ushort)sym; myNfsa.next.Add(key, dstState); }
/// <summary> /// Add a transition from "this" to "next" /// for every true bit in the BitArray cls /// </summary> /// <param name="cls">The transition bit array</param> /// <param name="nxt">The destination state</param> private void AddClsTrans(BitArray cls, NState nxt) { for (int i = 0; i < cls.Count; i++) if (cls[i]) AddRawTransition(i, nxt); }
/// <summary> /// Add a transition from NState "this" /// to NState "nxt", for each character /// value in the leaf range list. /// If the characters are packed, transform /// from character ordinal to equivalence class /// ordinal. /// </summary> /// <param name="leaf">The regex leaf node</param> /// <param name="nxt">The destination state</param> public void AddClsTrans(Leaf leaf, NState nxt) { BitArray cls = new BitArray(myNfaInst.MaxSym); if (myNfaInst.Pack) { foreach (int ord in leaf.rangeLit.equivClasses) cls[ord] = true; } else { foreach (CharRange rng in leaf.rangeLit.list.Ranges) for (int i = rng.minChr; i <= rng.maxChr; i++) cls[i] = true; if (leaf.rangeLit.list.IsInverted) cls = cls.Not(); } AddClsTrans(cls, nxt); }
/// <summary> /// Add an epsilon transition from "this" to "nxt" /// </summary> /// <param name="nxt">Destination state</param> public void AddEpsTrns(NState nxt) { int count = epsilons.Count; if (count < myNfaInst.MaxEps) epsilons.Length = myNfaInst.MaxEps; if (!epsilons[nxt.ord]) { epsList.Add(nxt); epsilons[nxt.ord] = true; } }
internal NState MkState() { NState s = new NState(this); s.ord = nStates.Count; if (s.ord >= maxE) maxE *= 2; nStates.Add(s); return s; }
/// <summary> /// Add a transition from NState "this" /// to NState "nxt", for the character "chr". /// If the characters are packed, transform /// from character ordinal to equivalence class /// ordinal. /// </summary> /// <param name="chr">The character value</param> /// <param name="nxt">The destination state</param> public void AddChrTrns(int chr, NState nxt) { if (myNfaInst.Pack) chr = myNfaInst.parent.task.partition[chr]; AddRawTransition(chr, nxt); }
/// <summary> /// Create a transition path in the NFSA from the given /// start state to the given end state, corresponding to the /// RegEx tree value. The method may (almost always does) /// create new NFSA states and recurses to make paths for /// the subtrees of the given tree. /// </summary> /// <param name="tree">The tree to encode</param> /// <param name="start">The start state for the pattern</param> /// <param name="end">The end state for the pattern</param> internal void MakePath(RegExTree tree, NState startState, NState endState) { NState tmp1 = null; NState tmp2 = null; int rLen, lLen; switch (tree.op) { case RegOp.eof: break; // Binary nodes =================================== case RegOp.context: case RegOp.concat: case RegOp.alt: // Binary nodes =================================== Binary binNode = tree as Binary; switch (tree.op) { case RegOp.context: rLen = binNode.rKid.contextLength(); lLen = binNode.lKid.contextLength(); if (rLen <= 0 && lLen <= 0) throw new StringInterpretException("variable right context '/' not implemented"); else { endState.rhCntx = rLen; endState.lhCntx = lLen; tmp1 = MkState(); MakePath(binNode.lKid, startState, tmp1); MakePath(binNode.rKid, tmp1, endState); } break; case RegOp.concat: tmp1 = MkState(); MakePath(binNode.lKid, startState, tmp1); MakePath(binNode.rKid, tmp1, endState); break; case RegOp.alt: tmp1 = MkState(); MakePath(binNode.lKid, startState, tmp1); tmp1.AddEpsTrns(endState); tmp1 = MkState(); MakePath(binNode.rKid, startState, tmp1); tmp1.AddEpsTrns(endState); break; } break; // Unary nodes =================================== case RegOp.closure: case RegOp.finiteRep: // Unary nodes =================================== Unary unaryNode = tree as Unary; switch (tree.op) { case RegOp.closure: tmp2 = MkState(); if (unaryNode.minRep == 0) { tmp1 = MkState(); startState.AddEpsTrns(tmp1); } else { NState dummy = startState; for (int i = 0; i < unaryNode.minRep; i++) { tmp1 = MkState(); MakePath(unaryNode.kid, dummy, tmp1); dummy = tmp1; } } MakePath(unaryNode.kid, tmp1, tmp2); tmp2.AddEpsTrns(tmp1); tmp1.AddEpsTrns(endState); break; case RegOp.finiteRep: { NState dummy = tmp1 = startState; for (int i = 0; i < unaryNode.minRep; i++) { tmp1 = MkState(); MakePath(unaryNode.kid, dummy, tmp1); dummy = tmp1; } tmp1.AddEpsTrns(endState); for (int i = unaryNode.minRep; i < unaryNode.maxRep; i++) { tmp1 = MkState(); MakePath(unaryNode.kid, dummy, tmp1); dummy = tmp1; dummy.AddEpsTrns(endState); } } break; } break; // Leaf nodes =================================== case RegOp.litStr: case RegOp.primitive: case RegOp.charClass: // Leaf nodes =================================== Leaf leafNode = tree as Leaf; switch (tree.op) { case RegOp.litStr: { // Make a linear sequence of states with successive // transitions on successive string characters. // string text = leafNode.str; NState dummy = startState; // Need to deal with special case of empty string if (text.Length == 0) dummy.AddEpsTrns(endState); else { // This code is complicated by the fact that unicode // escape substitution may have inserted surrogate // pairs of characters in the string. We need // one transition for every unicode character, // not one for every char value in this string. // int index = 0; int code = CharacterUtilities.CodePoint(text, ref index); // First character int next = CharacterUtilities.CodePoint(text, ref index); // Next, possibly -1 while (next >= 0) { tmp1 = MkState(); dummy.AddChrTrns(code, tmp1); dummy = tmp1; code = next; next = CharacterUtilities.CodePoint(text, ref index); } // Postcondition ==> "code" is the last char. dummy.AddChrTrns(code, endState); } } break; case RegOp.primitive: startState.AddChrTrns(leafNode.chVal, endState); break; case RegOp.charClass: startState.AddClsTrans(leafNode, endState); break; } break; default: throw new GplexInternalException("unknown tree op"); } }
internal void MarkAccept(NState acpt, RuleDesc rule) { acpt.accept = rule; acceptStates.Add(acpt.ord); }
public NfsaInstance(StartState ss, NFSA parent) { myStartCondition = ss; this.parent = parent; this.pack = parent.task.ChrClasses; if (pack) maxS = parent.task.partition.Length; // Number of equivalence classes else maxS = parent.task.TargetSymCardinality; // Size of alphabet entryState = MkState(); }
// // For version 1.0.1 recognize any line-end character if /unicode // static void AddAnchorContext(NfsaInstance nInst, NState endS, RuleDesc rule) { NState nEnd = nInst.MkState(); Leaf temp = new Leaf(RegOp.charClass); temp.rangeLit = RangeLiteral.RightAnchors; nInst.MakePath(temp, endS, nEnd); nInst.MarkAccept(nEnd, rule); nEnd.rhCntx = 1; }
internal void SetNext(int sym, NState dstState) { ulong key = checked(((ulong)this.serialNumber << 32) + (ulong)sym); myNfsa.next.Add(key, dstState); }
/// <summary> /// Add a transition from NState "this" /// to NState "nxt", for each character /// value in the leaf range list. /// If the characters are packed, transform /// from character ordinal to equivalence class /// ordinal. /// </summary> /// <param name="leaf">The regex leaf node</param> /// <param name="nxt">The destination state</param> public void AddClsTrans(Leaf leaf, NState nxt) { if (myNfaInst.parent.task.CaseAgnostic) { leaf.rangeLit.list = leaf.rangeLit.list.MakeCaseAgnosticList(); leaf.rangeLit.list.Canonicalize(); } BitArray cls = new BitArray(myNfaInst.MaxSym); if (myNfaInst.Pack) { foreach (int ord in leaf.rangeLit.equivClasses) cls[ord] = true; } else { foreach (CharRange rng in leaf.rangeLit.list.Ranges) for (int i = rng.minChr; i <= rng.maxChr; i++) cls[i] = true; if (leaf.rangeLit.list.IsInverted) cls = cls.Not(); } AddClsTrans(cls, nxt); }
/// <summary> /// Add a transition from NState "this" /// to NState "nxt", for the character "chr". /// If the characters are packed, transform /// from character ordinal to equivalence class /// ordinal. /// </summary> /// <param name="chr">The character value</param> /// <param name="nxt">The destination state</param> public void AddChrTrns(int chr, NState nxt) { if (myNfaInst.parent.task.CaseAgnostic && chr < Char.MaxValue) { char c = (char)chr; char lo = Char.ToLower(c); char hi = Char.ToUpper(c); if (lo != hi) { AddTrns(lo, nxt); AddTrns(hi, nxt); return; } } AddTrns(chr, nxt); }