码迷,mamicode.com
首页 > 其他好文 > 详细

CocoSourcesCS 2

时间:2015-06-24 23:49:08      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:

CocoSourcesCS 2

 

   1 /*-------------------------------------------------------------------------
   2 DFA.cs -- Generation of the Scanner Automaton
   3 Compiler Generator Coco/R,
   4 Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
   5 extended by M. Loeberbauer & A. Woess, Univ. of Linz
   6 with improvements by Pat Terry, Rhodes University
   7 
   8 This program is free software; you can redistribute it and/or modify it 
   9 under the terms of the GNU General Public License as published by the 
  10 Free Software Foundation; either version 2, or (at your option) any 
  11 later version.
  12 
  13 This program is distributed in the hope that it will be useful, but 
  14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
  16 for more details.
  17 
  18 You should have received a copy of the GNU General Public License along 
  19 with this program; if not, write to the Free Software Foundation, Inc., 
  20 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21 
  22 As an exception, it is allowed to write an extension of Coco/R that is
  23 used as a plugin in non-free software.
  24 
  25 If not otherwise stated, any source code generated by Coco/R (other than 
  26 Coco/R itself) does not fall under the GNU General Public License.
  27 -------------------------------------------------------------------------*/
  28 using System;
  29 using System.IO;
  30 using System.Text;
  31 using System.Collections;
  32 
  33 namespace at.jku.ssw.Coco {
  34 
  35 //-----------------------------------------------------------------------------
  36 //  State
  37 //-----------------------------------------------------------------------------
  38 
  39 public class State {                // state of finite automaton
  40     public int nr;                        // state number
  41     public Action firstAction;// to first action of this state
  42     public Symbol endOf;            // recognized token if state is final
  43     public bool ctx;                    // true if state is reached via contextTrans
  44     public State next;
  45     
  46     public void AddAction(Action act) {
  47         Action lasta = null, a = firstAction;
  48         while (a != null && act.typ >= a.typ) {lasta = a; a = a.next;}
  49         // collecting classes at the beginning gives better performance
  50         act.next = a;
  51         if (a==firstAction) firstAction = act; else lasta.next = act;
  52     }
  53     
  54     public void DetachAction(Action act) {
  55         Action lasta = null, a = firstAction;
  56         while (a != null && a != act) {lasta = a; a = a.next;}
  57         if (a != null)
  58             if (a == firstAction) firstAction = a.next; else lasta.next = a.next;
  59     }
  60     
  61     public void MeltWith(State s) { // copy actions of s to state
  62         for (Action action = s.firstAction; action != null; action = action.next) {
  63             Action a = new Action(action.typ, action.sym, action.tc);
  64             a.AddTargets(action);
  65             AddAction(a);
  66         }
  67     }
  68     
  69 }
  70 
  71 //-----------------------------------------------------------------------------
  72 //  Action
  73 //-----------------------------------------------------------------------------
  74 
  75 public class Action {            // action of finite automaton
  76     public int typ;                    // type of action symbol: clas, chr
  77     public int sym;                    // action symbol
  78     public int tc;                    // transition code: normalTrans, contextTrans
  79     public Target target;        // states reached from this action
  80     public Action next;
  81     
  82     public Action(int typ, int sym, int tc) {
  83         this.typ = typ; this.sym = sym; this.tc = tc;
  84     }
  85     
  86     public void AddTarget(Target t) { // add t to the action.targets
  87         Target last = null;
  88         Target p = target;
  89         while (p != null && t.state.nr >= p.state.nr) {
  90             if (t.state == p.state) return;
  91             last = p; p = p.next;
  92         }
  93         t.next = p;
  94         if (p == target) target = t; else last.next = t;
  95     }
  96 
  97     public void AddTargets(Action a) { // add copy of a.targets to action.targets
  98         for (Target p = a.target; p != null; p = p.next) {
  99             Target t = new Target(p.state);
 100             AddTarget(t);
 101         }
 102         if (a.tc == Node.contextTrans) tc = Node.contextTrans;
 103     }
 104     
 105     public CharSet Symbols(Tab tab) {
 106         CharSet s;
 107         if (typ == Node.clas)
 108             s = tab.CharClassSet(sym).Clone();
 109         else {
 110             s = new CharSet(); s.Set(sym);
 111         }
 112         return s;
 113     }
 114     
 115     public void ShiftWith(CharSet s, Tab tab) {
 116         if (s.Elements() == 1) {
 117             typ = Node.chr; sym = s.First();
 118         } else {
 119             CharClass c = tab.FindCharClass(s);
 120             if (c == null) c = tab.NewCharClass("#", s); // class with dummy name
 121             typ = Node.clas; sym = c.n;
 122         }
 123     }
 124     
 125 }
 126 
 127 //-----------------------------------------------------------------------------
 128 //  Target
 129 //-----------------------------------------------------------------------------
 130 
 131 public class Target {                // set of states that are reached by an action
 132     public State state;                // target state
 133     public Target next;
 134     
 135     public Target (State s) {
 136         state = s;
 137     }
 138 }
 139 
 140 //-----------------------------------------------------------------------------
 141 //  Melted
 142 //-----------------------------------------------------------------------------
 143 
 144 public class Melted {                    // info about melted states
 145     public BitArray set;                // set of old states
 146     public State state;                    // new state
 147     public Melted next;
 148     
 149     public Melted(BitArray set, State state) {
 150         this.set = set; this.state = state;
 151     }    
 152 }
 153 
 154 //-----------------------------------------------------------------------------
 155 //  Comment
 156 //-----------------------------------------------------------------------------
 157 
 158 public class Comment {                    // info about comment syntax
 159     public string start;
 160     public string stop;
 161     public bool nested;
 162     public Comment next;
 163     
 164     public Comment(string start, string stop, bool nested) {
 165         this.start = start; this.stop = stop; this.nested = nested;
 166     }
 167     
 168 }
 169 
 170 //-----------------------------------------------------------------------------
 171 //  CharSet
 172 //-----------------------------------------------------------------------------
 173 
 174 public class CharSet {
 175 
 176     public class Range {
 177         public int from, to;
 178         public Range next;
 179         public Range(int from, int to) { this.from = from; this.to = to; }
 180     }
 181 
 182     public Range head;
 183 
 184     public bool this[int i] {
 185         get {
 186             for (Range p = head; p != null; p = p.next)
 187                 if (i < p.from) return false;
 188                 else if (i <= p.to) return true; // p.from <= i <= p.to
 189             return false;
 190         }
 191     }
 192 
 193     public void Set(int i) {
 194         Range cur = head, prev = null;
 195         while (cur != null && i >= cur.from-1) {
 196             if (i <= cur.to + 1) { // (cur.from-1) <= i <= (cur.to+1)
 197                 if (i == cur.from - 1) cur.from--;
 198                 else if (i == cur.to + 1) {
 199                     cur.to++;
 200                     Range next = cur.next;
 201                     if (next != null && cur.to == next.from - 1) { cur.to = next.to; cur.next = next.next; };
 202                 }
 203                 return;
 204             }
 205             prev = cur; cur = cur.next;
 206         }
 207         Range n = new Range(i, i);
 208         n.next = cur;
 209         if (prev == null) head = n; else prev.next = n;
 210     }
 211 
 212     public CharSet Clone() {
 213         CharSet s = new CharSet();
 214         Range prev = null;
 215         for (Range cur = head; cur != null; cur = cur.next) {
 216             Range r = new Range(cur.from, cur.to);
 217             if (prev == null) s.head = r; else prev.next = r;
 218             prev = r;
 219         }
 220         return s;
 221     }
 222 
 223     public bool Equals(CharSet s) {
 224         Range p = head, q = s.head;
 225         while (p != null && q != null) {
 226             if (p.from != q.from || p.to != q.to) return false;
 227             p = p.next; q = q.next;
 228         }
 229         return p == q;
 230     }
 231 
 232     public int Elements() {
 233         int n = 0;
 234         for (Range p = head; p != null; p = p.next) n += p.to - p.from + 1;
 235         return n;
 236     }
 237 
 238     public int First() {
 239         if (head != null) return head.from;
 240         return -1;
 241     }
 242 
 243     public void Or(CharSet s) {
 244         for (Range p = s.head; p != null; p = p.next)
 245             for (int i = p.from; i <= p.to; i++) Set(i);
 246     }
 247 
 248     public void And(CharSet s) {
 249         CharSet x = new CharSet();
 250         for (Range p = head; p != null; p = p.next)
 251             for (int i = p.from; i <= p.to; i++)
 252                 if (s[i]) x.Set(i);
 253         head = x.head;
 254     }
 255 
 256     public void Subtract(CharSet s) {
 257         CharSet x = new CharSet();
 258         for (Range p = head; p != null; p = p.next)
 259             for (int i = p.from; i <= p.to; i++)
 260                 if (!s[i]) x.Set(i);
 261         head = x.head;
 262     }
 263 
 264     public bool Includes(CharSet s) {
 265         for (Range p = s.head; p != null; p = p.next)
 266             for (int i = p.from; i <= p.to; i++)
 267                 if (!this[i]) return false;
 268         return true;
 269     }
 270 
 271     public bool Intersects(CharSet s) {
 272         for (Range p = s.head; p != null; p = p.next)
 273             for (int i = p.from; i <= p.to; i++)
 274                 if (this[i]) return true;
 275         return false;
 276     }
 277 
 278     public void Fill() {
 279         head = new Range(Char.MinValue, Char.MaxValue);
 280     }
 281 }
 282 
 283 
 284 //-----------------------------------------------------------------------------
 285 //  Generator
 286 //-----------------------------------------------------------------------------
 287 class Generator {
 288     private const int EOF = -1;
 289 
 290     private FileStream fram;
 291     private StreamWriter gen;
 292     private readonly Tab tab;
 293     private string frameFile;
 294 
 295     public Generator(Tab tab) {
 296         this.tab = tab;
 297     }
 298 
 299     public FileStream OpenFrame(String frame) {
 300         if (tab.frameDir != null) frameFile = Path.Combine(tab.frameDir, frame);
 301         if (frameFile == null || !File.Exists(frameFile)) frameFile = Path.Combine(tab.srcDir, frame);
 302         if (frameFile == null || !File.Exists(frameFile)) throw new FatalError("Cannot find : " + frame);
 303 
 304         try {
 305             fram = new FileStream(frameFile, FileMode.Open, FileAccess.Read, FileShare.Read);
 306         } catch (FileNotFoundException) {
 307             throw new FatalError("Cannot open frame file: " + frameFile);
 308         }
 309         return fram;
 310     }
 311 
 312 
 313 
 314     public StreamWriter OpenGen(string target) {
 315         string fn = Path.Combine(tab.outDir, target);
 316         try {
 317             if (File.Exists(fn)) File.Copy(fn, fn + ".old", true);
 318             gen = new StreamWriter(new FileStream(fn, FileMode.Create)); /* pdt */
 319         } catch (IOException) {
 320             throw new FatalError("Cannot generate file: " + fn);
 321         }
 322         return gen;
 323     }
 324 
 325 
 326     public void GenCopyright() {
 327         string copyFr = null;
 328         if (tab.frameDir != null) copyFr = Path.Combine(tab.frameDir, "Copyright.frame");
 329         if (copyFr == null || !File.Exists(copyFr)) copyFr = Path.Combine(tab.srcDir, "Copyright.frame");
 330         if (copyFr == null || !File.Exists(copyFr)) return;
 331 
 332         try {
 333             FileStream scannerFram = fram;
 334             fram = new FileStream(copyFr, FileMode.Open, FileAccess.Read, FileShare.Read);
 335             CopyFramePart(null);
 336             fram = scannerFram;
 337         } catch (FileNotFoundException) {
 338             throw new FatalError("Cannot open Copyright.frame");
 339         }
 340     }
 341 
 342     public void SkipFramePart(String stop) {
 343         CopyFramePart(stop, false);
 344     }
 345 
 346 
 347     public void CopyFramePart(String stop) {
 348         CopyFramePart(stop, true);
 349     }
 350 
 351     // if stop == null, copies until end of file
 352     private void CopyFramePart(string stop, bool generateOutput) {
 353         char startCh = (char) 0;
 354         int endOfStopString = 0;
 355 
 356         if (stop != null) {
 357             startCh = stop[0];
 358             endOfStopString = stop.Length - 1;
 359         }
 360 
 361         int ch = framRead();
 362         while (ch != EOF) {
 363             if (stop != null && ch == startCh) {
 364                 int i = 0;
 365                 do {
 366                     if (i == endOfStopString) return; // stop[0..i] found
 367                     ch = framRead(); i++;
 368                 } while (ch == stop[i]);
 369                 // stop[0..i-1] found; continue with last read character
 370                 if (generateOutput) gen.Write(stop.Substring(0, i));
 371             } else {
 372                 if (generateOutput) gen.Write((char) ch);
 373                 ch = framRead();
 374             }
 375         }
 376         
 377         if (stop != null) throw new FatalError("Incomplete or corrupt frame file: " + frameFile);
 378     }
 379 
 380     private int framRead() {
 381         try {
 382             return fram.ReadByte();
 383         } catch (Exception) {
 384             throw new FatalError("Error reading frame file: " + frameFile);
 385         }
 386     }
 387 }
 388 
 389 //-----------------------------------------------------------------------------
 390 //  DFA
 391 //-----------------------------------------------------------------------------
 392 
 393 public class DFA {
 394     private int maxStates;
 395     private int lastStateNr;   // highest state number
 396     private State firstState;
 397     private State lastState;   // last allocated state
 398     private int lastSimState;  // last non melted state
 399     private FileStream fram;   // scanner frame input
 400     private StreamWriter gen;  // generated scanner file
 401     private Symbol curSy;      // current token to be recognized (in FindTrans)
 402     private bool dirtyDFA;     // DFA may become nondeterministic in MatchLiteral
 403 
 404     public bool ignoreCase;   // true if input should be treated case-insensitively
 405     public bool hasCtxMoves;  // DFA has context transitions
 406     
 407     // other Coco objects
 408     private Parser     parser;
 409     private Tab        tab;
 410     private Errors     errors;
 411     private TextWriter trace;
 412 
 413     //---------- Output primitives
 414     private string Ch(int ch) {
 415         if (ch <   || ch >= 127 || ch == \‘ || ch == \\) return Convert.ToString(ch);
 416         else return String.Format("‘{0}‘", (char)ch);
 417     }
 418     
 419     private string ChCond(char ch) {
 420         return String.Format("ch == {0}", Ch(ch));
 421     }
 422     
 423     private void PutRange(CharSet s) {
 424         for (CharSet.Range r = s.head; r != null; r = r.next) {
 425             if (r.from == r.to) { gen.Write("ch == " + Ch(r.from)); }
 426             else if (r.from == 0) { gen.Write("ch <= " + Ch(r.to)); }
 427             else { gen.Write("ch >= " + Ch(r.from) + " && ch <= " + Ch(r.to)); }
 428             if (r.next != null) gen.Write(" || ");
 429         }
 430     }
 431     
 432     //---------- State handling
 433     
 434     State NewState() {
 435         State s = new State(); s.nr = ++lastStateNr;
 436         if (firstState == null) firstState = s; else lastState.next = s;
 437         lastState = s;
 438         return s;
 439     }
 440     
 441     void NewTransition(State from, State to, int typ, int sym, int tc) {
 442         Target t = new Target(to);
 443         Action a = new Action(typ, sym, tc); a.target = t;
 444         from.AddAction(a);
 445         if (typ == Node.clas) curSy.tokenKind = Symbol.classToken;
 446     }
 447     
 448     void CombineShifts() {
 449         State state;
 450         Action a, b, c;
 451         CharSet seta, setb;
 452         for (state = firstState; state != null; state = state.next) {
 453             for (a = state.firstAction; a != null; a = a.next) {
 454                 b = a.next;
 455                 while (b != null)
 456                     if (a.target.state == b.target.state && a.tc == b.tc) {
 457                         seta = a.Symbols(tab); setb = b.Symbols(tab);
 458                         seta.Or(setb);
 459                         a.ShiftWith(seta, tab);
 460                         c = b; b = b.next; state.DetachAction(c);
 461                     } else b = b.next;
 462             }
 463         }
 464     }
 465     
 466     void FindUsedStates(State state, BitArray used) {
 467         if (used[state.nr]) return;
 468         used[state.nr] = true;
 469         for (Action a = state.firstAction; a != null; a = a.next)
 470             FindUsedStates(a.target.state, used);
 471     }
 472     
 473     void DeleteRedundantStates() {
 474         State[] newState = new State[lastStateNr + 1];
 475         BitArray used = new BitArray(lastStateNr + 1);
 476         FindUsedStates(firstState, used);
 477         // combine equal final states
 478         for (State s1 = firstState.next; s1 != null; s1 = s1.next) // firstState cannot be final
 479             if (used[s1.nr] && s1.endOf != null && s1.firstAction == null && !s1.ctx)
 480                 for (State s2 = s1.next; s2 != null; s2 = s2.next)
 481                     if (used[s2.nr] && s1.endOf == s2.endOf && s2.firstAction == null & !s2.ctx) {
 482                         used[s2.nr] = false; newState[s2.nr] = s1;
 483                     }
 484         for (State state = firstState; state != null; state = state.next)
 485             if (used[state.nr])
 486                 for (Action a = state.firstAction; a != null; a = a.next)
 487                     if (!used[a.target.state.nr])
 488                         a.target.state = newState[a.target.state.nr];
 489         // delete unused states
 490         lastState = firstState; lastStateNr = 0; // firstState has number 0
 491         for (State state = firstState.next; state != null; state = state.next)
 492             if (used[state.nr]) {state.nr = ++lastStateNr; lastState = state;}
 493             else lastState.next = state.next;
 494     }
 495     
 496     State TheState(Node p) {
 497         State state;
 498         if (p == null) {state = NewState(); state.endOf = curSy; return state;}
 499         else return p.state;
 500     }
 501     
 502     void Step(State from, Node p, BitArray stepped) {
 503         if (p == null) return;
 504         stepped[p.n] = true;
 505         switch (p.typ) {
 506             case Node.clas: case Node.chr: {
 507                 NewTransition(from, TheState(p.next), p.typ, p.val, p.code);
 508                 break;
 509             }
 510             case Node.alt: {
 511                 Step(from, p.sub, stepped); Step(from, p.down, stepped);
 512                 break;
 513             }
 514             case Node.iter: {
 515                 if (Tab.DelSubGraph(p.sub)) {
 516                     parser.SemErr("contents of {...} must not be deletable");
 517                     return;
 518                 }
 519                 if (p.next != null && !stepped[p.next.n]) Step(from, p.next, stepped);
 520                 Step(from, p.sub, stepped);
 521                 if (p.state != from) {
 522                     Step(p.state, p, new BitArray(tab.nodes.Count));
 523                 }
 524                 break;
 525             }
 526             case Node.opt: {
 527                 if (p.next != null && !stepped[p.next.n]) Step(from, p.next, stepped);
 528                 Step(from, p.sub, stepped);
 529                 break;
 530             }
 531         }
 532     }
 533 
 534     // Assigns a state n.state to every node n. There will be a transition from
 535     // n.state to n.next.state triggered by n.val. All nodes in an alternative
 536     // chain are represented by the same state.
 537     // Numbering scheme:
 538     //  - any node after a chr, clas, opt, or alt, must get a new number
 539     //  - if a nested structure starts with an iteration the iter node must get a new number
 540     //  - if an iteration follows an iteration, it must get a new number
 541     void NumberNodes(Node p, State state, bool renumIter) {
 542         if (p == null) return;
 543         if (p.state != null) return; // already visited;
 544         if (state == null || (p.typ == Node.iter && renumIter)) state = NewState();
 545         p.state = state;
 546         if (Tab.DelGraph(p)) state.endOf = curSy;
 547         switch (p.typ) {
 548             case Node.clas: case Node.chr: {
 549                 NumberNodes(p.next, null, false);
 550                 break;
 551             }
 552             case Node.opt: {
 553                 NumberNodes(p.next, null, false);
 554                 NumberNodes(p.sub, state, true);
 555                 break;
 556             }
 557             case Node.iter: {
 558                 NumberNodes(p.next, state, true);
 559                 NumberNodes(p.sub, state, true);
 560                 break;
 561             }
 562             case Node.alt: {
 563                 NumberNodes(p.next, null, false);
 564                 NumberNodes(p.sub, state, true);
 565                 NumberNodes(p.down, state, renumIter);
 566                 break;
 567             }
 568         }
 569     }
 570     
 571     void FindTrans (Node p, bool start, BitArray marked) {
 572         if (p == null || marked[p.n]) return;
 573         marked[p.n] = true;
 574         if (start) Step(p.state, p, new BitArray(tab.nodes.Count)); // start of group of equally numbered nodes
 575         switch (p.typ) {
 576             case Node.clas: case Node.chr: {
 577                 FindTrans(p.next, true, marked);
 578                 break;
 579             }
 580             case Node.opt: {
 581                 FindTrans(p.next, true, marked); FindTrans(p.sub, false, marked);
 582                 break;
 583             }
 584             case Node.iter: {
 585                 FindTrans(p.next, false, marked); FindTrans(p.sub, false, marked);
 586                 break;
 587             }
 588             case Node.alt: {
 589                 FindTrans(p.sub, false, marked); FindTrans(p.down, false, marked);
 590                 break;
 591             }
 592         }
 593     }
 594     
 595     public void ConvertToStates(Node p, Symbol sym) {
 596         curSy = sym;
 597         if (Tab.DelGraph(p)) {
 598             parser.SemErr("token might be empty");
 599             return;
 600         }
 601         NumberNodes(p, firstState, true);
 602         FindTrans(p, true, new BitArray(tab.nodes.Count));
 603         if (p.typ == Node.iter) {
 604             Step(firstState, p, new BitArray(tab.nodes.Count));
 605         }
 606     }
 607     
 608     // match string against current automaton; store it either as a fixedToken or as a litToken
 609     public void MatchLiteral(string s, Symbol sym) {
 610         s = tab.Unescape(s.Substring(1, s.Length-2));
 611         int i, len = s.Length;
 612         State state = firstState;
 613         Action a = null;
 614         for (i = 0; i < len; i++) { // try to match s against existing DFA
 615             a = FindAction(state, s[i]);
 616             if (a == null) break;
 617             state = a.target.state;
 618         }
 619         // if s was not totally consumed or leads to a non-final state => make new DFA from it
 620         if (i != len || state.endOf == null) {
 621             state = firstState; i = 0; a = null;
 622             dirtyDFA = true;
 623         }
 624         for (; i < len; i++) { // make new DFA for s[i..len-1], ML: i is either 0 or len
 625             State to = NewState();
 626             NewTransition(state, to, Node.chr, s[i], Node.normalTrans);
 627             state = to;
 628         }
 629         Symbol matchedSym = state.endOf;
 630         if (state.endOf == null) {
 631             state.endOf = sym;
 632         } else if (matchedSym.tokenKind == Symbol.fixedToken || (a != null && a.tc == Node.contextTrans)) {
 633             // s matched a token with a fixed definition or a token with an appendix that will be cut off
 634             parser.SemErr("tokens " + sym.name + " and " + matchedSym.name + " cannot be distinguished");
 635         } else { // matchedSym == classToken || classLitToken
 636             matchedSym.tokenKind = Symbol.classLitToken;
 637             sym.tokenKind = Symbol.litToken;
 638         }
 639     }
 640     
 641     void SplitActions(State state, Action a, Action b) {
 642         Action c; CharSet seta, setb, setc;
 643         seta = a.Symbols(tab); setb = b.Symbols(tab);
 644         if (seta.Equals(setb)) {
 645             a.AddTargets(b);
 646             state.DetachAction(b);
 647         } else if (seta.Includes(setb)) {
 648             setc = seta.Clone(); setc.Subtract(setb);
 649             b.AddTargets(a);
 650             a.ShiftWith(setc, tab);
 651         } else if (setb.Includes(seta)) {
 652             setc = setb.Clone(); setc.Subtract(seta);
 653             a.AddTargets(b);
 654             b.ShiftWith(setc, tab);
 655         } else {
 656             setc = seta.Clone(); setc.And(setb);
 657             seta.Subtract(setc);
 658             setb.Subtract(setc);
 659             a.ShiftWith(seta, tab);
 660             b.ShiftWith(setb, tab);
 661             c = new Action(0, 0, Node.normalTrans);  // typ and sym are set in ShiftWith
 662             c.AddTargets(a);
 663             c.AddTargets(b);
 664             c.ShiftWith(setc, tab);
 665             state.AddAction(c);
 666         }
 667     }
 668     
 669     bool Overlap(Action a, Action b) {
 670         CharSet seta, setb;
 671         if (a.typ == Node.chr)
 672             if (b.typ == Node.chr) return a.sym == b.sym;
 673             else {setb = tab.CharClassSet(b.sym); return setb[a.sym];}
 674         else {
 675             seta = tab.CharClassSet(a.sym);
 676             if (b.typ == Node.chr) return seta[b.sym];
 677             else {setb = tab.CharClassSet(b.sym); return seta.Intersects(setb);}
 678         }
 679     }
 680     
 681     void MakeUnique(State state) {
 682         bool changed;
 683         do {
 684             changed = false;
 685             for (Action a = state.firstAction; a != null; a = a.next)
 686                 for (Action b = a.next; b != null; b = b.next)
 687                     if (Overlap(a, b)) { SplitActions(state, a, b); changed = true; }
 688         } while (changed);
 689     }
 690     
 691     void MeltStates(State state) {
 692         bool ctx;
 693         BitArray targets;
 694         Symbol endOf;
 695         for (Action action = state.firstAction; action != null; action = action.next) {
 696             if (action.target.next != null) {
 697                 GetTargetStates(action, out targets, out endOf, out ctx);
 698                 Melted melt = StateWithSet(targets);
 699                 if (melt == null) {
 700                     State s = NewState(); s.endOf = endOf; s.ctx = ctx;
 701                     for (Target targ = action.target; targ != null; targ = targ.next)
 702                         s.MeltWith(targ.state);
 703                     MakeUnique(s);
 704                     melt = NewMelted(targets, s);
 705                 }
 706                 action.target.next = null;
 707                 action.target.state = melt.state;
 708             }
 709         }
 710     }
 711     
 712     void FindCtxStates() {
 713         for (State state = firstState; state != null; state = state.next)
 714             for (Action a = state.firstAction; a != null; a = a.next)
 715                 if (a.tc == Node.contextTrans) a.target.state.ctx = true;
 716     }
 717     
 718     public void MakeDeterministic() {
 719         State state;
 720         lastSimState = lastState.nr;
 721         maxStates = 2 * lastSimState; // heuristic for set size in Melted.set
 722         FindCtxStates();
 723         for (state = firstState; state != null; state = state.next)
 724             MakeUnique(state);
 725         for (state = firstState; state != null; state = state.next)
 726             MeltStates(state);
 727         DeleteRedundantStates();
 728         CombineShifts();
 729     }
 730     
 731     public void PrintStates() {
 732         trace.WriteLine();
 733         trace.WriteLine("---------- states ----------");
 734         for (State state = firstState; state != null; state = state.next) {
 735             bool first = true;
 736             if (state.endOf == null) trace.Write("               ");
 737             else trace.Write("E({0,12})", tab.Name(state.endOf.name));
 738             trace.Write("{0,3}:", state.nr);
 739             if (state.firstAction == null) trace.WriteLine();
 740             for (Action action = state.firstAction; action != null; action = action.next) {
 741                 if (first) {trace.Write(" "); first = false;} else trace.Write("                    ");
 742                 if (action.typ == Node.clas) trace.Write(((CharClass)tab.classes[action.sym]).name);
 743                 else trace.Write("{0, 3}", Ch(action.sym));
 744                 for (Target targ = action.target; targ != null; targ = targ.next)
 745                     trace.Write(" {0, 3}", targ.state.nr);
 746                 if (action.tc == Node.contextTrans) trace.WriteLine(" context"); else trace.WriteLine();
 747             }
 748         }
 749         trace.WriteLine();
 750         trace.WriteLine("---------- character classes ----------");
 751         tab.WriteCharClasses();
 752     }
 753     
 754 //---------------------------- actions --------------------------------
 755 
 756     public Action FindAction(State state, char ch) {
 757         for (Action a = state.firstAction; a != null; a = a.next)
 758             if (a.typ == Node.chr && ch == a.sym) return a;
 759             else if (a.typ == Node.clas) {
 760                 CharSet s = tab.CharClassSet(a.sym);
 761                 if (s[ch]) return a;
 762             }
 763         return null;
 764     }
 765     
 766     public void GetTargetStates(Action a, out BitArray targets, out Symbol endOf, out bool ctx) { 
 767         // compute the set of target states
 768         targets = new BitArray(maxStates); endOf = null;
 769         ctx = false;
 770         for (Target t = a.target; t != null; t = t.next) {
 771             int stateNr = t.state.nr;
 772             if (stateNr <= lastSimState) targets[stateNr] = true;
 773             else targets.Or(MeltedSet(stateNr));
 774             if (t.state.endOf != null)
 775                 if (endOf == null || endOf == t.state.endOf)
 776                     endOf = t.state.endOf;
 777                 else
 778                     errors.SemErr("Tokens " + endOf.name + " and " + t.state.endOf.name + " cannot be distinguished");
 779             if (t.state.ctx) {
 780                 ctx = true;
 781                 // The following check seems to be unnecessary. It reported an error
 782                 // if a symbol + context was the prefix of another symbol, e.g.
 783                 //   s1 = "a" "b" "c".
 784                 //   s2 = "a" CONTEXT("b").
 785                 // But this is ok.
 786                 // if (t.state.endOf != null) {
 787                 //   Console.WriteLine("Ambiguous context clause");
 788                 //     errors.count++;
 789                 // }
 790             }
 791         }
 792     }
 793     
 794 //------------------------- melted states ------------------------------
 795 
 796     Melted firstMelted;    // head of melted state list
 797     
 798     Melted NewMelted(BitArray set, State state) {
 799         Melted m = new Melted(set, state);
 800         m.next = firstMelted; firstMelted = m;
 801         return m;
 802     }
 803     
 804     BitArray MeltedSet(int nr) {
 805         Melted m = firstMelted;
 806         while (m != null) {
 807             if (m.state.nr == nr) return m.set; else m = m.next;
 808         }
 809         throw new FatalError("compiler error in Melted.Set");
 810     }
 811 
 812     Melted StateWithSet(BitArray s) {
 813         for (Melted m = firstMelted; m != null; m = m.next)
 814             if (Sets.Equals(s, m.set)) return m;
 815         return null;
 816     }
 817 
 818 //------------------------ comments --------------------------------
 819 
 820     public Comment firstComment;    // list of comments
 821 
 822     string CommentStr(Node p) {
 823         StringBuilder s = new StringBuilder();
 824         while (p != null) {
 825             if (p.typ == Node.chr) {
 826                 s.Append((char)p.val);
 827             } else if (p.typ == Node.clas) {
 828                 CharSet set = tab.CharClassSet(p.val);
 829                 if (set.Elements() != 1) parser.SemErr("character set contains more than 1 character");
 830                 s.Append((char)set.First());
 831             } else parser.SemErr("comment delimiters may not be structured");
 832             p = p.next;
 833         }
 834         if (s.Length == 0 || s.Length > 2) {
 835             parser.SemErr("comment delimiters must be 1 or 2 characters long");
 836             s = new StringBuilder("?");
 837         }
 838         return s.ToString();
 839     }
 840     
 841     public void NewComment(Node from, Node to, bool nested) {
 842         Comment c = new Comment(CommentStr(from), CommentStr(to), nested);
 843         c.next = firstComment; firstComment = c;
 844     }
 845 
 846 
 847 //------------------------ scanner generation ----------------------
 848 
 849     void GenComBody(Comment com) {
 850         gen.WriteLine(  "\t\t\tfor(;;) {");
 851         gen.Write    (  "\t\t\t\tif ({0}) ", ChCond(com.stop[0])); gen.WriteLine("{");
 852         if (com.stop.Length == 1) {
 853             gen.WriteLine("\t\t\t\t\tlevel--;");
 854             gen.WriteLine("\t\t\t\t\tif (level == 0) { oldEols = line - line0; NextCh(); return true; }");
 855             gen.WriteLine("\t\t\t\t\tNextCh();");
 856         } else {
 857             gen.WriteLine("\t\t\t\t\tNextCh();");
 858             gen.WriteLine("\t\t\t\t\tif ({0}) {{", ChCond(com.stop[1]));
 859             gen.WriteLine("\t\t\t\t\t\tlevel--;");
 860             gen.WriteLine("\t\t\t\t\t\tif (level == 0) { oldEols = line - line0; NextCh(); return true; }");
 861             gen.WriteLine("\t\t\t\t\t\tNextCh();");
 862             gen.WriteLine("\t\t\t\t\t}");
 863         }
 864         if (com.nested) {
 865             gen.Write    ("\t\t\t\t}"); gen.Write(" else if ({0}) ", ChCond(com.start[0])); gen.WriteLine("{");
 866             if (com.start.Length == 1)
 867                 gen.WriteLine("\t\t\t\t\tlevel++; NextCh();");
 868             else {
 869                 gen.WriteLine("\t\t\t\t\tNextCh();");
 870                 gen.Write    ("\t\t\t\t\tif ({0}) ", ChCond(com.start[1])); gen.WriteLine("{");
 871                 gen.WriteLine("\t\t\t\t\t\tlevel++; NextCh();");
 872                 gen.WriteLine("\t\t\t\t\t}");
 873             }
 874         }
 875         gen.WriteLine(    "\t\t\t\t} else if (ch == Buffer.EOF) return false;");
 876         gen.WriteLine(    "\t\t\t\telse NextCh();");
 877         gen.WriteLine(    "\t\t\t}");
 878     }
 879     
 880     void GenComment(Comment com, int i) {
 881         gen.WriteLine();
 882         gen.Write    ("\tbool Comment{0}() ", i); gen.WriteLine("{");
 883         gen.WriteLine("\t\tint level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;");
 884         if (com.start.Length == 1) {
 885             gen.WriteLine("\t\tNextCh();");
 886             GenComBody(com);
 887         } else {
 888             gen.WriteLine("\t\tNextCh();");
 889             gen.Write    ("\t\tif ({0}) ", ChCond(com.start[1])); gen.WriteLine("{");
 890             gen.WriteLine("\t\t\tNextCh();");
 891             GenComBody(com);
 892             gen.WriteLine("\t\t} else {");
 893             gen.WriteLine("\t\t\tbuffer.Pos = pos0; NextCh(); line = line0; col = col0; charPos = charPos0;");
 894             gen.WriteLine("\t\t}");
 895             gen.WriteLine("\t\treturn false;");
 896         }
 897         gen.WriteLine("\t}");
 898     }
 899     
 900     string SymName(Symbol sym) {
 901         if (Char.IsLetter(sym.name[0])) { // real name value is stored in Tab.literals
 902             foreach (DictionaryEntry e in tab.literals)
 903                 if ((Symbol)e.Value == sym) return (string)e.Key;
 904         }
 905         return sym.name;
 906     }
 907     
 908     void GenLiterals () {
 909         if (ignoreCase) {
 910             gen.WriteLine("\t\tswitch (t.val.ToLower()) {");
 911         } else {
 912             gen.WriteLine("\t\tswitch (t.val) {");
 913         }
 914         foreach (IList ts in new IList[] { tab.terminals, tab.pragmas }) {
 915             foreach (Symbol sym in ts) {
 916                 if (sym.tokenKind == Symbol.litToken) {
 917                     string name = SymName(sym);
 918                     if (ignoreCase) name = name.ToLower();
 919                     // sym.name stores literals with quotes, e.g. "\"Literal\""
 920                     gen.WriteLine("\t\t\tcase {0}: t.kind = {1}; break;", name, sym.n);
 921                 }
 922             }
 923         }
 924         gen.WriteLine("\t\t\tdefault: break;");
 925         gen.Write("\t\t}");
 926     }
 927     
 928     void WriteState(State state) {
 929         Symbol endOf = state.endOf;
 930         gen.WriteLine("\t\t\tcase {0}:", state.nr);
 931         if (endOf != null && state.firstAction != null) {
 932             gen.WriteLine("\t\t\t\trecEnd = pos; recKind = {0};", endOf.n);
 933         }
 934         bool ctxEnd = state.ctx;
 935         for (Action action = state.firstAction; action != null; action = action.next) {
 936             if (action == state.firstAction) gen.Write("\t\t\t\tif (");
 937             else gen.Write("\t\t\t\telse if (");
 938             if (action.typ == Node.chr) gen.Write(ChCond((char)action.sym));
 939             else PutRange(tab.CharClassSet(action.sym));
 940             gen.Write(") {");
 941             if (action.tc == Node.contextTrans) {
 942                 gen.Write("apx++; "); ctxEnd = false;
 943             } else if (state.ctx)
 944                 gen.Write("apx = 0; ");
 945             gen.Write("AddCh(); goto case {0};", action.target.state.nr);
 946             gen.WriteLine("}");
 947         }
 948         if (state.firstAction == null)
 949             gen.Write("\t\t\t\t{");
 950         else
 951             gen.Write("\t\t\t\telse {");
 952         if (ctxEnd) { // final context state: cut appendix
 953             gen.WriteLine();
 954             gen.WriteLine("\t\t\t\t\ttlen -= apx;");
 955             gen.WriteLine("\t\t\t\t\tSetScannerBehindT();");
 956             gen.Write("\t\t\t\t\t");
 957         }
 958         if (endOf == null) {
 959             gen.WriteLine("goto case 0;}");
 960         } else {
 961             gen.Write("t.kind = {0}; ", endOf.n);
 962             if (endOf.tokenKind == Symbol.classLitToken) {
 963                 gen.WriteLine("t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}");
 964             } else {
 965                 gen.WriteLine("break;}");
 966             }
 967         }
 968     }
 969     
 970     void WriteStartTab() {
 971         for (Action action = firstState.firstAction; action != null; action = action.next) {
 972             int targetState = action.target.state.nr;
 973             if (action.typ == Node.chr) {
 974                 gen.WriteLine("\t\tstart[" + action.sym + "] = " + targetState + "; ");
 975             } else {
 976                 CharSet s = tab.CharClassSet(action.sym);
 977                 for (CharSet.Range r = s.head; r != null; r = r.next) {
 978                     gen.WriteLine("\t\tfor (int i = " + r.from + "; i <= " + r.to + "; ++i) start[i] = " + targetState + ";");
 979                 }
 980             }
 981         }
 982         gen.WriteLine("\t\tstart[Buffer.EOF] = -1;");
 983     }
 984 
 985     public void WriteScanner() {
 986         Generator g = new Generator(tab);
 987         fram = g.OpenFrame("Scanner.frame");
 988         gen = g.OpenGen("Scanner.cs");
 989         if (dirtyDFA) MakeDeterministic();
 990 
 991         g.GenCopyright();
 992         g.SkipFramePart("-->begin");
 993 
 994         g.CopyFramePart("-->namespace");
 995         if (tab.nsName != null && tab.nsName.Length > 0) {
 996             gen.Write("namespace ");
 997             gen.Write(tab.nsName);
 998             gen.Write(" {");
 999         }
1000         g.CopyFramePart("-->declarations");
1001         gen.WriteLine("\tconst int maxT = {0};", tab.terminals.Count - 1);
1002         gen.WriteLine("\tconst int noSym = {0};", tab.noSym.n);
1003         if (ignoreCase)
1004             gen.Write("\tchar valCh;       // current input character (for token.val)");
1005         g.CopyFramePart("-->initialization");
1006         WriteStartTab();
1007         g.CopyFramePart("-->casing1");
1008         if (ignoreCase) {
1009             gen.WriteLine("\t\tif (ch != Buffer.EOF) {");
1010             gen.WriteLine("\t\t\tvalCh = (char) ch;");
1011             gen.WriteLine("\t\t\tch = char.ToLower((char) ch);");
1012             gen.WriteLine("\t\t}");
1013         }
1014         g.CopyFramePart("-->casing2");
1015         gen.Write("\t\t\ttval[tlen++] = ");
1016         if (ignoreCase) gen.Write("valCh;"); else gen.Write("(char) ch;");
1017         g.CopyFramePart("-->comments");
1018         Comment com = firstComment; 
1019         int comIdx = 0;
1020         while (com != null) {
1021             GenComment(com, comIdx);
1022             com = com.next; comIdx++;
1023         }
1024         g.CopyFramePart("-->literals"); GenLiterals();
1025         g.CopyFramePart("-->scan1");
1026         gen.Write("\t\t\t");
1027         if (tab.ignored.Elements() > 0) { PutRange(tab.ignored); } else { gen.Write("false"); }
1028         g.CopyFramePart("-->scan2");
1029         if (firstComment != null) {
1030             gen.Write("\t\tif (");
1031             com = firstComment; comIdx = 0;
1032             while (com != null) {
1033                 gen.Write(ChCond(com.start[0]));
1034                 gen.Write(" && Comment{0}()", comIdx);
1035                 if (com.next != null) gen.Write(" ||");
1036                 com = com.next; comIdx++;
1037             }
1038             gen.Write(") return NextToken();");
1039         }
1040         if (hasCtxMoves) { gen.WriteLine(); gen.Write("\t\tint apx = 0;"); } /* pdt */
1041         g.CopyFramePart("-->scan3");
1042         for (State state = firstState.next; state != null; state = state.next)
1043             WriteState(state);
1044         g.CopyFramePart(null);
1045         if (tab.nsName != null && tab.nsName.Length > 0) gen.Write("}");
1046         gen.Close();
1047     }
1048     
1049     public DFA (Parser parser) {
1050         this.parser = parser;
1051         tab = parser.tab;
1052         errors = parser.errors;
1053         trace = parser.trace;
1054         firstState = null; lastState = null; lastStateNr = -1;
1055         firstState = NewState();
1056         firstMelted = null; firstComment = null;
1057         ignoreCase = false;
1058         dirtyDFA = false;
1059         hasCtxMoves = false;
1060     }
1061     
1062 } // end DFA
1063 
1064 } // end namespace

 

CocoSourcesCS 2

标签:

原文地址:http://www.cnblogs.com/endv/p/4598820.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!