dfa.cs
来自「全功能c#编译器」· CS 代码 · 共 890 行 · 第 1/2 页
CS
890 行
static void NumberNodes(Node p, State state) {
/* Assigns a state n.state to every node n. There will be a transition from
n.state to n.next.state triggered by n.val. All nodes in an alternative
chain are represented by the same state.
*/
if (p == null) return;
if (p.state != null) return; // already visited;
if (state == null) state = NewState();
p.state = state;
if (Node.DelGraph(p)) state.endOf = curSy;
switch (p.typ) {
case Node.clas: case Node.chr: {
NumberNodes(p.next, null);
break;
}
case Node.opt: {
NumberNodes(p.next, null); NumberNodes(p.sub, state);
break;
}
case Node.iter: {
NumberNodes(p.next, state); NumberNodes(p.sub, state);
break;
}
case Node.alt: {
NumberNodes(p.sub, state); NumberNodes(p.down, state);
break;
}
}
}
static void FindTrans (Node p, bool start, BitArray marked) {
if (p == null || marked[p.n]) return;
marked[p.n] = true;
if (start) Step(p.state, p, new BitArray(Node.nodes.Count)); // start of group of equally numbered nodes
switch (p.typ) {
case Node.clas: case Node.chr: {
FindTrans(p.next, true, marked);
break;
}
case Node.opt: {
FindTrans(p.next, true, marked); FindTrans(p.sub, false, marked);
break;
}
case Node.iter: {
FindTrans(p.next, false, marked); FindTrans(p.sub, false, marked);
break;
}
case Node.alt: {
FindTrans(p.sub, false, marked); FindTrans(p.down, false, marked);
break;
}
}
}
public static void ConvertToStates(Node p, Symbol sym) {
curGraph = p; curSy = sym;
if (Node.DelGraph(curGraph)) Parser.SemErr("token might be empty");
NumberNodes(curGraph, firstState);
FindTrans(curGraph, true, new BitArray(Node.nodes.Count));
}
static Symbol MatchedDFA(string s, Symbol sym) {
int i, len = s.Length;
bool weakMatch = false;
// s has no quotes
State state = firstState;
for (i = 0; i < len; i++) { // try to match s against existing DFA
Action a = state.TheAction(s[i]);
if (a == null) break;
if (a.typ == Node.clas) weakMatch = true;
state = a.target.state;
}
// don't execute the following block if s was totally consumed and the DFA is in a final state
if (weakMatch && (i != len || state.endOf == null)) {
state = firstState; i = 0;
dirtyDFA = true;
}
for (; i < len; i++) { // make new DFA for s[i..len-1]
State to = NewState();
NewTransition(state, to, Node.chr, s[i], Node.normalTrans);
state = to;
}
Symbol matchedSym = state.endOf;
if (state.endOf == null) state.endOf = sym;
return matchedSym;
}
public static void MatchLiteral(Symbol sym) { // store string either as token or as literal
string name = Unescape(sym.name.Substring(1, sym.name.Length-2));
if (name.IndexOf('\0') >= 0) Parser.SemErr("\\0 not allowed here. Used as eof character");
Symbol matchedSym = MatchedDFA(name, sym);
if (matchedSym == null)
sym.tokenKind = Symbol.classToken;
else {
matchedSym.tokenKind = Symbol.classLitToken;
sym.tokenKind = Symbol.litToken;
}
}
static void SplitActions(State state, Action a, Action b) {
Action c; BitArray seta, setb, setc;
seta = a.Symbols(); setb = b.Symbols();
if (Sets.Equals(seta, setb)) {
a.AddTargets(b);
state.DetachAction(b);
} else if (Sets.Includes(seta, setb)) {
setc = (BitArray)seta.Clone(); Sets.Subtract(setc, setb);
b.AddTargets(a);
a.ShiftWith(setc);
} else if (Sets.Includes(setb, seta)) {
setc = (BitArray)setb.Clone(); Sets.Subtract(setc, seta);
a.AddTargets(b);
b.ShiftWith(setc);
} else {
setc = (BitArray)seta.Clone(); setc.And(setb);
Sets.Subtract(seta, setc);
Sets.Subtract(setb, setc);
a.ShiftWith(seta);
b.ShiftWith(setb);
c = new Action(0, 0, Node.normalTrans); // typ and sym are set in ShiftWith
c.AddTargets(a);
c.AddTargets(b);
c.ShiftWith(setc);
state.AddAction(c);
}
}
private static bool Overlap(Action a, Action b) {
BitArray seta, setb;
if (a.typ == Node.chr)
if (b.typ == Node.chr) return a.sym == b.sym;
else {setb = CharClass.Set(b.sym); return setb[a.sym];}
else {
seta = CharClass.Set(a.sym);
if (b.typ ==Node.chr) return seta[b.sym];
else {setb = CharClass.Set(b.sym); return Sets.Intersect(seta, setb);}
}
}
static bool MakeUnique(State state) { // return true if actions were split
bool changed = false;
for (Action a = state.firstAction; a != null; a = a.next)
for (Action b = a.next; b != null; b = b.next)
if (Overlap(a, b)) {SplitActions(state, a, b); changed = true;}
return changed;
}
static void MeltStates(State state) {
bool changed, ctx;
BitArray targets;
Symbol endOf;
for (Action action = state.firstAction; action != null; action = action.next) {
if (action.target.next != null) {
action.GetTargetStates(out targets, out endOf, out ctx);
Melted melt = Melted.StateWithSet(targets);
if (melt == null) {
State s = NewState(); s.endOf = endOf; s.ctx = ctx;
for (Target targ = action.target; targ != null; targ = targ.next)
s.MeltWith(targ.state);
do {changed = MakeUnique(s);} while (changed);
melt = new Melted(targets, s);
}
action.target.next = null;
action.target.state = melt.state;
}
}
}
static void FindCtxStates() {
for (State state = firstState; state != null; state = state.next)
for (Action a = state.firstAction; a != null; a = a.next)
if (a.tc == Node.contextTrans) a.target.state.ctx = true;
}
public static void MakeDeterministic() {
State state;
bool changed;
lastSimState = lastState.nr;
maxStates = 2 * lastSimState; // heuristic for set size in Melted.set
FindCtxStates();
for (state = firstState; state != null; state = state.next)
do {changed = MakeUnique(state);} while (changed);
for (state = firstState; state != null; state = state.next)
MeltStates(state);
DeleteRedundantStates();
CombineShifts();
}
public static void PrintStates() {
Trace.WriteLine("\n---------- states ----------");
for (State state = firstState; state != null; state = state.next) {
bool first = true;
if (state.endOf == null) Trace.Write(" ");
else Trace.Write("E({0,12})", Node.Name(state.endOf.name));
Trace.Write("{0,3}:", state.nr);
if (state.firstAction == null) Trace.WriteLine();
for (Action action = state.firstAction; action != null; action = action.next) {
if (first) {Trace.Write(" "); first = false;} else Trace.Write(" ");
if (action.typ == Node.clas) Trace.Write(((CharClass)CharClass.classes[action.sym]).name);
else Trace.Write("{0, 3}", Ch((char)action.sym));
for (Target targ = action.target; targ != null; targ = targ.next)
Trace.Write(" {0, 3}", targ.state.nr);
if (action.tc == Node.contextTrans) Trace.WriteLine(" context"); else Trace.WriteLine();
}
}
Trace.WriteLine("\n---------- character classes ----------");
CharClass.WriteClasses();
}
static void GenComBody(Comment com) {
gen.WriteLine( "\t\t\tfor(;;) {");
gen.Write ( "\t\t\t\tif ({0}) ", ChCond(com.stop[0])); gen.WriteLine("{");
if (com.stop.Length == 1) {
gen.WriteLine("\t\t\t\t\tlevel--;");
gen.WriteLine("\t\t\t\t\tif (level == 0) { oldEols = line - line0; NextCh(); return true; }");
gen.WriteLine("\t\t\t\t\tNextCh();");
} else {
gen.WriteLine("\t\t\t\t\tNextCh();");
gen.WriteLine("\t\t\t\t\tif ({0}) {{", ChCond(com.stop[1]));
gen.WriteLine("\t\t\t\t\t\tlevel--;");
gen.WriteLine("\t\t\t\t\t\tif (level == 0) { oldEols = line - line0; NextCh(); return true; }");
gen.WriteLine("\t\t\t\t\t\tNextCh();");
gen.WriteLine("\t\t\t\t\t}");
}
if (com.nested) {
gen.Write ("\t\t\t\t}"); gen.Write(" else if ({0}) ", ChCond(com.start[0])); gen.WriteLine("{");
if (com.start.Length == 1)
gen.WriteLine("\t\t\t\t\tlevel++; NextCh();");
else {
gen.WriteLine("\t\t\t\t\tNextCh();");
gen.Write ("\t\t\t\t\tif ({0}) ", ChCond(com.start[1])); gen.WriteLine("{");
gen.WriteLine("\t\t\t\t\t\tlevel++; NextCh();");
gen.WriteLine("\t\t\t\t\t}");
}
}
gen.WriteLine( "\t\t\t\t} else if (ch == EOF) return false;");
gen.WriteLine( "\t\t\t\telse NextCh();");
gen.WriteLine( "\t\t\t}");
}
static void GenComment(Comment com, int i) {
gen.Write ("\n\tstatic bool Comment{0}() ", i); gen.WriteLine("{");
gen.WriteLine("\t\tint level = 1, line0 = line, lineStart0 = lineStart;");
if (com.start.Length == 1) {
gen.WriteLine("\t\tNextCh();");
GenComBody(com);
} else {
gen.WriteLine("\t\tNextCh();");
gen.Write ("\t\tif ({0}) ", ChCond(com.start[1])); gen.WriteLine("{");
gen.WriteLine("\t\t\tNextCh();");
GenComBody(com);
gen.WriteLine("\t\t} else {");
gen.WriteLine("\t\t\tif (ch==EOL) {line--; lineStart = lineStart0;}");
gen.WriteLine("\t\t\tpos = pos - 2; Buffer.Pos = pos+1; NextCh();");
gen.WriteLine("\t\t}");
gen.WriteLine("\t\treturn false;");
}
gen.WriteLine("\t}");
}
static void CopyFramePart(string stop) {
char startCh = stop[0];
int endOfStopString = stop.Length-1;
int ch = fram.ReadByte();
while (ch != EOF)
if (ch == startCh) {
int i = 0;
do {
if (i == endOfStopString) return; // stop[0..i] found
ch = fram.ReadByte(); i++;
} while (ch == stop[i]);
// stop[0..i-1] found; continue with last read character
gen.Write(stop.Substring(0, i));
} else {
gen.Write((char)ch); ch = fram.ReadByte();
}
Errors.Exception(" -- incomplete or corrupt scanner frame file");
}
static void GenLiterals () {
foreach (Symbol sym in Symbol.terminals) {
if (sym.tokenKind == Symbol.litToken) {
// sym.name stores literals with quotes, e.g. "\"Literal\"",
// therefore do NOT place any quotes around {0} after the case
// or you'll get: case ""Literal"": t.kind = ..., which causes an error
gen.WriteLine("\t\t\tcase {0}: t.kind = {1}; break;", sym.name, sym.n);
}
}
gen.WriteLine("\t\t\tdefault: break;");
}
static void WriteState(State state) {
Symbol endOf = state.endOf;
gen.WriteLine("\t\t\tcase {0}:", state.nr);
bool ctxEnd = state.ctx;
for (Action action = state.firstAction; action != null; action = action.next) {
if (action == state.firstAction) gen.Write("\t\t\t\tif (");
else gen.Write("\t\t\t\telse if (");
if (action.typ == Node.chr) gen.Write(ChCond((char)action.sym));
else PutRange(CharClass.Set(action.sym));
gen.Write(") {");
if (action.tc == Node.contextTrans) {
gen.Write("apx++; "); ctxEnd = false;
} else if (state.ctx)
gen.Write("apx = 0; ");
gen.Write("buf.Append(ch); NextCh(); goto case {0};", action.target.state.nr);
gen.WriteLine("}");
}
if (state.firstAction == null)
gen.Write("\t\t\t\t{");
else
gen.Write("\t\t\t\telse {");
if (ctxEnd) { // final context state: cut appendix
gen.WriteLine();
gen.WriteLine("\t\t\t\t\tbuf.Length = buf.Length - apx;");
gen.WriteLine("\t\t\t\t\tpos = pos - apx - 1; line = t.line;");
gen.WriteLine("\t\t\t\t\tBuffer.Pos = pos+1; NextCh();");
gen.Write( "\t\t\t\t\t");
}
if (endOf == null) {
gen.WriteLine("t.kind = noSym; goto done;}");
} else {
gen.Write("t.kind = {0}; ", endOf.n);
if (endOf.tokenKind == Symbol.classLitToken) {
gen.WriteLine("t.val = buf.ToString(); CheckLiteral(); return t;}");
} else {
gen.WriteLine("goto done;}");
}
}
}
static void FillStartTab(int[] startTab) {
startTab[0] = State.lastNr + 1; // eof
for (Action action = firstState.firstAction; action != null; action = action.next) {
int targetState = action.target.state.nr;
if (action.typ == Node.chr) startTab[action.sym] = targetState;
else {
BitArray s = CharClass.Set(action.sym);
for (int i = 0; i < s.Count; i++)
if (s[i]) startTab[i] = targetState;
}
}
}
public static void WriteScanner() {
int i, j;
int[] startTab = new int[CharClass.charSetSize];
string dir = System.Environment.CurrentDirectory;
string fr = dir + "\\Scanner.frame";
if (!File.Exists(fr)) {
string frameDir = Environment.GetEnvironmentVariable("crframes");
if (frameDir != null) fr = frameDir.Trim() + "\\Scanner.frame";
if (!File.Exists(fr)) Errors.Exception("-- Cannot find Scanner.frame");
}
try {
fram = new FileStream(fr, FileMode.Open, FileAccess.Read, FileShare.Read);
} catch (FileNotFoundException) {
Errors.Exception("-- Cannot open Scanner.frame.");
}
try {
string fn = dir + "\\Scanner.cs";
if (File.Exists(fn)) File.Copy(fn, fn+".old", true);
FileStream s = new FileStream(fn, FileMode.Create);
gen = new StreamWriter(s);
} catch (IOException) {
Errors.Exception("-- Cannot generate scanner file.");
}
if (dirtyDFA) MakeDeterministic();
FillStartTab(startTab);
CopyFramePart("-->namespace");
/* AW add namespace, if it exists */
if (Tab.nsName != null && Tab.nsName.Length > 0) {
gen.Write("namespace ");
gen.Write(Tab.nsName);
gen.Write(" {");
}
CopyFramePart("-->constants");
gen.WriteLine("\tconst int maxT = {0};", Symbol.terminals.Count - 1);
CopyFramePart("-->declarations");
gen.WriteLine("\tconst int noSym = {0};", Tab.noSym.n);
gen.WriteLine("\tstatic short[] start = {");
for (i = 0; i < CharClass.charSetSize / 16; i++) {
gen.Write("\t");
for (j = 0; j < 16; j++)
gen.Write("{0,3},", startTab[16*i+j]);
gen.WriteLine();
}
gen.WriteLine("\t 0};");
CopyFramePart("-->initialization");
gen.WriteLine("\t\tignore = new BitArray({0});", CharClass.charSetSize);
gen.Write("\t\t");
if (Tab.ignored == null) gen.Write("ignore[' '] = true;");
else {
j = 0;
for (i = 0; i < Tab.ignored.Count; i++)
if (Tab.ignored[i]) {
gen.Write("ignore[{0}] = true; ", i);
if (++j % 4 == 0) { gen.WriteLine(); gen.Write("\t\t"); }
}
}
CopyFramePart("-->comment");
Comment com = Comment.first; i = 0;
while (com != null) {
GenComment(com, i);
com = com.next; i++;
}
CopyFramePart("-->literals"); GenLiterals();
CopyFramePart("-->scan1");
if (Comment.first!=null) {
gen.Write("\t\tif (");
com = Comment.first; i = 0;
while (com != null) {
gen.Write(ChCond(com.start[0]));
gen.Write(" && Comment{0}()", i);
if (com.next != null) gen.Write(" ||");
com = com.next; i++;
}
gen.Write(") return NextToken();");
}
if (hasCtxMoves) gen.WriteLine("\t\tint apx = 0;");
CopyFramePart("-->scan2");
for (State state = firstState.next; state != null; state = state.next)
WriteState(state);
gen.Write("\t\t\tcase "+(State.lastNr+1)+": {t.kind = 0; goto done;}");
CopyFramePart("$$$");
/* AW 12-20-02 close namespace, if it exists */
if (Tab.nsName != null && Tab.nsName.Length > 0) gen.Write("}");
gen.Close();
}
public static void Init (string dir) {
srcDir = dir;
firstState = null; lastState = null; State.lastNr = -1;
firstState = NewState();
Melted.first = null; Comment.first = null;
dirtyDFA = false;
hasCtxMoves = false;
}
} // end DFA
} // end namespace
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?