Author: lupus
Date: 2008-02-13 06:36:07 -0500 (Wed, 13 Feb 2008)
New Revision: 95565

Modified:
   trunk/mcs/class/System/System.Text.RegularExpressions/ChangeLog
   trunk/mcs/class/System/System.Text.RegularExpressions/RxCompiler.cs
   trunk/mcs/class/System/System.Text.RegularExpressions/RxInterpreter.cs
   trunk/mcs/class/System/System.Text.RegularExpressions/RxOp.cs
Log:


Wed Feb 13 13:18:12 CET 2008 Paolo Molaro <[EMAIL PROTECTED]>

        * RxCompiler.cs, RxInterpreter.cs, RxOp.cs: unicode categories and
        some grouping/capture support.



Modified: trunk/mcs/class/System/System.Text.RegularExpressions/ChangeLog
===================================================================
--- trunk/mcs/class/System/System.Text.RegularExpressions/ChangeLog     
2008-02-13 10:11:06 UTC (rev 95564)
+++ trunk/mcs/class/System/System.Text.RegularExpressions/ChangeLog     
2008-02-13 11:36:07 UTC (rev 95565)
@@ -1,4 +1,9 @@
 
+Wed Feb 13 13:18:12 CET 2008 Paolo Molaro <[EMAIL PROTECTED]>
+
+       * RxCompiler.cs, RxInterpreter.cs, RxOp.cs: unicode categories and
+       some grouping/capture support.
+
 Tue Feb 12 19:16:49 CET 2008 Paolo Molaro <[EMAIL PROTECTED]>
 
        * RxCompiler.cs, RxInterpreter.cs, RxOp.cs: experimental new

Modified: trunk/mcs/class/System/System.Text.RegularExpressions/RxCompiler.cs
===================================================================
--- trunk/mcs/class/System/System.Text.RegularExpressions/RxCompiler.cs 
2008-02-13 10:11:06 UTC (rev 95564)
+++ trunk/mcs/class/System/System.Text.RegularExpressions/RxCompiler.cs 
2008-02-13 11:36:07 UTC (rev 95565)
@@ -1,5 +1,6 @@
 using System;
 using System.Collections;
+using System.Globalization;
 
 namespace System.Text.RegularExpressions {
 
@@ -141,23 +142,271 @@
                        }
                }
 
