2007-10-22 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System / System.Text.RegularExpressions / compiler.cs
index 8640b5d7392e4e41af0d329f47e7f5be7bd03e1d..9173edcd5a42c04f3be4fc77e1da1894f927154e 100644 (file)
-//\r
-// assembly:   System\r
-// namespace:  System.Text.RegularExpressions\r
-// file:       compiler.cs\r
-//\r
-// author:     Dan Lewis (dlewis@gmx.co.uk)\r
-//             (c) 2002\r
-\r
-using System;\r
-using System.Collections;\r
-\r
-namespace System.Text.RegularExpressions {\r
-       abstract class LinkRef {\r
-               // empty\r
-       }\r
-               \r
-       interface ICompiler {\r
-               void Reset ();\r
-               IMachineFactory GetMachineFactory ();\r
-\r
-               // instruction emission\r
-\r
-               void EmitFalse ();\r
-               void EmitTrue ();\r
-\r
-               // character matching\r
-\r
-               void EmitCharacter (char c, bool negate, bool ignore, bool reverse);\r
-               void EmitCategory (Category cat, bool negate, bool reverse);\r
-               void EmitRange (char lo, char hi, bool negate, bool ignore, bool reverse);\r
-               void EmitSet (char lo, BitArray set, bool negate, bool ignore, bool reverse);\r
-\r
-               // other operators\r
-\r
-               void EmitString (string str, bool ignore, bool reverse);\r
-               void EmitPosition (Position pos);\r
-               void EmitOpen (int gid);\r
-               void EmitClose (int gid);\r
-               void EmitBalance (int gid, int balance);\r
-               void EmitReference (int gid, bool ignore, bool reverse);\r
-\r
-               // constructs\r
-\r
-               void EmitIfDefined (int gid, LinkRef tail);\r
-               void EmitSub (LinkRef tail);\r
-               void EmitTest (LinkRef yes, LinkRef tail);\r
-               void EmitBranch (LinkRef next);\r
-               void EmitJump (LinkRef target);\r
-               void EmitRepeat (int min, int max, bool lazy, LinkRef until);\r
-               void EmitUntil (LinkRef repeat);\r
-               void EmitIn (LinkRef tail);\r
-               void EmitInfo (int count, int min, int max);\r
-               void EmitFastRepeat (int min, int max, bool lazy, LinkRef tail);\r
-               void EmitAnchor (bool reverse, int offset, LinkRef tail);\r
-\r
-               // event for the CILCompiler\r
-               void EmitBranchEnd();\r
-               void EmitAlternationEnd();\r
-\r
-               LinkRef NewLink ();\r
-               void ResolveLink (LinkRef link);\r
-       }\r
-\r
-       class InterpreterFactory : IMachineFactory {\r
-               public InterpreterFactory (ushort[] pattern) {\r
-                       this.pattern = pattern;\r
-               }\r
-               \r
-               public IMachine NewInstance () {\r
-                       return new Interpreter (pattern);\r
-               }\r
-\r
-               public int GroupCount {\r
-                       get { return pattern[0]; }\r
-               }\r
-\r
-               public IDictionary Mapping {\r
-                       get { return mapping; }\r
-                       set { mapping = value; }\r
-               }\r
-\r
-               private IDictionary mapping;\r
-               private ushort[] pattern;\r
-       }\r
-\r
-       class PatternCompiler : ICompiler {\r
-               public static ushort EncodeOp (OpCode op, OpFlags flags) {\r
-                       return (ushort)((int)op | ((int)flags & 0xff00));\r
-               }\r
-\r
-               public static void DecodeOp (ushort word, out OpCode op, out OpFlags flags) {\r
-                       op = (OpCode)(word & 0x00ff);\r
-                       flags = (OpFlags)(word & 0xff00);\r
-               }\r
-\r
-               public PatternCompiler () {\r
-                       pgm = new ArrayList ();\r
-               }\r
-\r
-               // ICompiler implementation\r
-\r
-               public void Reset () {\r
-                       pgm.Clear ();\r
-               }\r
-\r
-               public IMachineFactory GetMachineFactory () {\r
-                       ushort[] image = new ushort[pgm.Count];\r
-                       pgm.CopyTo (image);\r
-\r
-                       return new InterpreterFactory (image);\r
-               }\r
-\r
-               public void EmitFalse () {\r
-                       Emit (OpCode.False);\r
-               }\r
-\r
-               public void EmitTrue () {\r
-                       Emit (OpCode.True);\r
-               }\r
-\r
-               public void EmitCharacter (char c, bool negate, bool ignore, bool reverse) {\r
-                       Emit (OpCode.Character, MakeFlags (negate, ignore, reverse, false));\r
-\r
-                       if (ignore)\r
-                               c = Char.ToLower (c);\r
-\r
-                       Emit ((ushort)c);\r
-               }\r
-\r
-               public void EmitCategory (Category cat, bool negate, bool reverse) {\r
-                       Emit (OpCode.Category, MakeFlags (negate, false, reverse, false));\r
-                       Emit ((ushort)cat);\r
-               }\r
-\r
-               public void EmitRange (char lo, char hi, bool negate, bool ignore, bool reverse) {\r
-                       Emit (OpCode.Range, MakeFlags (negate, ignore, reverse, false));\r
-                       Emit ((ushort)lo);\r
-                       Emit ((ushort)hi);\r
-               }\r
-\r
-               public void EmitSet (char lo, BitArray set, bool negate, bool ignore, bool reverse) {\r
-                       Emit (OpCode.Set, MakeFlags (negate, ignore, reverse, false));\r
-                       Emit ((ushort)lo);\r
-\r
-                       int len = (set.Length + 0xf) >> 4;\r
-                       Emit ((ushort)len);\r
-\r
-                       int b = 0;\r
-                       while (len -- != 0) {\r
-                               ushort word = 0;\r
-                               for (int i = 0; i < 16; ++ i) {\r
-                                       if (b >= set.Length)\r
-                                               break;\r
-                               \r
-                                       if (set[b ++])\r
-                                               word |= (ushort)(1 << i);\r
-                               }\r
-\r
-                               Emit (word);\r
-                       }\r
-               }\r
-\r
-               public void EmitString (string str, bool ignore, bool reverse) {\r
-                       Emit (OpCode.String, MakeFlags (false, ignore, reverse, false));\r
-                       int len = str.Length;\r
-                       Emit ((ushort)len);\r
-\r
-                       if (ignore)\r
-                               str = str.ToLower ();\r
-                       \r
-                       for (int i = 0; i < len; ++ i)\r
-                               Emit ((ushort)str[i]);\r
-               }\r
-\r
-               public void EmitPosition (Position pos) {\r
-                       Emit (OpCode.Position, 0);\r
-                       Emit ((ushort)pos);\r
-               }\r
-\r
-               public void EmitOpen (int gid) {\r
-                       Emit (OpCode.Open);\r
-                       Emit ((ushort)gid);\r
-               }\r
-\r
-               public void EmitClose (int gid) {\r
-                       Emit (OpCode.Close);\r
-                       Emit ((ushort)gid);\r
-               }\r
-\r
-               public void EmitBalance (int gid, int balance) {\r
-                       Emit (OpCode.Balance);\r
-                       Emit ((ushort)gid);\r
-                       Emit ((ushort)balance);\r
-               }\r
-\r
-               public void EmitReference (int gid, bool ignore, bool reverse) {\r
-                       Emit (OpCode.Reference, MakeFlags (false, ignore, reverse, false));\r
-                       Emit ((ushort)gid);\r
-               }\r
-\r
-               public void EmitIfDefined (int gid, LinkRef tail) {\r
-                       BeginLink (tail);\r
-                       Emit (OpCode.IfDefined);\r
-                       EmitLink (tail);\r
-                       Emit ((ushort)gid);\r
-               }\r
-\r
-               public void EmitSub (LinkRef tail) {\r
-                       BeginLink (tail);\r
-                       Emit (OpCode.Sub);\r
-                       EmitLink (tail);\r
-               }\r
-\r
-               public void EmitTest (LinkRef yes, LinkRef tail) {\r
-                       BeginLink (yes);\r
-                       BeginLink (tail);\r
-                       Emit (OpCode.Test);\r
-                       EmitLink (yes);\r
-                       EmitLink (tail);\r
-               }\r
-\r
-               public void EmitBranch (LinkRef next) {\r
-                       BeginLink (next);\r
-                       Emit (OpCode.Branch, 0);\r
-                       EmitLink (next);\r
-               }\r
-\r
-               public void EmitJump (LinkRef target) {\r
-                       BeginLink (target);\r
-                       Emit (OpCode.Jump, 0);\r
-                       EmitLink (target);\r
-               }\r
-\r
-               public void EmitRepeat (int min, int max, bool lazy, LinkRef until) {\r
-                       BeginLink (until);\r
-                       Emit (OpCode.Repeat, MakeFlags (false, false, false, lazy));\r
-                       EmitLink (until);\r
-                       Emit ((ushort)min);\r
-                       Emit ((ushort)max);\r
-               }\r
-\r
-               public void EmitUntil (LinkRef repeat) {\r
-                       ResolveLink (repeat);\r
-                       Emit (OpCode.Until);\r
-               }\r
-\r
-               public void EmitFastRepeat (int min, int max, bool lazy, LinkRef tail) {\r
-                       BeginLink (tail);\r
-                       Emit (OpCode.FastRepeat, MakeFlags (false, false, false, lazy));\r
-                       EmitLink (tail);\r
-                       Emit ((ushort)min);\r
-                       Emit ((ushort)max);\r
-               }\r
-\r
-               public void EmitIn (LinkRef tail) {\r
-                       BeginLink (tail);\r
-                       Emit (OpCode.In);\r
-                       EmitLink (tail);\r
-               }\r
-\r
-               public void EmitAnchor (bool reverse, int offset, LinkRef tail) {\r
-                       BeginLink (tail);\r
-                       Emit (OpCode.Anchor, MakeFlags(false, false, reverse, false));\r
-                       EmitLink (tail);\r
-                       Emit ((ushort)offset);\r
-               }\r
-\r
-               public void EmitInfo (int count, int min, int max) {\r
-                       Emit (OpCode.Info);\r
-                       Emit ((ushort)count);\r
-                       Emit ((ushort)min);\r
-                       Emit ((ushort)max);\r
-               }\r
-\r
-               public LinkRef NewLink () {\r
-                       return new PatternLinkStack ();\r
-               }\r
-               \r
-               public void ResolveLink (LinkRef lref) {\r
-                       PatternLinkStack stack = (PatternLinkStack)lref;\r
-               \r
-                       while (stack.Pop ())\r
-                               pgm[stack.OffsetAddress] = (ushort)stack.GetOffset (CurrentAddress);\r
-               }\r
-\r
-               public void EmitBranchEnd(){}\r
-               public void EmitAlternationEnd(){}\r
-\r
-               // private members\r
-\r
-               private static OpFlags MakeFlags (bool negate, bool ignore, bool reverse, bool lazy) {\r
-                       OpFlags flags = 0;\r
-                       if (negate) flags |= OpFlags.Negate;\r
-                       if (ignore) flags |= OpFlags.IgnoreCase;\r
-                       if (reverse) flags |= OpFlags.RightToLeft;\r
-                       if (lazy) flags |= OpFlags.Lazy;\r
-\r
-                       return flags;\r
-               }\r
-               \r
-               private void Emit (OpCode op) {\r
-                       Emit (op, (OpFlags)0);\r
-               }\r
-\r
-               private void Emit (OpCode op, OpFlags flags) {\r
-                       Emit (EncodeOp (op, flags));\r
-               }\r
-\r
-               private void Emit (ushort word) {\r
-                       pgm.Add (word);\r
-               }\r
-\r
-               private int CurrentAddress {\r
-                       get { return pgm.Count; }\r
-               }\r
-\r
-               private void BeginLink (LinkRef lref) {\r
-                       PatternLinkStack stack = (PatternLinkStack)lref;\r
-                       stack.BaseAddress = CurrentAddress;\r
-               }\r
-\r
-               private void EmitLink (LinkRef lref) {\r
-                       PatternLinkStack stack = (PatternLinkStack)lref;\r
-                       stack.OffsetAddress = CurrentAddress;\r
-                       Emit ((ushort)0);       // placeholder\r
-                       stack.Push ();\r
-               }\r
-\r
-\r
-               private class PatternLinkStack : LinkStack {\r
-                       public PatternLinkStack () {\r
-                       }\r
-               \r
-                       public int BaseAddress {\r
-                               set { link.base_addr = value; }\r
-                       }\r
-\r
-                       public int OffsetAddress {\r
-                               get { return link.offset_addr; }\r
-                               set { link.offset_addr = value; }\r
-                       }\r
-\r
-                       public int GetOffset (int target_addr) {\r
-                               return target_addr - link.base_addr;\r
-                       }\r
-\r
-                       // LinkStack implementation\r
-\r
-                       protected override object GetCurrent () { return link; }\r
-                       protected override void SetCurrent (object l) { link = (Link)l; }\r
-\r
-                       private struct Link {\r
-                               public int base_addr;\r
-                               public int offset_addr;\r
-                       }\r
-\r
-                       Link link;\r
-               }\r
-\r
-               private ArrayList pgm;\r
-       }\r
-\r
-       abstract class LinkStack : LinkRef {\r
-               public LinkStack () {\r
-                       stack = new Stack ();\r
-               }\r
-\r
-               public void Push () {\r
-                       stack.Push (GetCurrent ());\r
-               }\r
-\r
-               public bool Pop () {\r
-                       if (stack.Count > 0) {\r
-                               SetCurrent (stack.Pop ());\r
-                               return true;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-               protected abstract object GetCurrent ();\r
-               protected abstract void SetCurrent (object l);\r
-\r
-               private Stack stack;\r
-       }\r
-\r
-       //Used by CILCompiler and Interpreter\r
-       internal struct Mark {\r
-               public int Start, End;\r
-               public int Previous;\r
-               \r
-               public bool IsDefined {\r
-                       get { return Start >= 0 && End >= 0; }\r
-               }\r
-               \r
-               public int Index {\r
-                       get { return Start < End ? Start : End; }\r
-               }\r
-               \r
-               public int Length {\r
-                       get { return Start < End ? End - Start : Start - End; }\r
-               }\r
-       }\r
-\r
-}\r
+//
+// assembly:   System
+// namespace:  System.Text.RegularExpressions
+// file:       compiler.cs
+//
+// author:     Dan Lewis (dlewis@gmx.co.uk)
+//             (c) 2002
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+
+namespace System.Text.RegularExpressions {
+       abstract class LinkRef {
+               // empty
+       }
+               
+       interface ICompiler {
+               void Reset ();
+               IMachineFactory GetMachineFactory ();
+
+               // instruction emission
+
+               void EmitFalse ();
+               void EmitTrue ();
+
+               // character matching
+
+               void EmitCharacter (char c, bool negate, bool ignore, bool reverse);
+               void EmitCategory (Category cat, bool negate, bool reverse);
+               void EmitNotCategory (Category cat, bool negate, bool reverse);
+               void EmitRange (char lo, char hi, bool negate, bool ignore, bool reverse);
+               void EmitSet (char lo, BitArray set, bool negate, bool ignore, bool reverse);
+
+               // other operators
+
+               void EmitString (string str, bool ignore, bool reverse);
+               void EmitPosition (Position pos);
+               void EmitOpen (int gid);
+               void EmitClose (int gid);
+               void EmitBalanceStart(int gid, int balance, bool capture,  LinkRef tail);
+               void EmitBalance ();
+               void EmitReference (int gid, bool ignore, bool reverse);
+
+               // constructs
+
+               void EmitIfDefined (int gid, LinkRef tail);
+               void EmitSub (LinkRef tail);
+               void EmitTest (LinkRef yes, LinkRef tail);
+               void EmitBranch (LinkRef next);
+               void EmitJump (LinkRef target);
+               void EmitRepeat (int min, int max, bool lazy, LinkRef until);
+               void EmitUntil (LinkRef repeat);
+               void EmitIn (LinkRef tail);
+               void EmitInfo (int count, int min, int max);
+               void EmitFastRepeat (int min, int max, bool lazy, LinkRef tail);
+               void EmitAnchor (bool reverse, int offset, LinkRef tail);
+
+               // event for the CILCompiler
+               void EmitBranchEnd();
+               void EmitAlternationEnd();
+
+               LinkRef NewLink ();
+               void ResolveLink (LinkRef link);
+       }
+
+       class InterpreterFactory : IMachineFactory {
+               public InterpreterFactory (ushort[] pattern) {
+                       this.pattern = pattern;
+               }
+               
+               public IMachine NewInstance () {
+                       return new Interpreter (pattern);
+               }
+
+               public int GroupCount {
+                       get { return pattern[1]; }
+               }
+
+               public IDictionary Mapping {
+                       get { return mapping; }
+                       set { mapping = value; }
+               }
+
+               private IDictionary mapping;
+               private ushort[] pattern;
+       }
+
+       class PatternCompiler : ICompiler {
+               public static ushort EncodeOp (OpCode op, OpFlags flags) {
+                       return (ushort)((int)op | ((int)flags & 0xff00));
+               }
+
+               public static void DecodeOp (ushort word, out OpCode op, out OpFlags flags) {
+                       op = (OpCode)(word & 0x00ff);
+                       flags = (OpFlags)(word & 0xff00);
+               }
+
+               public PatternCompiler () {
+                       pgm = new ArrayList ();
+               }
+
+               // ICompiler implementation
+
+               public void Reset () {
+                       pgm.Clear ();
+               }
+
+               public IMachineFactory GetMachineFactory () {
+                       ushort[] image = new ushort[pgm.Count];
+                       pgm.CopyTo (image);
+
+                       return new InterpreterFactory (image);
+               }
+
+               public void EmitFalse () {
+                       Emit (OpCode.False);
+               }
+
+               public void EmitTrue () {
+                       Emit (OpCode.True);
+               }
+
+               void EmitCount (int count)
+               {
+                       uint ucount = (uint) count;
+                       Emit ((ushort) (ucount & 0xFFFF)); // lo 16bits
+                       Emit ((ushort) (ucount >> 16));    // hi
+               }
+
+               public void EmitCharacter (char c, bool negate, bool ignore, bool reverse) {
+                       Emit (OpCode.Character, MakeFlags (negate, ignore, reverse, false));
+
+                       if (ignore)
+                               c = Char.ToLower (c);
+
+                       Emit ((ushort)c);
+               }
+
+               public void EmitCategory (Category cat, bool negate, bool reverse) {
+                       Emit (OpCode.Category, MakeFlags (negate, false, reverse, false));
+                       Emit ((ushort)cat);
+               }
+
+               public void EmitNotCategory (Category cat, bool negate, bool reverse) {
+                       Emit (OpCode.NotCategory, MakeFlags (negate, false, reverse, false));
+                       Emit ((ushort)cat);
+               }
+
+               public void EmitRange (char lo, char hi, bool negate, bool ignore, bool reverse) {
+                       Emit (OpCode.Range, MakeFlags (negate, ignore, reverse, false));
+                       Emit ((ushort)lo);
+                       Emit ((ushort)hi);
+               }
+
+               public void EmitSet (char lo, BitArray set, bool negate, bool ignore, bool reverse) {
+                       Emit (OpCode.Set, MakeFlags (negate, ignore, reverse, false));
+                       Emit ((ushort)lo);
+
+                       int len = (set.Length + 0xf) >> 4;
+                       Emit ((ushort)len);
+
+                       int b = 0;
+                       while (len -- != 0) {
+                               ushort word = 0;
+                               for (int i = 0; i < 16; ++ i) {
+                                       if (b >= set.Length)
+                                               break;
+                               
+                                       if (set[b ++])
+                                               word |= (ushort)(1 << i);
+                               }
+
+                               Emit (word);
+                       }
+               }
+
+               public void EmitString (string str, bool ignore, bool reverse) {
+                       Emit (OpCode.String, MakeFlags (false, ignore, reverse, false));
+                       int len = str.Length;
+                       Emit ((ushort)len);
+
+                       if (ignore)
+                               str = str.ToLower ();
+                       
+                       for (int i = 0; i < len; ++ i)
+                               Emit ((ushort)str[i]);
+               }
+
+               public void EmitPosition (Position pos) {
+                       Emit (OpCode.Position, 0);
+                       Emit ((ushort)pos);
+               }
+
+               public void EmitOpen (int gid) {
+                       Emit (OpCode.Open);
+                       Emit ((ushort)gid);
+               }
+
+               public void EmitClose (int gid) {
+                       Emit (OpCode.Close);
+                       Emit ((ushort)gid);
+               }
+
+              
+
+               public void EmitBalanceStart (int gid, int balance, bool capture, LinkRef tail) {
+                       BeginLink (tail);
+                       Emit (OpCode.BalanceStart);
+                       Emit ((ushort)gid);
+                       Emit ((ushort)balance);
+                       Emit ((ushort)(capture ? 1 : 0));
+                       EmitLink (tail);
+               }
+
+               public void EmitBalance () {
+                       Emit (OpCode.Balance);
+               }
+
+               public void EmitReference (int gid, bool ignore, bool reverse) {
+                       Emit (OpCode.Reference, MakeFlags (false, ignore, reverse, false));
+                       Emit ((ushort)gid);
+               }
+
+               public void EmitIfDefined (int gid, LinkRef tail) {
+                       BeginLink (tail);
+                       Emit (OpCode.IfDefined);
+                       EmitLink (tail);
+                       Emit ((ushort)gid);
+               }
+
+               public void EmitSub (LinkRef tail) {
+                       BeginLink (tail);
+                       Emit (OpCode.Sub);
+                       EmitLink (tail);
+               }
+
+               public void EmitTest (LinkRef yes, LinkRef tail) {
+                       BeginLink (yes);
+                       BeginLink (tail);
+                       Emit (OpCode.Test);
+                       EmitLink (yes);
+                       EmitLink (tail);
+               }
+
+               public void EmitBranch (LinkRef next) {
+                       BeginLink (next);
+                       Emit (OpCode.Branch, 0);
+                       EmitLink (next);
+               }
+
+               public void EmitJump (LinkRef target) {
+                       BeginLink (target);
+                       Emit (OpCode.Jump, 0);
+                       EmitLink (target);
+               }
+
+               public void EmitRepeat (int min, int max, bool lazy, LinkRef until) {
+                       BeginLink (until);
+                       Emit (OpCode.Repeat, MakeFlags (false, false, false, lazy));
+                       EmitLink (until);
+                       EmitCount (min);
+                       EmitCount (max);
+               }
+
+               public void EmitUntil (LinkRef repeat) {
+                       ResolveLink (repeat);
+                       Emit (OpCode.Until);
+               }
+
+               public void EmitFastRepeat (int min, int max, bool lazy, LinkRef tail) {
+                       BeginLink (tail);
+                       Emit (OpCode.FastRepeat, MakeFlags (false, false, false, lazy));
+                       EmitLink (tail);
+                       EmitCount (min);
+                       EmitCount (max);
+               }
+
+               public void EmitIn (LinkRef tail) {
+                       BeginLink (tail);
+                       Emit (OpCode.In);
+                       EmitLink (tail);
+               }
+
+               public void EmitAnchor (bool reverse, int offset, LinkRef tail) {
+                       BeginLink (tail);
+                       Emit (OpCode.Anchor, MakeFlags(false, false, reverse, false));
+                       EmitLink (tail);
+                       Emit ((ushort)offset);
+               }
+
+               public void EmitInfo (int count, int min, int max) {
+                       Emit (OpCode.Info);
+                       EmitCount (count);
+                       EmitCount (min);
+                       EmitCount (max);
+               }
+
+               public LinkRef NewLink () {
+                       return new PatternLinkStack ();
+               }
+               
+               public void ResolveLink (LinkRef lref) {
+                       PatternLinkStack stack = (PatternLinkStack)lref;
+               
+                       while (stack.Pop ())
+                               pgm[stack.OffsetAddress] = (ushort)stack.GetOffset (CurrentAddress);
+               }
+
+               public void EmitBranchEnd(){}
+               public void EmitAlternationEnd(){}
+
+               // private members
+
+               private static OpFlags MakeFlags (bool negate, bool ignore, bool reverse, bool lazy) {
+                       OpFlags flags = 0;
+                       if (negate) flags |= OpFlags.Negate;
+                       if (ignore) flags |= OpFlags.IgnoreCase;
+                       if (reverse) flags |= OpFlags.RightToLeft;
+                       if (lazy) flags |= OpFlags.Lazy;
+
+                       return flags;
+               }
+               
+               private void Emit (OpCode op) {
+                       Emit (op, (OpFlags)0);
+               }
+
+               private void Emit (OpCode op, OpFlags flags) {
+                       Emit (EncodeOp (op, flags));
+               }
+
+               private void Emit (ushort word) {
+                       pgm.Add (word);
+               }
+
+               private int CurrentAddress {
+                       get { return pgm.Count; }
+               }
+
+               private void BeginLink (LinkRef lref) {
+                       PatternLinkStack stack = (PatternLinkStack)lref;
+                       stack.BaseAddress = CurrentAddress;
+               }
+
+               private void EmitLink (LinkRef lref) {
+                       PatternLinkStack stack = (PatternLinkStack)lref;
+                       stack.OffsetAddress = CurrentAddress;
+                       Emit ((ushort)0);       // placeholder
+                       stack.Push ();
+               }
+
+
+               private class PatternLinkStack : LinkStack {
+                       public PatternLinkStack () {
+                       }
+               
+                       public int BaseAddress {
+                               set { link.base_addr = value; }
+                       }
+
+                       public int OffsetAddress {
+                               get { return link.offset_addr; }
+                               set { link.offset_addr = value; }
+                       }
+
+                       public int GetOffset (int target_addr) {
+                               return target_addr - link.base_addr;
+                       }
+
+                       // LinkStack implementation
+
+                       protected override object GetCurrent () { return link; }
+                       protected override void SetCurrent (object l) { link = (Link)l; }
+
+                       private struct Link {
+                               public int base_addr;
+                               public int offset_addr;
+                       }
+
+                       Link link;
+               }
+
+               private ArrayList pgm;
+       }
+
+       abstract class LinkStack : LinkRef {
+               public LinkStack () {
+                       stack = new Stack ();
+               }
+
+               public void Push () {
+                       stack.Push (GetCurrent ());
+               }
+
+               public bool Pop () {
+                       if (stack.Count > 0) {
+                               SetCurrent (stack.Pop ());
+                               return true;
+                       }
+
+                       return false;
+               }
+
+               protected abstract object GetCurrent ();
+               protected abstract void SetCurrent (object l);
+
+               private Stack stack;
+       }
+
+       //Used by CILCompiler and Interpreter
+       internal struct Mark {
+               public int Start, End;
+               public int Previous;
+               
+               public bool IsDefined {
+                       get { return Start >= 0 && End >= 0; }
+               }
+               
+               public int Index {
+                       get { return Start < End ? Start : End; }
+               }
+               
+               public int Length {
+                       get { return Start < End ? End - Start : Start - End; }
+               }
+       }
+
+}