Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Use a more clever algorithm for collecting fates
Takes 12% off STD SAFE.setting time.
  • Loading branch information
sorear committed Nov 24, 2010
1 parent e8a2b1c commit 6a9add7
Showing 1 changed file with 47 additions and 15 deletions.
62 changes: 47 additions & 15 deletions lib/Cursor.cs
Expand Up @@ -1274,14 +1274,14 @@ public sealed class LexerState {
}
}

public void CollectFates(NFA nf, Stack<int> f) {
public void CollectFates(NFA nf, Lexer l) {
for (int i = nf.nodes.Length - 1; i >= 0; i--) {
if ((nstates[i >> 5] & (1 << (i & 31))) != 0) {
NFA.Node n = nf.nodes[i];
if (n.final) {
if (Lexer.LtmTrace)
Console.WriteLine("+ Adding fate {0}", n.fate);
f.Push(n.fate);
l.NoteFate(n.fate);
}
}
}
Expand Down Expand Up @@ -1334,6 +1334,14 @@ public class Lexer {
LexerState start;
LexerState nil;

int nfates;
// 2*nfates+2 elements, arranged in linked list nodes of 2 values
// each, prev then next. If prev == -1 this element is not in the
// list. Element 0 is the header node; the list is maintained
// circular.
int[] fatebuffer;
int usedfates;

public static bool LtmTrace =
Environment.GetEnvironmentVariable("NIECZA_LTM_TRACE") != null;

Expand Down Expand Up @@ -1387,6 +1395,11 @@ public class Lexer {
pad.nodes_l[target].final = true;
alts[alt_shuffle[ix]].ToNFA(pad, root, target);
}
nfates = alts.Length;
fatebuffer = new int[nfates*2+2];
for (int i = 0; i < nfates*2+2; i++)
fatebuffer[i] = -1;
fatebuffer[0] = fatebuffer[1] = 0;
pad.Complete();
// now the NFA nodes are all in tiebreak order by lowest index
if (LtmTrace) {
Expand Down Expand Up @@ -1414,16 +1427,39 @@ public class Lexer {
Console.WriteLine("--- END");
}

internal void NoteFate(int fate) {
fate++; // 0 is used as a sentinel
if (fatebuffer[fate * 2] == -1) {
usedfates++;
} else {
// next->prev = prev
fatebuffer[fatebuffer[fate * 2] * 2 + 1] =
fatebuffer[fate * 2 + 1];
fatebuffer[fatebuffer[fate * 2 + 1] * 2] =
fatebuffer[fate * 2];
}
fatebuffer[fate * 2] = fatebuffer[0];
fatebuffer[fate * 2 + 1] = 0;
fatebuffer[fatebuffer[0] * 2 + 1] = fate;
fatebuffer[0] = fate;
}

public int[] Run(string from, int pos) {
LexerState state = start;
Stack<int> fate = new Stack<int>();
// clear out any old fates
for (int i = fatebuffer[0]; i != 0; ) {
int j = fatebuffer[2*i];
fatebuffer[2*i] = -1;
i = j;
}
fatebuffer[0] = fatebuffer[1] = 0;
usedfates = 0;

if (LtmTrace)
Console.WriteLine("+ Trying lexer {0} at {1}", tag, pos);

while (true) {
state.CollectFates(pad, fate);
state.CollectFates(pad, this);

if (pos == from.Length || state == nil) break;
char ch = from[pos++];
Expand All @@ -1439,20 +1475,16 @@ public class Lexer {
state = next;
}

List<int> uniqfates = new List<int>();
HashSet<int> usedfates = new HashSet<int>();
int[] uniqfates = new int[usedfates];

while (fate.Count != 0) {
int f = fate.Pop();
if (usedfates.Contains(f))
continue;
usedfates.Add(f);
int cursor = 0;
for (int i = 0; i < usedfates; i++) {
cursor = fatebuffer[cursor * 2];
uniqfates[i] = cursor - 1;
if (LtmTrace)
Console.WriteLine("+ Useful fate: {0}", f);
uniqfates.Add(f);
Console.WriteLine("+ Useful fate: {0}", cursor - 1);
}

return uniqfates.ToArray();
return uniqfates;
}

public static Lexer GetProtoregexLexer(DynMetaObject kl, string name) {
Expand Down

0 comments on commit 6a9add7

Please sign in to comment.