+               void EmitUniCat (UnicodeCategory cat, int offset)
+               {
+                       Emit ((RxOp)((int)RxOp.CategoryUnicode + offset));
+                       Emit ((byte)cat);
+               }
+
                public void EmitCategory (Category cat, bool negate, bool 
reverse)
                {
-                       if (negate | reverse)
-                               throw new NotSupportedException ();
+                       int offset = 0;
+                       if (negate)
+                               offset += 1;
+                       if (reverse)
+                               offset += 2;
                        switch (cat) {
                        case Category.Any:
-                               Emit (RxOp.CategoryAny);
+                       case Category.EcmaAny:
+                               Emit ((RxOp)((int)RxOp.CategoryAny + offset));
                                break;
+                       case Category.Word:
+                               Emit ((RxOp)((int)RxOp.CategoryWord + offset));
+                               break;
+                       case Category.Digit:
+                               Emit ((RxOp)((int)RxOp.CategoryDigit + offset));
+                               break;
+                       case Category.WhiteSpace:
+                               Emit ((RxOp)((int)RxOp.CategoryWhiteSpace + 
offset));
+                               break;
+                       case Category.EcmaWord:
+                               Emit ((RxOp)((int)RxOp.CategoryEcmaWord + 
offset));
+                               break;
+                       case Category.EcmaDigit:
+                               Emit ((RxOp)((int)RxOp.CategoryEcmaDigit + 
offset));
+                               break;
+                       case Category.EcmaWhiteSpace:
+                               Emit ((RxOp)((int)RxOp.CategoryEcmaWhiteSpace + 
offset));
+                               break;
+                       case Category.UnicodeSpecials:
+                               Emit ((RxOp)((int)RxOp.CategoryUnicodeSpecials 
+ offset));
+                               break;
+                       // Unicode categories...
+                       // letter
+                       case Category.UnicodeLu: EmitUniCat 
(UnicodeCategory.UppercaseLetter, offset); break;
+                       case Category.UnicodeLl: EmitUniCat 
(UnicodeCategory.LowercaseLetter, offset); break;
+                       case Category.UnicodeLt: EmitUniCat 
(UnicodeCategory.TitlecaseLetter, offset); break;
+                       case Category.UnicodeLm: EmitUniCat 
(UnicodeCategory.ModifierLetter, offset); break;
+                       case Category.UnicodeLo: EmitUniCat 
(UnicodeCategory.OtherLetter, offset); break;
+                       // mark
+                       case Category.UnicodeMn: EmitUniCat 
(UnicodeCategory.NonSpacingMark, offset); break;
+                       case Category.UnicodeMe: EmitUniCat 
(UnicodeCategory.EnclosingMark, offset); break;
+                       case Category.UnicodeMc: EmitUniCat 
(UnicodeCategory.SpacingCombiningMark, offset); break;
+                       case Category.UnicodeNd: EmitUniCat 
(UnicodeCategory.DecimalDigitNumber, offset); break;
+                       // number
+                       case Category.UnicodeNl: EmitUniCat 
(UnicodeCategory.LetterNumber, offset); break;
+                       case Category.UnicodeNo: EmitUniCat 
(UnicodeCategory.OtherNumber, offset); break;
+                       // separator
+                       case Category.UnicodeZs: EmitUniCat 
(UnicodeCategory.SpaceSeparator, offset); break;
+                       case Category.UnicodeZl: EmitUniCat 
(UnicodeCategory.LineSeparator, offset); break;
+                       case Category.UnicodeZp: EmitUniCat 
(UnicodeCategory.ParagraphSeparator, offset); break;
+                       // punctuation
+                       case Category.UnicodePd: EmitUniCat 
(UnicodeCategory.DashPunctuation, offset); break;
+                       case Category.UnicodePs: EmitUniCat 
(UnicodeCategory.OpenPunctuation, offset); break;
+                       case Category.UnicodePi: EmitUniCat 
(UnicodeCategory.InitialQuotePunctuation, offset); break;
+                       case Category.UnicodePe: EmitUniCat 
(UnicodeCategory.ClosePunctuation, offset); break;
+                       case Category.UnicodePf: EmitUniCat 
(UnicodeCategory.FinalQuotePunctuation, offset); break;
+                       case Category.UnicodePc: EmitUniCat 
(UnicodeCategory.ConnectorPunctuation, offset); break;
+                       case Category.UnicodePo: EmitUniCat 
(UnicodeCategory.OtherPunctuation, offset); break;
+                       // symbol
+                       case Category.UnicodeSm: EmitUniCat 
(UnicodeCategory.MathSymbol, offset); break;
+                       case Category.UnicodeSc: EmitUniCat 
(UnicodeCategory.CurrencySymbol, offset); break;
+                       case Category.UnicodeSk: EmitUniCat 
(UnicodeCategory.ModifierSymbol, offset); break;
+                       case Category.UnicodeSo: EmitUniCat 
(UnicodeCategory.OtherSymbol, offset); break;
+                       // other
+                       case Category.UnicodeCc: EmitUniCat 
(UnicodeCategory.Control, offset); break;
+                       case Category.UnicodeCf: EmitUniCat 
(UnicodeCategory.Format, offset); break;
+                       case Category.UnicodeCo: EmitUniCat 
(UnicodeCategory.PrivateUse, offset); break;
+                       case Category.UnicodeCs: EmitUniCat 
(UnicodeCategory.Surrogate, offset); break;
+                       case Category.UnicodeCn: EmitUniCat 
(UnicodeCategory.OtherNotAssigned, offset); break; 
+                       // Unicode block ranges...
+                       case Category.UnicodeBasicLatin:
+                               EmitRange ('\u0000', '\u007F', negate, false, 
reverse); break;
+                       case Category.UnicodeLatin1Supplement:
+                               EmitRange ('\u0080', '\u00FF', negate, false, 
reverse); break;
+                       case Category.UnicodeLatinExtendedA:
+                               EmitRange ('\u0100', '\u017F', negate, false, 
reverse); break;
+                       case Category.UnicodeLatinExtendedB:
+                               EmitRange ('\u0180', '\u024F', negate, false, 
reverse); break;
+                       case Category.UnicodeIPAExtensions:
+                               EmitRange ('\u0250', '\u02AF', negate, false, 
reverse); break;
+                       case Category.UnicodeSpacingModifierLetters:
+                               EmitRange ('\u02B0', '\u02FF', negate, false, 
reverse); break;
+                       case Category.UnicodeCombiningDiacriticalMarks:
+                               EmitRange ('\u0300', '\u036F', negate, false, 
reverse); break;
+                       case Category.UnicodeGreek:
+                               EmitRange ('\u0370', '\u03FF', negate, false, 
reverse); break;
+                       case Category.UnicodeCyrillic:
+                               EmitRange ('\u0400', '\u04FF', negate, false, 
reverse); break;
+                       case Category.UnicodeArmenian:
+                               EmitRange ('\u0530', '\u058F', negate, false, 
reverse); break;
+                       case Category.UnicodeHebrew:
+                               EmitRange ('\u0590', '\u05FF', negate, false, 
reverse); break;
+                       case Category.UnicodeArabic:
+                               EmitRange ('\u0600', '\u06FF', negate, false, 
reverse); break;
+                       case Category.UnicodeSyriac:
+                               EmitRange ('\u0700', '\u074F', negate, false, 
reverse); break;
+                       case Category.UnicodeThaana:
+                               EmitRange ('\u0780', '\u07BF', negate, false, 
reverse); break;
+                       case Category.UnicodeDevanagari:
+                               EmitRange ('\u0900', '\u097F', negate, false, 
reverse); break;
+                       case Category.UnicodeBengali:
+                               EmitRange ('\u0980', '\u09FF', negate, false, 
reverse); break;
+                       case Category.UnicodeGurmukhi:
+                               EmitRange ('\u0A00', '\u0A7F', negate, false, 
reverse); break;
+                       case Category.UnicodeGujarati:
+                               EmitRange ('\u0A80', '\u0AFF', negate, false, 
reverse); break;
+                       case Category.UnicodeOriya:
+                               EmitRange ('\u0B00', '\u0B7F', negate, false, 
reverse); break;
+                       case Category.UnicodeTamil:
+                               EmitRange ('\u0B80', '\u0BFF', negate, false, 
reverse); break;
+                       case Category.UnicodeTelugu:
+                               EmitRange ('\u0C00', '\u0C7F', negate, false, 
reverse); break;
+                       case Category.UnicodeKannada:
+                               EmitRange ('\u0C80', '\u0CFF', negate, false, 
reverse); break;
+                       case Category.UnicodeMalayalam:
+                               EmitRange ('\u0D00', '\u0D7F', negate, false, 
reverse); break;
+                       case Category.UnicodeSinhala:
+                               EmitRange ('\u0D80', '\u0DFF', negate, false, 
reverse); break;
+                       case Category.UnicodeThai:
+                               EmitRange ('\u0E00', '\u0E7F', negate, false, 
reverse); break;
+                       case Category.UnicodeLao:
+                               EmitRange ('\u0E80', '\u0EFF', negate, false, 
reverse); break;
+                       case Category.UnicodeTibetan:
+                               EmitRange ('\u0F00', '\u0FFF', negate, false, 
reverse); break;
+                       case Category.UnicodeMyanmar:
+                               EmitRange ('\u1000', '\u109F', negate, false, 
reverse); break;
+                       case Category.UnicodeGeorgian:
+                               EmitRange ('\u10A0', '\u10FF', negate, false, 
reverse); break;
+                       case Category.UnicodeHangulJamo:
+                               EmitRange ('\u1100', '\u11FF', negate, false, 
reverse); break;
+                       case Category.UnicodeEthiopic:
+                               EmitRange ('\u1200', '\u137F', negate, false, 
reverse); break;
+                       case Category.UnicodeCherokee:
+                               EmitRange ('\u13A0', '\u13FF', negate, false, 
reverse); break;
+                       case Category.UnicodeUnifiedCanadianAboriginalSyllabics:
+                               EmitRange ('\u1400', '\u167F', negate, false, 
reverse); break;
+                       case Category.UnicodeOgham:
+                               EmitRange ('\u1680', '\u169F', negate, false, 
reverse); break;
+                       case Category.UnicodeRunic:
+                               EmitRange ('\u16A0', '\u16FF', negate, false, 
reverse); break;
+                       case Category.UnicodeKhmer:
+                               EmitRange ('\u1780', '\u17FF', negate, false, 
reverse); break;
+                       case Category.UnicodeMongolian:
+                               EmitRange ('\u1800', '\u18AF', negate, false, 
reverse); break;
+                       case Category.UnicodeLatinExtendedAdditional:
+                               EmitRange ('\u1E00', '\u1EFF', negate, false, 
reverse); break;
+                       case Category.UnicodeGreekExtended:
+                               EmitRange ('\u1F00', '\u1FFF', negate, false, 
reverse); break;
+                       case Category.UnicodeGeneralPunctuation:
+                               EmitRange ('\u2000', '\u206F', negate, false, 
reverse); break;
+                       case Category.UnicodeSuperscriptsandSubscripts:
+                               EmitRange ('\u2070', '\u209F', negate, false, 
reverse); break;
+                       case Category.UnicodeCurrencySymbols:
+                               EmitRange ('\u20A0', '\u20CF', negate, false, 
reverse); break;
+                       case Category.UnicodeCombiningMarksforSymbols:
+                               EmitRange ('\u20D0', '\u20FF', negate, false, 
reverse); break;
+                       case Category.UnicodeLetterlikeSymbols:
+                               EmitRange ('\u2100', '\u214F', negate, false, 
reverse); break;
+                       case Category.UnicodeNumberForms:
+                               EmitRange ('\u2150', '\u218F', negate, false, 
reverse); break;
+                       case Category.UnicodeArrows:
+                               EmitRange ('\u2190', '\u21FF', negate, false, 
reverse); break;
+                       case Category.UnicodeMathematicalOperators:
+                               EmitRange ('\u2200', '\u22FF', negate, false, 
reverse); break;
+                       case Category.UnicodeMiscellaneousTechnical:
+                               EmitRange ('\u2300', '\u23FF', negate, false, 
reverse); break;
+                       case Category.UnicodeControlPictures:
+                               EmitRange ('\u2400', '\u243F', negate, false, 
reverse); break;
+                       case Category.UnicodeOpticalCharacterRecognition:
+                               EmitRange ('\u2440', '\u245F', negate, false, 
reverse); break;
+                       case Category.UnicodeEnclosedAlphanumerics:
+                               EmitRange ('\u2460', '\u24FF', negate, false, 
reverse); break;
+                       case Category.UnicodeBoxDrawing:
+                               EmitRange ('\u2500', '\u257F', negate, false, 
reverse); break;
+                       case Category.UnicodeBlockElements:
+                               EmitRange ('\u2580', '\u259F', negate, false, 
reverse); break;
+                       case Category.UnicodeGeometricShapes:
+                               EmitRange ('\u25A0', '\u25FF', negate, false, 
reverse); break;
+                       case Category.UnicodeMiscellaneousSymbols:
+                               EmitRange ('\u2600', '\u26FF', negate, false, 
reverse); break;
+                       case Category.UnicodeDingbats:
+                               EmitRange ('\u2700', '\u27BF', negate, false, 
reverse); break;
+                       case Category.UnicodeBraillePatterns:
+                               EmitRange ('\u2800', '\u28FF', negate, false, 
reverse); break;
+                       case Category.UnicodeCJKRadicalsSupplement:
+                               EmitRange ('\u2E80', '\u2EFF', negate, false, 
reverse); break;
+                       case Category.UnicodeKangxiRadicals:
+                               EmitRange ('\u2F00', '\u2FDF', negate, false, 
reverse); break;
+                       case Category.UnicodeIdeographicDescriptionCharacters:
+                               EmitRange ('\u2FF0', '\u2FFF', negate, false, 
reverse); break;
+                       case Category.UnicodeCJKSymbolsandPunctuation:
+                               EmitRange ('\u3000', '\u303F', negate, false, 
reverse); break;
+                       case Category.UnicodeHiragana:
+                               EmitRange ('\u3040', '\u309F', negate, false, 
reverse); break;
+                       case Category.UnicodeKatakana:
+                               EmitRange ('\u30A0', '\u30FF', negate, false, 
reverse); break;
+                       case Category.UnicodeBopomofo:
+                               EmitRange ('\u3100', '\u312F', negate, false, 
reverse); break;
+                       case Category.UnicodeHangulCompatibilityJamo:
+                               EmitRange ('\u3130', '\u318F', negate, false, 
reverse); break;
+                       case Category.UnicodeKanbun:
+                               EmitRange ('\u3190', '\u319F', negate, false, 
reverse); break;
+                       case Category.UnicodeBopomofoExtended:
+                               EmitRange ('\u31A0', '\u31BF', negate, false, 
reverse); break;
+                       case Category.UnicodeEnclosedCJKLettersandMonths:
+                               EmitRange ('\u3200', '\u32FF', negate, false, 
reverse); break;
+                       case Category.UnicodeCJKCompatibility:
+                               EmitRange ('\u3300', '\u33FF', negate, false, 
reverse); break;
+                       case Category.UnicodeCJKUnifiedIdeographsExtensionA:
+                               EmitRange ('\u3400', '\u4DB5', negate, false, 
reverse); break;
+                       case Category.UnicodeCJKUnifiedIdeographs:
+                               EmitRange ('\u4E00', '\u9FFF', negate, false, 
reverse); break;
+                       case Category.UnicodeYiSyllables:
+                               EmitRange ('\uA000', '\uA48F', negate, false, 
reverse); break;
+                       case Category.UnicodeYiRadicals:
+                               EmitRange ('\uA490', '\uA4CF', negate, false, 
reverse); break;
+                       case Category.UnicodeHangulSyllables:
+                               EmitRange ('\uAC00', '\uD7A3', negate, false, 
reverse); break;
+                       case Category.UnicodeHighSurrogates:
+                               EmitRange ('\uD800', '\uDB7F', negate, false, 
reverse); break;
+                       case Category.UnicodeHighPrivateUseSurrogates:
+                               EmitRange ('\uDB80', '\uDBFF', negate, false, 
reverse); break;
+                       case Category.UnicodeLowSurrogates:
+                               EmitRange ('\uDC00', '\uDFFF', negate, false, 
reverse); break;
+                       case Category.UnicodePrivateUse:
+                               EmitRange ('\uE000', '\uF8FF', negate, false, 
reverse); break;
+                       case Category.UnicodeCJKCompatibilityIdeographs:
+                               EmitRange ('\uF900', '\uFAFF', negate, false, 
reverse); break;
+                       case Category.UnicodeAlphabeticPresentationForms:
+                               EmitRange ('\uFB00', '\uFB4F', negate, false, 
reverse); break;
+                       case Category.UnicodeArabicPresentationFormsA:
+                               EmitRange ('\uFB50', '\uFDFF', negate, false, 
reverse); break;
+                       case Category.UnicodeCombiningHalfMarks:
+                               EmitRange ('\uFE20', '\uFE2F', negate, false, 
reverse); break;
+                       case Category.UnicodeCJKCompatibilityForms:
+                               EmitRange ('\uFE30', '\uFE4F', negate, false, 
reverse); break;
+                       case Category.UnicodeSmallFormVariants:
+                               EmitRange ('\uFE50', '\uFE6F', negate, false, 
reverse); break;
+                       case Category.UnicodeArabicPresentationFormsB:
+                               EmitRange ('\uFE70', '\uFEFE', negate, false, 
reverse); break;
+                       case Category.UnicodeHalfwidthandFullwidthForms:
+                               EmitRange ('\uFF00', '\uFFEF', negate, false, 
reverse); break;
                        default:
-                               Console.WriteLine ("Missing cat: {0}", cat);
-                               throw new NotSupportedException ();
+                               Console.WriteLine ("Missing category: {0}", 
cat);
+                               EmitFalse ();
+                               break;
                        }
                }
 
                public void EmitNotCategory (Category cat, bool negate, bool 
reverse)
                {
-                       throw new NotSupportedException ();
+                       // not sure why the compiler needed this separate 
interface funtion
+                       if (negate) {
+                               EmitCategory (cat, false, reverse);
+                       } else {
+                               EmitCategory (cat, true, reverse);
+                       }
                }
 
                public void EmitRange (char lo, char hi, bool negate, bool 
ignore, bool reverse)
@@ -307,11 +556,14 @@
 
                public void EmitBalance ()
                {
-                       throw new NotSupportedException ();
+                       // it doesn't seem we need to do anything, so just 
don't emit anything
+                       //throw new NotSupportedException ();
                }
 
                public void EmitReference (int gid, bool ignore, bool reverse)
                {
+                       if (gid > ushort.MaxValue)
+                               throw new NotSupportedException ();
                        int offset = 0;
                        if (ignore)
                                offset += 1;
@@ -323,7 +575,12 @@
 
                public void EmitIfDefined (int gid, LinkRef tail)
                {
-                       throw new NotSupportedException ();
+                       if (gid > ushort.MaxValue)
+                               throw new NotSupportedException ();
+                       BeginLink (tail);
+                       Emit (RxOp.IfDefined);
+                       EmitLink (tail);
+                       Emit ((ushort)gid);
                }
 
                public void EmitSub (LinkRef tail)

Modified: trunk/mcs/class/System/System.Text.RegularExpressions/RxInterpreter.cs
===================================================================
--- trunk/mcs/class/System/System.Text.RegularExpressions/RxInterpreter.cs      
2008-02-13 10:11:06 UTC (rev 95564)
+++ trunk/mcs/class/System/System.Text.RegularExpressions/RxInterpreter.cs      
2008-02-13 11:36:07 UTC (rev 95565)
@@ -1,6 +1,7 @@
 
 using System;
 using System.Collections;
+using System.Globalization;
 
 namespace System.Text.RegularExpressions {
 
@@ -13,6 +14,10 @@
                int match_start;
                int[] groups;
 
+               Mark[] marks = null; // mark stack
+               int mark_start; // start of current checkpoint
+               int mark_end; // end of checkpoint/next free mark
+
                static int ReadInt (byte[] code, int pc)
                {
                        int val = code [pc];
@@ -41,6 +46,116 @@
                        return Match.Empty;
                }
 
+               // capture management
+               private void Open (int gid, int ptr) {
+                       int m = groups [gid];
+                       if (m < mark_start || marks [m].IsDefined) {
+                               m = CreateMark (m);
+                               groups [gid] = m;
+                       }
+
+                       marks [m].Start = ptr;
+               }
+
+               private void Close (int gid, int ptr) {
+                       marks [groups [gid]].End = ptr;
+               }
+
+               private bool Balance (int gid, int balance_gid, bool capture, 
int ptr) {
+                       int b = groups [balance_gid];
+
+                       if (b == -1 || marks [b].Index < 0) {
+                               //Group not previously matched
+                               return false;
+                       }
+                       if (gid > 0 && capture){ 
+                               Open (gid, marks [b].Index + marks [b].Length);
+                               Close (gid, ptr);
+                       }
+
+                       groups [balance_gid] = marks[b].Previous;
+                       return true;
+               }
+
+               private int Checkpoint () {
+                       mark_start = mark_end;
+                       return mark_start;
+               }
+
+               private void Backtrack (int cp) {
+                       for (int i = 0; i < groups.Length; ++ i) {
+                               int m = groups [i];
+                               while (cp <= m)
+                                       m = marks [m].Previous;
+                               groups [i] = m;
+                       }
+               }
+
+               private void ResetGroups () {
+                       int n = groups.Length;
+                       if (marks == null)
+                               marks = new Mark [n * 10];
+                       if (n == 1)
+                               return;
+
+                       for (int i = 0; i < n; ++ i) {
+                               groups [i] = i;
+
+                               marks [i].Start = -1;
+                               marks [i].End = -1;
+                               marks [i].Previous = -1;
+                       }
+                       mark_start = 0;
+                       mark_end = n;
+               }
+
+               private int GetLastDefined (int gid) {
+                       int m = groups [gid];
+                       while (m >= 0 && !marks [m].IsDefined)
+                               m = marks [m].Previous;
+
+                       return m;
+               }
+
+               private int CreateMark (int previous) {
+                       if (mark_end == marks.Length) {
+                               Mark [] dest = new Mark [marks.Length * 2];
+                               marks.CopyTo (dest, 0);
+                               marks = dest;
+                       }
+
+                       int m = mark_end ++;
+                       marks [m].Start = marks [m].End = -1;
+                       marks [m].Previous = previous;
+
+                       return m;
+               }
+
+               private void GetGroupInfo (int gid, out int first_mark_index, 
out int n_caps)
+               {
+                       first_mark_index = -1;
+                       n_caps = 0;
+                       for (int m = groups [gid]; m >= 0; m = marks 
[m].Previous) {
+                               if (!marks [m].IsDefined)
+                                       continue;
+                               if (first_mark_index < 0)
+                                       first_mark_index = m;
+                               ++n_caps;
+                       }
+               }
+
+               private void PopulateGroup (Group g, int first_mark_index, int 
n_caps)
+               {
+                       int i = 1;
+                       for (int m = marks [first_mark_index].Previous; m >= 0; 
m = marks [m].Previous) {
+                               if (!marks [m].IsDefined)
+                                       continue;
+                               Capture cap = new Capture (str, marks 
[m].Index, marks [m].Length);
+                               g.Captures.SetValue (cap, n_caps - 1 - i);
+                               ++i;
+                       }
+               }
+
                bool EvalByteCode (int pc, int strpos, ref int strpos_result)
                {
                        int length, start, end;
@@ -94,14 +209,49 @@
                                        pc += program [pc + 1] | (program [pc + 
2] << 8);
                                        while (strpos < string_end) {
                                                int res = strpos;
+                                               if (groups.Length > 1) {
+                                                       ResetGroups ();
+                                                       marks [groups 
[0]].Start = strpos;
+                                               }
                                                if (EvalByteCode (pc, strpos, 
ref res)) {
                                                        match_start = strpos;
+                                                       if (groups.Length > 1)
+                                                               marks [groups 
[0]].End = res;
                                                        strpos_result = res;
                                                        return true;
                                                }
                                                strpos++;
                                        }
                                        return false;
+                               case RxOp.Reference:
+                                       length = GetLastDefined (program [pc + 
1] | (program [pc + 2] << 8));
+                                       if (length < 0)
+                                               return false;
+                                       start = marks [length].Index;
+                                       length = marks [length].Length;
+                                       if (strpos + length > string_end)
+                                               return false;
+                                       for (end = start + length; start < end; 
++start) {
+                                               if (str [strpos] != str [start])
+                                                       return false;
+                                               strpos++;
+                                       }
+                                       pc += 3;
+                                       continue;
+                               case RxOp.IfDefined:
+                                       if (GetLastDefined (program [pc + 3] | 
(program [pc + 4] << 8)) < 0)
+                                               pc += 5;
+                                       else
+                                               pc += program [pc + 1] | 
(program [pc + 2] << 8);
+                                       continue;
+                               case RxOp.OpenGroup:
+                                       Open (program [pc + 1] | (program [pc + 
2] << 8), strpos);
+                                       pc += 3;
+                                       continue;
+                               case RxOp.CloseGroup:
+                                       Close (program [pc + 1] | (program [pc 
+ 2] << 8), strpos);
+                                       pc += 3;
+                                       continue;
                                case RxOp.Jump:
                                        pc += program [pc + 1] | (program [pc + 
2] << 8);
                                        continue;
@@ -257,6 +407,34 @@
                                                }
                                        }
                                        return false;
+                               case RxOp.UnicodeChar:
+                                       if (strpos < string_end && (str 
[strpos] == (program [pc + 1] | (program [pc + 2] << 8)))) {
+                                               strpos++;
+                                               pc += 3;
+                                               continue;
+                                       }
+                                       return false;
+                               case RxOp.NoUnicodeChar:
+                                       if (strpos < string_end && (str 
[strpos] != (program [pc + 1] | (program [pc + 2] << 8)))) {
+                                               strpos++;
+                                               pc += 3;
+                                               continue;
+                                       }
+                                       return false;
+                               case RxOp.UnicodeCharIgnoreCase:
+                                       if (strpos < string_end && 
(Char.ToLower (str [strpos]) == (program [pc + 1] | (program [pc + 2] << 8)))) {
+                                               strpos++;
+                                               pc += 3;
+                                               continue;
+                                       }
+                                       return false;
+                               case RxOp.NoUnicodeCharIgnoreCase:
+                                       if (strpos < string_end && 
(Char.ToLower (str [strpos]) != (program [pc + 1] | (program [pc + 2] << 8)))) {
+                                               strpos++;
+                                               pc += 3;
+                                               continue;
+                                       }
+                                       return false;
                                case RxOp.CategoryAny:
                                        if (strpos < string_end && str [strpos] 
!= '\n') {
                                                strpos++;
@@ -264,6 +442,87 @@
                                                continue;
                                        }
                                        return false;
+                               case RxOp.CategoryWord:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (Char.IsLetterOrDigit (c) || 
Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation) {
+                                                       strpos++;
+                                                       pc++;
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoCategoryWord:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!Char.IsLetterOrDigit (c) 
&& Char.GetUnicodeCategory (c) != UnicodeCategory.ConnectorPunctuation) {
+                                                       strpos++;
+                                                       pc++;
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.CategoryDigit:
+                                       if (strpos < string_end && Char.IsDigit 
(str [strpos])) {
+                                               strpos++;
+                                               pc++;
+                                               continue;
+                                       }
+                                       return false;
+                               case RxOp.CategoryWhiteSpace:
+                                       if (strpos < string_end && 
Char.IsWhiteSpace (str [strpos])) {
+                                               strpos++;
+                                               pc++;
+                                               continue;
+                                       }
+                                       return false;
+                               case RxOp.CategoryEcmaWord:
+                                       if (strpos < string_end) {
+                                               int c = str [strpos];
+                                               if ('a' <= c && c <= 'z' || 'A' 
<= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_') {
+                                                       strpos++;
+                                                       pc++;
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.CategoryEcmaDigit:
+                                       if (strpos < string_end) {
+                                               int c = str [strpos];
+                                               if ('0' <= c && c <= '9') {
+                                                       strpos++;
+                                                       pc++;
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.CategoryEcmaWhiteSpace:
+                                       if (strpos < string_end) {
+                                               int c = str [strpos];
+                                               if (c == ' ' || c == '\t' || c 
== '\n' || c == '\r' || c == '\f' || c == '\v') {
+                                                       strpos++;
+                                                       pc++;
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.CategoryUnicodeSpecials:
+                                       if (strpos < string_end) {
+                                               int c = str [strpos];
+                                               if ('\uFEFF' <= c && c <= 
'\uFEFF' || '\uFFF0' <= c && c <= '\uFFFD') {
+                                                       strpos++;
+                                                       pc++;
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.CategoryUnicode:
+                                       if (strpos < string_end && 
Char.GetUnicodeCategory (str [strpos]) == (UnicodeCategory)program [pc + 1]) {
+                                               strpos++;
+                                               pc += 2;
+                                               continue;
+                                       }
+                                       return false;
                                case RxOp.Branch: {
                                        int res = 0;
                                        if (EvalByteCode (pc + 3, strpos, ref 
res)) {

Modified: trunk/mcs/class/System/System.Text.RegularExpressions/RxOp.cs
===================================================================
--- trunk/mcs/class/System/System.Text.RegularExpressions/RxOp.cs       
2008-02-13 10:11:06 UTC (rev 95564)
+++ trunk/mcs/class/System/System.Text.RegularExpressions/RxOp.cs       
2008-02-13 11:36:07 UTC (rev 95565)
@@ -30,8 +30,10 @@
                StringIgnoreCaseReverse,
 
                // followed by two byte length and unicode chars (two bytes per 
char)
-               // a better setup may be to have all the unicode chars in a 
separate
-               // char array and reference them from here with (offset, 
length) pairs
+               // a better setup may be to reference the chars in the patterns 
string
+               // (offset, length) pairs, at least when the pattern contains 
them,
+               // but this means we can't lowercase before hand: consider 
using a separate
+               // string/array
                // keep the order, see EmitString ()
                UnicodeString,
                UnicodeStringIgnoreCase,
@@ -107,14 +109,48 @@
 
                // add reverse and negate versions of the categories
                CategoryAny,
+               NoCategoryAny,
+               CategoryAnyReverse,
+               NoCategoryAnyReverse,
                CategoryDigit,
+               NoCategoryDigit,
+               CategoryDigitReverse,
+               NoCategoryDigitReverse,
                CategoryWord,
+               NoCategoryWord,
+               CategoryWordReverse,
+               NoCategoryWordReverse,
                CategoryWhiteSpace,
+               NoCategoryWhiteSpace,
+               CategoryWhiteSpaceReverse,
+               NoCategoryWhiteSpaceReverse,
                CategoryEcmaWord,
+               NoCategoryEcmaWord,
+               CategoryEcmaWordReverse,
+               NoCategoryEcmaWordReverse,
+               CategoryEcmaDigit,
+               NoCategoryEcmaDigit,
+               CategoryEcmaDigitReverse,
+               NoCategoryEcmaDigitReverse,
                CategoryEcmaWhiteSpace,
+               NoCategoryEcmaWhiteSpace,
+               CategoryEcmaWhiteSpaceReverse,
+               NoCategoryEcmaWhiteSpaceReverse,
 
                // followed by a unicode category value (byte)
                CategoryUnicode,
+               NoCategoryUnicode,
+               CategoryUnicodeReverse,
+               NoCategoryUnicodeReverse,
+
+               CategoryUnicodeLetter,
+               CategoryUnicodeMark,
+               CategoryUnicodeNumber,
+               CategoryUnicodeSeparator,
+               CategoryUnicodePunctuation,
+               CategoryUnicodeSymbol,
+               CategoryUnicodeSpecials,
+               CategoryUnicodeOther,
                // add more categories
 
                // backreferences
@@ -130,6 +166,9 @@
                OpenGroup,
                CloseGroup,
 
+               // followed by offset and two-byte group id
+               IfDefined,
+
                // skip ahead num bytes
                // followed by two-byte offset
                Jump,

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to