2009-01-07 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mcs / class / System / System.Text.RegularExpressions / RxInterpreter.cs
index 0250e4cb47ea44cd29aed28dc7ebac905b5a5b1e..980e17ff34c52d9da0be5df0c1f8d749bf201f20 100644 (file)
@@ -1,4 +1,6 @@
 
+// Based upon interpreter.cs, written by Dan Lewis (dlewis@gmx.co.uk)
+
 using System;
 using System.Collections;
 using System.Globalization;
@@ -28,11 +30,11 @@ namespace System.Text.RegularExpressions {
                RepeatContext deep;             // points to the most-nested repeat context
 
                /* The readonly ensures the JIT can optimize out if (trace_rx) statements */
-               static readonly bool trace_rx = Environment.GetEnvironmentVariable ("RXD") != null;
+               public static readonly bool trace_rx = Environment.GetEnvironmentVariable ("MONO_TRACE_RX") != null;
 
                // private classes
 
-               private struct IntStack {
+               internal struct IntStack {
                        int [] values;
                        int count;
                        public int Pop ()
@@ -120,9 +122,9 @@ namespace System.Text.RegularExpressions {
                static int ReadInt (byte[] code, int pc)
                {
                        int val = code [pc];
-                       val |= code [pc + 1] << 8;
-                       val |= code [pc + 2] << 16;
-                       val |= code [pc + 3] << 24;
+                       val |= (int)code [pc + 1] << 8;
+                       val |= (int)code [pc + 2] << 16;
+                       val |= (int)code [pc + 3] << 24;
                        return val;
                }
 
@@ -130,7 +132,7 @@ namespace System.Text.RegularExpressions {
                {
                        this.program = program;
                        this.eval_del = eval_del;
-                       group_count = 1 + (program [1] | (program [2] << 8));
+                       group_count = 1 + (program [1] | ((int)program [2] << 8));
                        groups = new int [group_count];
                        stack = new IntStack ();
 
@@ -296,7 +298,7 @@ namespace System.Text.RegularExpressions {
                }
 
                // used by the IL backend
-               protected void SetStartOfMatch (int pos)
+           internal void SetStartOfMatch (int pos)
                {
                        marks [groups [0]].Start = pos;
                }
@@ -412,12 +414,71 @@ namespace System.Text.RegularExpressions {
                                        }
                                        return false;
                                case RxOp.Anchor:
-                                       length = program [pc + 3] | (program [pc + 4] << 8);
-                                       pc += program [pc + 1] | (program [pc + 2] << 8);
+                                       int skip = program [pc + 1] | ((int)program [pc + 2] << 8);
+                                       int anch_offset = program [pc + 3] | ((int)program [pc + 4] << 8);
+
+                                       /*
+                                        * In the general case, we have to evaluate the bytecode
+                                        * starting at pc + skip, however the optimizer emits some
+                                        * special cases, whose bytecode begins at pc + 5.
+                                        */
+                                       int anch_pc = pc + 5;
+                                       RxOp anch_op = (RxOp)(program[anch_pc] & 0x00ff);
+
+                                       bool spec_anch = false;
+
+                                       // FIXME: Add more special cases from interpreter.cs
+                                       if (anch_op == RxOp.String || anch_op == RxOp.StringIgnoreCase) {
+                                               if (pc + skip == anch_pc + 2 + program [anch_pc + 1] + 1) {
+                                                       // Anchor
+                                                       //      String
+                                                       //      True
+                                                       spec_anch = true;
+                                                       if (trace_rx)
+                                                               Console.WriteLine ("  string anchor at {0}, offset {1}", anch_pc, anch_offset);
+                                               }
+                                       }
+
+                                       pc += skip;
+
+                                       if ((RxOp)program [pc] == RxOp.StartOfString) {
+                                               if (strpos == 0) {
+                                                       int res = strpos;
+                                                       if (groups.Length > 1) {
+                                                               ResetGroups ();
+                                                               marks [groups [0]].Start = strpos;
+                                                       }
+                                                       if (EvalByteCode (pc + 1, strpos, ref res)) {
+                                                               marks [groups [0]].Start = strpos;
+                                                               if (groups.Length > 1)
+                                                                       marks [groups [0]].End = res;
+                                                               strpos_result = res;
+                                                               return true;
+                                                       }
+                                               }
+                                               return false;
+                                       }
+
                                        // it's important to test also the end of the string
                                        // position for things like: "" =~ /$/
                                        end = string_end + 1;
                                        while (strpos < end) {
+                                               if (spec_anch) {
+                                                       if (anch_op == RxOp.String || anch_op == RxOp.StringIgnoreCase) {
+                                                               /* 
+                                                                * This means the match must contain a given
+                                                                * string at a constant position, so we can skip 
+                                                                * forward until the string matches. This is a win if
+                                                                * the rest of the regex 
+                                                                * has a complex positive lookbehind for example.
+                                                                */
+                                                               int tmp_res = strpos;
+                                                               if (!EvalByteCode (anch_pc, strpos + anch_offset, ref tmp_res)) {
+                                                                       strpos ++;
+                                                                       continue;
+                                                               }
+                                                       }
+                                               }
                                                int res = strpos;
                                                if (groups.Length > 1) {
                                                        ResetGroups ();
@@ -435,8 +496,8 @@ namespace System.Text.RegularExpressions {
                                        }
                                        return false;
                                case RxOp.AnchorReverse:
-                                       length = program [pc + 3] | (program [pc + 4] << 8);
-                                       pc += program [pc + 1] | (program [pc + 2] << 8);
+                                       length = program [pc + 3] | ((int)program [pc + 4] << 8);
+                                       pc += program [pc + 1] | ((int)program [pc + 2] << 8);
                                        // it's important to test also the end of the string
                                        // position for things like: "" =~ /$/
                                        end = 0;
@@ -458,7 +519,7 @@ namespace System.Text.RegularExpressions {
                                        }
                                        return false;
                                case RxOp.Reference:
-                                       length = GetLastDefined (program [pc + 1] | (program [pc + 2] << 8));
+                                       length = GetLastDefined (program [pc + 1] | ((int)program [pc + 2] << 8));
                                        if (length < 0)
                                                return false;
                                        start = marks [length].Index;
@@ -473,7 +534,7 @@ namespace System.Text.RegularExpressions {
                                        pc += 3;
                                        continue;
                                case RxOp.ReferenceIgnoreCase:
-                                       length = GetLastDefined (program [pc + 1] | (program [pc + 2] << 8));
+                                       length = GetLastDefined (program [pc + 1] | ((int)program [pc + 2] << 8));
                                        if (length < 0)
                                                return false;
                                        start = marks [length].Index;
@@ -488,7 +549,7 @@ namespace System.Text.RegularExpressions {
                                        pc += 3;
                                        continue;
                                case RxOp.ReferenceReverse: {
-                                       length = GetLastDefined (program [pc + 1] | (program [pc + 2] << 8));
+                                       length = GetLastDefined (program [pc + 1] | ((int)program [pc + 2] << 8));
                                        if (length < 0)
                                                return false;
                                        start = marks [length].Index;
@@ -505,15 +566,15 @@ namespace System.Text.RegularExpressions {
                                        continue;
                                }
                                case RxOp.IfDefined:
-                                       if (GetLastDefined (program [pc + 3] | (program [pc + 4] << 8)) >= 0)
+                                       if (GetLastDefined (program [pc + 3] | ((int)program [pc + 4] << 8)) >= 0)
                                                pc += 5;
                                        else
-                                               pc += program [pc + 1] | (program [pc + 2] << 8);
+                                               pc += program [pc + 1] | ((int)program [pc + 2] << 8);
                                        continue;
                                case RxOp.SubExpression: {
                                        int res = 0;
                                        if (EvalByteCode (pc + 3, strpos, ref res)) {
-                                               pc += program [pc + 1] | (program [pc + 2] << 8);
+                                               pc += program [pc + 1] | ((int)program [pc + 2] << 8);
                                                strpos = res;
                                                continue;
                                        }
@@ -523,18 +584,18 @@ namespace System.Text.RegularExpressions {
                                        int res = 0;
                                        // FIXME: checkpoint
                                        if (EvalByteCode (pc + 5, strpos, ref res)) {
-                                               pc += program [pc + 1] | (program [pc + 2] << 8);
+                                               pc += program [pc + 1] | ((int)program [pc + 2] << 8);
                                        } else {
-                                               pc += program [pc + 3] | (program [pc + 4] << 8);
+                                               pc += program [pc + 3] | ((int)program [pc + 4] << 8);
                                        }
                                        continue;
                                }
                                case RxOp.OpenGroup:
-                                       Open (program [pc + 1] | (program [pc + 2] << 8), strpos);
+                                       Open (program [pc + 1] | ((int)program [pc + 2] << 8), strpos);
                                        pc += 3;
                                        continue;
                                case RxOp.CloseGroup:
-                                       Close (program [pc + 1] | (program [pc + 2] << 8), strpos);
+                                       Close (program [pc + 1] | ((int)program [pc + 2] << 8), strpos);
                                        pc += 3;
                                        continue;
                                case RxOp.BalanceStart: {
@@ -543,14 +604,14 @@ namespace System.Text.RegularExpressions {
                                        if (!EvalByteCode (pc + 8, strpos, ref res))
                                                goto Fail;
 
-                                       int gid = program [pc + 1] | (program [pc + 2] << 8);
-                                       int balance_gid = program [pc + 3] | (program [pc + 4] << 8);
+                                       int gid = program [pc + 1] | ((int)program [pc + 2] << 8);
+                                       int balance_gid = program [pc + 3] | ((int)program [pc + 4] << 8);
                                        bool capture = program [pc + 5] > 0;
                                        if (!Balance (gid, balance_gid, capture, strpos))
                                                goto Fail;
 
                                        strpos = res;                                   
-                                       pc += program[pc + 6] | (program [pc + 7] << 8);
+                                       pc += program[pc + 6] | ((int)program [pc + 7] << 8);
                                        break;
                                }
                                case RxOp.Balance: {
@@ -558,10 +619,10 @@ namespace System.Text.RegularExpressions {
                                }
 
                                case RxOp.Jump:
-                                       pc += program [pc + 1] | (program [pc + 2] << 8);
+                                       pc += program [pc + 1] | ((int)program [pc + 2] << 8);
                                        continue;
                                case RxOp.TestCharGroup:
-                                       char_group_end = pc + program [pc + 1] | (program [pc + 2] << 8);
+                                       char_group_end = pc + (program [pc + 1] | ((int)program [pc + 2] << 8));
                                        pc += 3;
                                        continue;
                                case RxOp.String:
@@ -590,43 +651,92 @@ namespace System.Text.RegularExpressions {
                                        }
                                        pc = end;
                                        continue;
-                               case RxOp.UnicodeString:
+                               case RxOp.StringReverse: {
+                                       start = pc + 2;
+                                       length = program [pc + 1];
+                                       if (strpos < length)
+                                               return false;
+                                       int p = strpos - length;
+                                       end = start + length;
+                                       for (; start < end; ++start, ++p) {
+                                               if (str [p] != program [start])
+                                                       return false;
+                                       }
+                                       strpos -= length;
+                                       pc = end;
+                                       continue;
+                               }
+                               case RxOp.StringIgnoreCaseReverse: {
+                                       start = pc + 2;
+                                       length = program [pc + 1];
+                                       if (strpos < length)
+                                               return false;
+                                       int p = strpos - length;
+                                       end = start + length;
+                                       for (; start < end; ++start, ++p) {
+                                               if (str [p] != program [start] && Char.ToLower (str [p]) != program [start])
+                                                       return false;
+                                       }
+                                       strpos -= length;
+                                       pc = end;
+                                       continue;
+                               }
+                               case RxOp.UnicodeString: {
                                        start = pc + 3;
-                                       length = program [pc + 1] | (program [pc + 2] << 8);
+                                       length = program [pc + 1] | ((int)program [pc + 2] << 8);
                                        if (strpos + length > string_end)
                                                return false;
                                        end = start + length * 2;
                                        for (; start < end; start += 2) {
-                                               int c = program [start] | (program [start + 1] << 8);
+                                               int c = program [start] | ((int)program [start + 1] << 8);
                                                if (str [strpos] != c)
                                                        return false;
                                                strpos++;
                                        }
                                        pc = end;
                                        continue;
-                               case RxOp.UnicodeStringIgnoreCase:
+                               }
+                               case RxOp.UnicodeStringIgnoreCase: {
                                        start = pc + 3;
-                                       length = program [pc + 1] | (program [pc + 2] << 8);
+                                       length = program [pc + 1] | ((int)program [pc + 2] << 8);
                                        if (strpos + length > string_end)
                                                return false;
                                        end = start + length * 2;
                                        for (; start < end; start += 2) {
-                                               int c = program [start] | (program [start + 1] << 8);
+                                               int c = program [start] | ((int)program [start + 1] << 8);
                                                if (str [strpos] != c && Char.ToLower (str [strpos]) != c)
                                                        return false;
                                                strpos++;
                                        }
                                        pc = end;
                                        continue;
-                               case RxOp.StringReverse: {
-                                       start = pc + 2;
-                                       length = program [pc + 1];
+                               }
+                               case RxOp.UnicodeStringReverse: {
+                                       start = pc + 3;
+                                       length = program [pc + 1] | ((int)program [pc + 2] << 8);
                                        if (strpos < length)
                                                return false;
                                        int p = strpos - length;
-                                       end = start + length;
-                                       for (; start < end; ++start, ++p) {
-                                               if (str [p] != program [start])
+                                       end = start + length * 2;
+                                       for (; start < end; start += 2, p += 2) {
+                                               int c = program [start] | ((int)program [start + 1] << 8);
+                                               if (str [p] != c)
+                                                       return false;
+                                       }
+                                       strpos -= length;
+                                       pc = end;
+                                       continue;
+                               }
+                               case RxOp.UnicodeStringIgnoreCaseReverse: {
+                                       start = pc + 3;
+                                       length = program [pc + 1] | ((int)program [pc + 2] << 8);
+                                       if (strpos < length)
+                                               return false;
+                                       int p = strpos - length;
+                                       end = start + length * 2;
+                                       for (; start < end; start += 2, p += 2) {
+                                               int c = program [start] | ((int)program [start + 1] << 8);
+                                               if (str [p] != c && Char.ToLower (str [p]) != c)
                                                        return false;
                                        }
                                        strpos -= length;
@@ -639,10 +749,9 @@ namespace System.Text.RegularExpressions {
                                         * generic opcode, which has three parameters:
                                         * - reverse (Reverse), revert (No), ignore-case (IgnoreCase)
                                         * Thus each opcode has 8 variants.
-                                        * FIXME: Generate the specialized versions using a script, or
-                                        * move all unusual variations (Reverse+IgnoreCase+Unicode) 
-                                        * into a generic GenericChar opcode like in the old 
-                                        * interpreter.
+                                        * FIXME: Maybe move all unusual variations 
+                                        * (Reverse+IgnoreCase+Unicode) into a generic GenericChar opcode 
+                                        * like in the old interpreter.
                                         * FIXME: Move all the Reverse opcodes to a separate method.
                                         */
 #if FALSE
@@ -667,6 +776,8 @@ namespace System.Text.RegularExpressions {
                                                                pc += ins_len;
                                                                if (char_group_end == 0 || (pc + 1 == char_group_end))
                                                                        strpos ++;
+                                                               if (pc + 1 == char_group_end)
+                                                                       goto test_char_group_passed;
                                                                continue;
                                                        }
                                                } else {
@@ -676,7 +787,7 @@ namespace System.Text.RegularExpressions {
                                                                pc += ins_len;
                                                                continue;
                                                        } else {
-                                                               /* Fail both inside an outside a char group */
+                                                               /* Fail both inside and outside a char group */
                                                                return false;
                                                        }
                                                }
@@ -687,62 +798,36 @@ namespace System.Text.RegularExpressions {
                                                // - strpos -- instead of strpos ++
                                        }
 #endif
-
-                                       /* Char */
-
+                               // GENERATED BY gen-interp.cs, DO NOT MODIFY
+                               
+                               /* Char */
+                               
                                case RxOp.Char:
-                                       if (strpos < string_end && (str [strpos] == program [pc + 1])) {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc += 2;
-                                               continue;
-                                       }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc += 2;
-                                       continue;
-                               case RxOp.CharIgnoreCase:
-                                       if (strpos < string_end && (Char.ToLower (str [strpos]) == program [pc + 1])) {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc += 2;
-                                               continue;
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (((c == program [pc + 1]))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 2;
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
                                        pc += 2;
                                        continue;
-                               case RxOp.NoChar:
-                                       if (strpos < string_end && (str [strpos] != program [pc + 1])) {
-                                               pc += 2;
-                                               if ((char_group_end == 0) || (pc + 1 == char_group_end))
-                                                       strpos ++;
-                                               continue;
-                                       } else {
-                                               return false;
-                                       }
-                               case RxOp.NoCharIgnoreCase:
-                                       if (strpos < string_end && (Char.ToLower (str [strpos]) != program [pc + 1])) {
-                                               pc += 2;
-                                               if (char_group_end == 0 || (pc + 1 == char_group_end))
-                                                       strpos++;
-                                               continue;
-                                       } else {
-                                               return false;
-                                       }
-
-                                       /* Range */
-
+                               
+                               /* Range */
+                               
                                case RxOp.Range:
                                        if (strpos < string_end) {
-                                               int c = str [strpos];
-                                               if (c >= program [pc + 1] && c <= program [pc + 2]) {
-                                                       pc += 3;
-                                                       strpos++;
+                                               char c = str [strpos];
+                                               if (((c >= program [pc + 1] && c <= program [pc + 2]))) {
+                                                       strpos ++;
                                                        if (char_group_end != 0)
                                                                goto test_char_group_passed;
+                                                       pc += 3;
                                                        continue;
                                                }
                                        }
@@ -750,865 +835,1312 @@ namespace System.Text.RegularExpressions {
                                                return false;
                                        pc += 3;
                                        continue;
-                               case RxOp.RangeIgnoreCase:
+                               
+                               /* UnicodeRange */
+                               
+                               case RxOp.UnicodeRange:
                                        if (strpos < string_end) {
-                                               int c = Char.ToLower (str [strpos]);
-                                               if (c >= program [pc + 1] && c <= program [pc + 2]) {
-                                                       pc += 3;
-                                                       strpos++;
+                                               char c = str [strpos];
+                                               if (((c >= (program [pc + 1] | ((int)program [pc + 2] << 8))) && (c <= (program [pc + 3] | ((int)program [pc + 4] << 8))))) {
+                                                       strpos ++;
                                                        if (char_group_end != 0)
                                                                goto test_char_group_passed;
+                                                       pc += 5;
                                                        continue;
                                                }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc += 3;
+                                       pc += 5;
                                        continue;
-                               case RxOp.NoRange:
+                               
+                               /* UnicodeChar */
+                               
+                               case RxOp.UnicodeChar:
                                        if (strpos < string_end) {
-                                               int c = str [strpos];
-                                               if (!(c >= program [pc + 1] && c <= program [pc + 2])) {
+                                               char c = str [strpos];
+                                               if (((c == (program [pc + 1] | ((int)program [pc + 2] << 8))))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
                                                        pc += 3;
-                                                       if ((char_group_end == 0 || (pc + 1 == char_group_end)))
-                                                               strpos ++;
                                                        continue;
                                                }
                                        }
-                                       return false;
-                               case RxOp.NoRangeIgnoreCase:
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 3;
+                                       continue;
+                               
+                               /* CategoryAny */
+                               
+                               case RxOp.CategoryAny:
                                        if (strpos < string_end) {
-                                               int c = Char.ToLower (str [strpos]);
-                                               if (!(c >= program [pc + 1] && c <= program [pc + 2])) {
-                                                       pc += 3;
-                                                       if ((char_group_end == 0 || (pc + 1 == char_group_end)))
-                                                               strpos ++;
+                                               char c = str [strpos];
+                                               if (((c != '\n'))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 1;
                                                        continue;
                                                }
                                        }
-                                       return false;
-
-                                       /* UnicodeRange */
-
-                               case RxOp.UnicodeRange:
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 1;
+                                       continue;
+                               
+                               /* CategoryAnySingleline */
+                               
+                               case RxOp.CategoryAnySingleline:
                                        if (strpos < string_end) {
-                                               int c = str [strpos];
-                        int lo = program [pc + 1] | (program [pc + 2] << 8);
-                        int hi = program [pc + 3] | (program [pc + 4] << 8);
-                                               if (c >= lo && c <= hi) {
-                                                       pc += 5;
-                                                       strpos++;
+                                               char c = str [strpos];
+                                               if ((true)) {
+                                                       strpos ++;
                                                        if (char_group_end != 0)
                                                                goto test_char_group_passed;
+                                                       pc += 1;
                                                        continue;
                                                }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc += 5;
+                                       pc += 1;
                                        continue;
-                               case RxOp.UnicodeRangeIgnoreCase:
+                               
+                               /* CategoryWord */
+                               
+                               case RxOp.CategoryWord:
                                        if (strpos < string_end) {
-                                               int c = Char.ToLower (str [strpos]);
-                        int lo = program [pc + 1] | (program [pc + 2] << 8);
-                        int hi = program [pc + 3] | (program [pc + 4] << 8);
-                                               if (c >= lo && c <= hi) {
-                                                       pc += 5;
-                                                       strpos++;
+                                               char c = str [strpos];
+                                               if (((Char.IsLetterOrDigit (c) || Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation))) {
+                                                       strpos ++;
                                                        if (char_group_end != 0)
                                                                goto test_char_group_passed;
+                                                       pc += 1;
                                                        continue;
                                                }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc += 5;
+                                       pc += 1;
                                        continue;
-                               case RxOp.NoUnicodeRange:
+                               
+                               /* CategoryDigit */
+                               
+                               case RxOp.CategoryDigit:
                                        if (strpos < string_end) {
-                                               int c = str [strpos];
-                        int lo = program [pc + 1] | (program [pc + 2] << 8);
-                        int hi = program [pc + 3] | (program [pc + 4] << 8);
-                                               if (!(c >= lo && c <= hi)) {
-                                                       pc += 5;
-                                                       if ((char_group_end == 0 || (pc + 1 == char_group_end)))
-                                                               strpos ++;
+                                               char c = str [strpos];
+                                               if (((Char.IsDigit (c)))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 1;
                                                        continue;
                                                }
                                        }
-                                       return false;
-                               case RxOp.NoUnicodeRangeIgnoreCase:
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 1;
+                                       continue;
+                               
+                               /* CategoryWhiteSpace */
+                               
+                               case RxOp.CategoryWhiteSpace:
                                        if (strpos < string_end) {
-                                               int c = Char.ToLower (str [strpos]);
-                        int lo = program [pc + 1] | (program [pc + 2] << 8);
-                        int hi = program [pc + 3] | (program [pc + 4] << 8);
-                                               if (!(c >= lo && c <= hi)) {
-                                                       pc += 5;
-                                                       if ((char_group_end == 0 || (pc + 1 == char_group_end)))
-                                                               strpos ++;
+                                               char c = str [strpos];
+                                               if (((Char.IsWhiteSpace (c)))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 1;
                                                        continue;
                                                }
                                        }
-                                       return false;
-
-                                       /* Bitmap */
-
-                               case RxOp.Bitmap:
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 1;
+                                       continue;
+                               
+                               /* CategoryEcmaWord */
+                               
+                               case RxOp.CategoryEcmaWord:
                                        if (strpos < string_end) {
-                                               int c = str [strpos];
-                                               c -= program [pc + 1];
-                                               length = program [pc + 2];
-                                               if (c < 0 || c >= (length << 3)) {
-                                                       if (char_group_end == 0)
-                                                               return false;
-                                                       pc += length + 3;
-                                                       continue;
-                                               }
-                                               pc += 3;
-                                               if ((program [pc + (c >> 3)] & (1 << (c & 0x7))) != 0) {
-                                                       strpos++;
+                                               char c = str [strpos];
+                                               if ((('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_'))) {
+                                                       strpos ++;
                                                        if (char_group_end != 0)
                                                                goto test_char_group_passed;
-                                                       pc += length;
+                                                       pc += 1;
                                                        continue;
                                                }
-                                               if (char_group_end == 0)
-                                                       return false;
-                                               pc += length;
-                                               continue;
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc += 3 + program [pc + 2];
+                                       pc += 1;
                                        continue;
-                               case RxOp.BitmapIgnoreCase:
+                               
+                               /* CategoryEcmaWhiteSpace */
+                               
+                               case RxOp.CategoryEcmaWhiteSpace:
                                        if (strpos < string_end) {
-                                               int c = Char.ToLower (str [strpos]);
-                                               c -= program [pc + 1];
-                                               length = program [pc + 2];
-                                               if (c < 0 || c >= (length << 3)) {
-                                                       if (char_group_end == 0)
-                                                               return false;
-                                                       pc += length + 3;
-                                                       continue;
-                                               }
-                                               pc += 3;
-                                               if ((program [pc + (c >> 3)] & (1 << (c & 0x7))) != 0) {
-                                                       strpos++;
+                                               char c = str [strpos];
+                                               if (((c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'))) {
+                                                       strpos ++;
                                                        if (char_group_end != 0)
                                                                goto test_char_group_passed;
-                                                       pc += length;
+                                                       pc += 1;
                                                        continue;
                                                }
-                                               if (char_group_end == 0)
-                                                       return false;
-                                               pc += length;
-                                               continue;
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc += 3 + program [pc + 2];
+                                       pc += 1;
                                        continue;
-                               case RxOp.NoBitmap:
+                               
+                               /* CategoryUnicodeSpecials */
+                               
+                               case RxOp.CategoryUnicodeSpecials:
                                        if (strpos < string_end) {
-                                               int c = str [strpos];
-                                               c -= program [pc + 1];
-                                               length = program [pc + 2];
-                                               if (c < 0 || c >= (length << 3)) {
-                                                       pc += 3 + length;
-                                                       if ((char_group_end == 0 || (pc + 1 == char_group_end)))
-                                                               strpos++;
-                                                       continue;
-                                               }
-                                               pc += 3;
-                                               if ((program [pc + (c >> 3)] & (1 << (c & 0x7))) != 0) {
-                                                       if (char_group_end == 0)
-                                                               return false;
-                                                       pc += length;
-                                                       continue;
-                                               } else {
-                                                       pc += length;
-                                                       if ((char_group_end == 0 || (pc + 1 == char_group_end)))
-                                                               strpos++;
+                                               char c = str [strpos];
+                                               if ((('\uFEFF' <= c && c <= '\uFEFF' || '\uFFF0' <= c && c <= '\uFFFD'))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 1;
                                                        continue;
                                                }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc += 3 + program [pc + 2];
+                                       pc += 1;
                                        continue;
-                               case RxOp.NoBitmapIgnoreCase:
+                               
+                               /* CategoryUnicode */
+                               
+                               case RxOp.CategoryUnicode:
                                        if (strpos < string_end) {
-                                               int c = str [strpos];
-                                               c -= program [pc + 1];
-                                               length =  program [pc + 2];
-                                               pc += 3;
-                                               if (c < 0 || c >= (length << 3)) {
-                                                       strpos++;
+                                               char c = str [strpos];
+                                               if (((Char.GetUnicodeCategory (c) == (UnicodeCategory)program [pc + 1]))) {
+                                                       strpos ++;
                                                        if (char_group_end != 0)
                                                                goto test_char_group_passed;
-                                                       pc += length;
+                                                       pc += 2;
                                                        continue;
                                                }
-                                               if ((program [pc + (c >> 3)] & (1 << (c & 0x7))) != 0) {
-                                                       if (char_group_end == 0)
-                                                               return false;
-                                                       pc += length;
-                                                       continue;
-                                               } else {
-                                                       strpos++;
+                                       }
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 2;
+                                       continue;
+                               
+                               /* CategoryGeneral */
+                               
+                               case RxOp.CategoryGeneral:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (((CategoryUtils.IsCategory ((Category)program [pc + 1], c)))) {
+                                                       strpos ++;
                                                        if (char_group_end != 0)
                                                                goto test_char_group_passed;
-                                                       pc += length;
+                                                       pc += 2;
                                                        continue;
                                                }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc += 3 + program [pc + 2];
+                                       pc += 2;
                                        continue;
-
-                                       /* UnicodeChar */
-
-                               case RxOp.UnicodeChar:
-                                       if (strpos < string_end && (str [strpos] == (program [pc + 1] | (program [pc + 2] << 8)))) {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc += 3;
-                                               continue;
+                               
+                               /* Bitmap */
+                               
+                               case RxOp.Bitmap:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               int c2 = (int)c; c2 -= program [pc + 1]; length = program [pc + 2];
+                                               if (((c2 >= 0 && c2 < (length << 3) && (program [pc + 3 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 3 + program [pc + 2];
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc += 3;
+                                       pc += 3 + program [pc + 2];
                                        continue;
-                               case RxOp.NoUnicodeChar:
-                                       if (strpos < string_end && (str [strpos] != (program [pc + 1] | (program [pc + 2] << 8)))) {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc += 3;
-                                               continue;
+                               
+                               /* UnicodeBitmap */
+                               
+                               case RxOp.UnicodeBitmap:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               int c2 = (int)c; c2 -= (program [pc + 1] | ((int)program [pc + 2] << 8)); length = (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                               if (((c2 >= 0 && c2 < (length << 3) && (program [pc + 5 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 5 + (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                                       continue;
+                                               }
+                                       }
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 5 + (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                       continue;
+                               case RxOp.CharIgnoreCase:
+                                       if (strpos < string_end) {
+                                               char c = Char.ToLower (str [strpos]);
+                                               if (((c == program [pc + 1]))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 2;
+                                                       continue;
+                                               }
+                                       }
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 2;
+                                       continue;
+                               case RxOp.RangeIgnoreCase:
+                                       if (strpos < string_end) {
+                                               char c = Char.ToLower (str [strpos]);
+                                               if (((c >= program [pc + 1] && c <= program [pc + 2]))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 3;
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
                                        pc += 3;
                                        continue;
+                               case RxOp.UnicodeRangeIgnoreCase:
+                                       if (strpos < string_end) {
+                                               char c = Char.ToLower (str [strpos]);
+                                               if (((c >= (program [pc + 1] | ((int)program [pc + 2] << 8))) && (c <= (program [pc + 3] | ((int)program [pc + 4] << 8))))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 5;
+                                                       continue;
+                                               }
+                                       }
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 5;
+                                       continue;
                                case RxOp.UnicodeCharIgnoreCase:
-                                       if (strpos < string_end && (Char.ToLower (str [strpos]) == (program [pc + 1] | (program [pc + 2] << 8)))) {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc += 3;
-                                               continue;
+                                       if (strpos < string_end) {
+                                               char c = Char.ToLower (str [strpos]);
+                                               if (((c == (program [pc + 1] | ((int)program [pc + 2] << 8))))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 3;
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
                                        pc += 3;
                                        continue;
+                               case RxOp.BitmapIgnoreCase:
+                                       if (strpos < string_end) {
+                                               char c = Char.ToLower (str [strpos]);
+                                               int c2 = (int)c; c2 -= program [pc + 1]; length = program [pc + 2];
+                                               if (((c2 >= 0 && c2 < (length << 3) && (program [pc + 3 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 3 + program [pc + 2];
+                                                       continue;
+                                               }
+                                       }
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 3 + program [pc + 2];
+                                       continue;
+                               case RxOp.UnicodeBitmapIgnoreCase:
+                                       if (strpos < string_end) {
+                                               char c = Char.ToLower (str [strpos]);
+                                               int c2 = (int)c; c2 -= (program [pc + 1] | ((int)program [pc + 2] << 8)); length = (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                               if (((c2 >= 0 && c2 < (length << 3) && (program [pc + 5 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       strpos ++;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 5 + (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                                       continue;
+                                               }
+                                       }
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 5 + (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                       continue;
+                               case RxOp.NoChar:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!((c == program [pc + 1]))) {
+                                                       pc += 2;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoRange:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!((c >= program [pc + 1] && c <= program [pc + 2]))) {
+                                                       pc += 3;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoUnicodeRange:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!((c >= (program [pc + 1] | ((int)program [pc + 2] << 8))) && (c <= (program [pc + 3] | ((int)program [pc + 4] << 8))))) {
+                                                       pc += 5;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoUnicodeChar:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!((c == (program [pc + 1] | ((int)program [pc + 2] << 8))))) {
+                                                       pc += 3;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoCategoryAny:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!((c != '\n'))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoCategoryAnySingleline:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!(true)) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoCategoryWord:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!((Char.IsLetterOrDigit (c) || Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoCategoryDigit:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!((Char.IsDigit (c)))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoCategoryWhiteSpace:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!((Char.IsWhiteSpace (c)))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoCategoryEcmaWord:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!(('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_'))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoCategoryEcmaWhiteSpace:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!((c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoCategoryUnicodeSpecials:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!(('\uFEFF' <= c && c <= '\uFEFF' || '\uFFF0' <= c && c <= '\uFFFD'))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoCategoryUnicode:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!((Char.GetUnicodeCategory (c) == (UnicodeCategory)program [pc + 1]))) {
+                                                       pc += 2;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoCategoryGeneral:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               if (!((CategoryUtils.IsCategory ((Category)program [pc + 1], c)))) {
+                                                       pc += 2;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoBitmap:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               int c2 = (int)c; c2 -= program [pc + 1]; length = program [pc + 2];
+                                               if (!((c2 >= 0 && c2 < (length << 3) && (program [pc + 3 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       pc += 3 + program [pc + 2];
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoUnicodeBitmap:
+                                       if (strpos < string_end) {
+                                               char c = str [strpos];
+                                               int c2 = (int)c; c2 -= (program [pc + 1] | ((int)program [pc + 2] << 8)); length = (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                               if (!((c2 >= 0 && c2 < (length << 3) && (program [pc + 5 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       pc += 5 + (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoCharIgnoreCase:
+                                       if (strpos < string_end) {
+                                               char c = Char.ToLower (str [strpos]);
+                                               if (!((c == program [pc + 1]))) {
+                                                       pc += 2;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoRangeIgnoreCase:
+                                       if (strpos < string_end) {
+                                               char c = Char.ToLower (str [strpos]);
+                                               if (!((c >= program [pc + 1] && c <= program [pc + 2]))) {
+                                                       pc += 3;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoUnicodeRangeIgnoreCase:
+                                       if (strpos < string_end) {
+                                               char c = Char.ToLower (str [strpos]);
+                                               if (!((c >= (program [pc + 1] | ((int)program [pc + 2] << 8))) && (c <= (program [pc + 3] | ((int)program [pc + 4] << 8))))) {
+                                                       pc += 5;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
                                case RxOp.NoUnicodeCharIgnoreCase:
-                                       if (strpos < string_end && (Char.ToLower (str [strpos]) != (program [pc + 1] | (program [pc + 2] << 8)))) {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc += 3;
-                                               continue;
+                                       if (strpos < string_end) {
+                                               char c = Char.ToLower (str [strpos]);
+                                               if (!((c == (program [pc + 1] | ((int)program [pc + 2] << 8))))) {
+                                                       pc += 3;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoBitmapIgnoreCase:
+                                       if (strpos < string_end) {
+                                               char c = Char.ToLower (str [strpos]);
+                                               int c2 = (int)c; c2 -= program [pc + 1]; length = program [pc + 2];
+                                               if (!((c2 >= 0 && c2 < (length << 3) && (program [pc + 3 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       pc += 3 + program [pc + 2];
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoUnicodeBitmapIgnoreCase:
+                                       if (strpos < string_end) {
+                                               char c = Char.ToLower (str [strpos]);
+                                               int c2 = (int)c; c2 -= (program [pc + 1] | ((int)program [pc + 2] << 8)); length = (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                               if (!((c2 >= 0 && c2 < (length << 3) && (program [pc + 5 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       pc += 5 + (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos ++;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.CharReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (((c == program [pc + 1]))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 2;
+                                                       continue;
+                                               }
+                                       }
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 2;
+                                       continue;
+                               case RxOp.RangeReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (((c >= program [pc + 1] && c <= program [pc + 2]))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 3;
+                                                       continue;
+                                               }
+                                       }
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 3;
+                                       continue;
+                               case RxOp.UnicodeRangeReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (((c >= (program [pc + 1] | ((int)program [pc + 2] << 8))) && (c <= (program [pc + 3] | ((int)program [pc + 4] << 8))))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 5;
+                                                       continue;
+                                               }
+                                       }
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 5;
+                                       continue;
+                               case RxOp.UnicodeCharReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (((c == (program [pc + 1] | ((int)program [pc + 2] << 8))))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 3;
+                                                       continue;
+                                               }
+                                       }
+                                       if (char_group_end == 0)
+                                               return false;
+                                       pc += 3;
+                                       continue;
+                               case RxOp.CategoryAnyReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (((c != '\n'))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 1;
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc += 3;
+                                       pc += 1;
                                        continue;
-
-                                       /* CategoryAny */
-
-                               case RxOp.CategoryAny:
-                                       if (strpos < string_end && str [strpos] != '\n') {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
+                               case RxOp.CategoryAnySinglelineReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if ((true)) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 1;
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 1;
                                        continue;
-
-                                       /* CategoryAnySingleline */
-
-                               case RxOp.CategoryAnySingleline:
-                                       if (strpos < string_end) {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
+                               case RxOp.CategoryWordReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (((Char.IsLetterOrDigit (c) || Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 1;
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 1;
                                        continue;
-
-                                       /* CategoryWord */
-
-                               case RxOp.CategoryWord:
-                                       if (strpos < string_end) {
-                                               char c = str [strpos];
-                                               if (Char.IsLetterOrDigit (c) || Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation) {
-                                                       strpos++;
+                               case RxOp.CategoryDigitReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (((Char.IsDigit (c)))) {
+                                                       strpos --;
                                                        if (char_group_end != 0)
                                                                goto test_char_group_passed;
-                                                       pc++;
+                                                       pc += 1;
                                                        continue;
                                                }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 1;
                                        continue;
-                               case RxOp.NoCategoryWord:
-                                       if (strpos < string_end) {
-                                               char c = str [strpos];
-                                               if (!Char.IsLetterOrDigit (c) && Char.GetUnicodeCategory (c) != UnicodeCategory.ConnectorPunctuation) {
-                                                       strpos++;
+                               case RxOp.CategoryWhiteSpaceReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (((Char.IsWhiteSpace (c)))) {
+                                                       strpos --;
                                                        if (char_group_end != 0)
                                                                goto test_char_group_passed;
-                                                       pc++;
+                                                       pc += 1;
                                                        continue;
                                                }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 1;
                                        continue;
-
-                                       /* CategoryDigit */
-
-                               case RxOp.CategoryDigit:
-                                       if (strpos < string_end && Char.IsDigit (str [strpos])) {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
+                               case RxOp.CategoryEcmaWordReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if ((('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_'))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 1;
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 1;
                                        continue;
-                               case RxOp.NoCategoryDigit:
-                                       if (strpos < string_end && !Char.IsDigit (str [strpos])) {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
+                               case RxOp.CategoryEcmaWhiteSpaceReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (((c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 1;
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 1;
                                        continue;
-
-                                       /* CategoryWhiteSpace */
-
-                               case RxOp.CategoryWhiteSpace:
-                                       if (strpos < string_end && Char.IsWhiteSpace (str [strpos])) {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
+                               case RxOp.CategoryUnicodeSpecialsReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if ((('\uFEFF' <= c && c <= '\uFEFF' || '\uFFF0' <= c && c <= '\uFFFD'))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 1;
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 1;
                                        continue;
-                               case RxOp.NoCategoryWhiteSpace:
-                                       if (strpos < string_end && !Char.IsWhiteSpace (str [strpos])) {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
+                               case RxOp.CategoryUnicodeReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (((Char.GetUnicodeCategory (c) == (UnicodeCategory)program [pc + 1]))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 2;
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 2;
                                        continue;
-
-                                       /* CategoryEcmaWord */
-
-                               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++;
+                               case RxOp.CategoryGeneralReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (((CategoryUtils.IsCategory ((Category)program [pc + 1], c)))) {
+                                                       strpos --;
                                                        if (char_group_end != 0)
                                                                goto test_char_group_passed;
-                                                       pc++;
+                                                       pc += 2;
                                                        continue;
                                                }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 2;
                                        continue;
-                               case RxOp.NoCategoryEcmaWord:
-                                       if (strpos < string_end) {
-                                               int c = str [strpos];
-                                               if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_') {
-                                                       if (char_group_end == 0)
-                                                               return false;
-                                                       pc++;
+                               case RxOp.BitmapReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               int c2 = (int)c; c2 -= program [pc + 1]; length = program [pc + 2];
+                                               if (((c2 >= 0 && c2 < (length << 3) && (program [pc + 3 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 3 + program [pc + 2];
                                                        continue;
                                                }
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 3 + program [pc + 2];
                                        continue;
-
-                                       /* CategoryEcmaWhiteSpace */
-
-                               case RxOp.CategoryEcmaWhiteSpace:
-                                       if (strpos < string_end) {
-                                               int c = str [strpos];
-                                               if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v') {
-                                                       strpos++;
+                               case RxOp.UnicodeBitmapReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               int c2 = (int)c; c2 -= (program [pc + 1] | ((int)program [pc + 2] << 8)); length = (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                               if (((c2 >= 0 && c2 < (length << 3) && (program [pc + 5 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       strpos --;
                                                        if (char_group_end != 0)
                                                                goto test_char_group_passed;
-                                                       pc++;
+                                                       pc += 5 + (program [pc + 3] | ((int)program [pc + 4] << 8));
                                                        continue;
                                                }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 5 + (program [pc + 3] | ((int)program [pc + 4] << 8));
                                        continue;
-                               case RxOp.NoCategoryEcmaWhiteSpace:
-                                       if (strpos < string_end) {
-                                               int c = str [strpos];
-                                               if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v') {
-                                                       if (char_group_end == 0)
-                                                               return false;
-                                                       pc++;
+                               case RxOp.CharIgnoreCaseReverse:
+                                       if (strpos > 0) {
+                                               char c = Char.ToLower (str [strpos - 1]);
+                                               if (((c == program [pc + 1]))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 2;
                                                        continue;
                                                }
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 2;
                                        continue;
-
-                                       /* CategoryUnicodeSpecials */
-
-                               case RxOp.CategoryUnicodeSpecials:
-                                       if (strpos < string_end) {
-                                               int c = str [strpos];
-                                               if ('\uFEFF' <= c && c <= '\uFEFF' || '\uFFF0' <= c && c <= '\uFFFD') {
-                                                       strpos++;
+                               case RxOp.RangeIgnoreCaseReverse:
+                                       if (strpos > 0) {
+                                               char c = Char.ToLower (str [strpos - 1]);
+                                               if (((c >= program [pc + 1] && c <= program [pc + 2]))) {
+                                                       strpos --;
                                                        if (char_group_end != 0)
                                                                goto test_char_group_passed;
-                                                       pc++;
+                                                       pc += 3;
                                                        continue;
                                                }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 3;
                                        continue;
-                               case RxOp.NoCategoryUnicodeSpecials:
-                                       if (strpos < string_end) {
-                                               int c = str [strpos];
-                                               if ('\uFEFF' <= c && c <= '\uFEFF' || '\uFFF0' <= c && c <= '\uFFFD') {
-                                                       if (char_group_end == 0)
-                                                               return false;
-                                                       pc++;
+                               case RxOp.UnicodeRangeIgnoreCaseReverse:
+                                       if (strpos > 0) {
+                                               char c = Char.ToLower (str [strpos - 1]);
+                                               if (((c >= (program [pc + 1] | ((int)program [pc + 2] << 8))) && (c <= (program [pc + 3] | ((int)program [pc + 4] << 8))))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 5;
                                                        continue;
                                                }
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc++;
+                                       pc += 5;
                                        continue;
-
-                                       /* CategoryUnicode */
-
-                               case RxOp.CategoryUnicode:
-                                       if (strpos < string_end && Char.GetUnicodeCategory (str [strpos]) == (UnicodeCategory)program [pc + 1]) {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc += 2;
-                                               continue;
+                               case RxOp.UnicodeCharIgnoreCaseReverse:
+                                       if (strpos > 0) {
+                                               char c = Char.ToLower (str [strpos - 1]);
+                                               if (((c == (program [pc + 1] | ((int)program [pc + 2] << 8))))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 3;
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc += 2;
+                                       pc += 3;
                                        continue;
-                               case RxOp.NoCategoryUnicode:
-                                       if (strpos < string_end && Char.GetUnicodeCategory (str [strpos]) != (UnicodeCategory)program [pc + 1]) {
-                                               strpos++;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc += 2;
-                                               continue;
+                               case RxOp.BitmapIgnoreCaseReverse:
+                                       if (strpos > 0) {
+                                               char c = Char.ToLower (str [strpos - 1]);
+                                               int c2 = (int)c; c2 -= program [pc + 1]; length = program [pc + 2];
+                                               if (((c2 >= 0 && c2 < (length << 3) && (program [pc + 3 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 3 + program [pc + 2];
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc += 2;
+                                       pc += 3 + program [pc + 2];
                                        continue;
-
-                                       /*
-                                        * Reverse versions of the above opcodes.
-                                        */
-
-                               case RxOp.CharReverse:
-                                       if (strpos > 0 && (str [strpos - 1] == program [pc + 1])) {
-                                               strpos --;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc += 2;
-                                               continue;
+                               case RxOp.UnicodeBitmapIgnoreCaseReverse:
+                                       if (strpos > 0) {
+                                               char c = Char.ToLower (str [strpos - 1]);
+                                               int c2 = (int)c; c2 -= (program [pc + 1] | ((int)program [pc + 2] << 8)); length = (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                               if (((c2 >= 0 && c2 < (length << 3) && (program [pc + 5 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       strpos --;
+                                                       if (char_group_end != 0)
+                                                               goto test_char_group_passed;
+                                                       pc += 5 + (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                                       continue;
+                                               }
                                        }
                                        if (char_group_end == 0)
                                                return false;
-                                       pc += 2;
+                                       pc += 5 + (program [pc + 3] | ((int)program [pc + 4] << 8));
                                        continue;
                                case RxOp.NoCharReverse:
-                                       if (strpos > 0 && (str [strpos - 1] != program [pc + 1])) {
-                                               pc += 2;
-                                               if ((char_group_end == 0) || (pc + 1 == char_group_end))
-                                                       strpos --;
-                                               continue;
-                                       } else {
-                                               return false;
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (!((c == program [pc + 1]))) {
+                                                       pc += 2;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
                                        }
-                               case RxOp.RangeReverse:
+                                       return false;
+                               case RxOp.NoRangeReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (!((c >= program [pc + 1] && c <= program [pc + 2]))) {
+                                                       pc += 3;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoUnicodeRangeReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (!((c >= (program [pc + 1] | ((int)program [pc + 2] << 8))) && (c <= (program [pc + 3] | ((int)program [pc + 4] << 8))))) {
+                                                       pc += 5;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
+                                       }
+                                       return false;
+                               case RxOp.NoUnicodeCharReverse:
                                        if (strpos > 0) {
-                                               int c = str [strpos - 1];
-                                               if (c >= program [pc + 1] && c <= program [pc + 2]) {
+                                               char c = str [strpos - 1];
+                                               if (!((c == (program [pc + 1] | ((int)program [pc + 2] << 8))))) {
                                                        pc += 3;
-                                                       strpos--;
-                                                       if (char_group_end != 0)
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
                                                                goto test_char_group_passed;
+                                                       }
                                                        continue;
                                                }
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc += 3;
-                                       continue;
-                               case RxOp.NoRangeReverse:
+                                       return false;
+                               case RxOp.NoCategoryAnyReverse:
                                        if (strpos > 0) {
-                                               int c = str [strpos - 1];
-                                               if (!(c >= program [pc + 1] && c <= program [pc + 2])) {
-                                                       pc += 3;
-                                                       if ((char_group_end == 0 || (pc + 1 == char_group_end)))
+                                               char c = str [strpos - 1];
+                                               if (!((c != '\n'))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
                                                                strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
                                                        continue;
                                                }
                                        }
                                        return false;
-                               case RxOp.BitmapReverse:
+                               case RxOp.NoCategoryAnySinglelineReverse:
                                        if (strpos > 0) {
-                                               int c = str [strpos - 1];
-                                               c -= program [pc + 1];
-                                               length = program [pc + 2];
-                                               if (c < 0 || c >= (length << 3)) {
-                                                       if (char_group_end == 0)
-                                                               return false;
-                                                       pc += length + 3;
+                                               char c = str [strpos - 1];
+                                               if (!(true)) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
                                                        continue;
                                                }
-                                               pc += 3;
-                                               if ((program [pc + (c >> 3)] & (1 << (c & 0x7))) != 0) {
-                                                       strpos--;
-                                                       if (char_group_end != 0)
+                                       }
+                                       return false;
+                               case RxOp.NoCategoryWordReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (!((Char.IsLetterOrDigit (c) || Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
                                                                goto test_char_group_passed;
-                                                       pc += length;
+                                                       }
                                                        continue;
                                                }
-                                               if (char_group_end == 0)
-                                                       return false;
-                                               pc += length;
-                                               continue;
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc += 3 + program [pc + 2];
-                                       continue;
-                               case RxOp.NoBitmapReverse:
+                                       return false;
+                               case RxOp.NoCategoryDigitReverse:
                                        if (strpos > 0) {
-                                               int c = str [strpos - 1];
-                                               c -= program [pc + 1];
-                                               length = program [pc + 2];
-                                               if (c < 0 || c >= (length << 3)) {
-                                                       pc += 3 + length;
-                                                       if ((char_group_end == 0 || (pc + 1 == char_group_end)))
-                                                               strpos--;
-                                                       continue;
-                                               }
-                                               pc += 3;
-                                               if ((program [pc + (c >> 3)] & (1 << (c & 0x7))) != 0) {
-                                                       if (char_group_end == 0)
-                                                               return false;
-                                                       pc += length;
-                                                       continue;
-                                               } else {
-                                                       pc += length;
-                                                       if ((char_group_end == 0 || (pc + 1 == char_group_end)))
-                                                               strpos--;
+                                               char c = str [strpos - 1];
+                                               if (!((Char.IsDigit (c)))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
                                                        continue;
                                                }
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc += 3 + program [pc + 2];
-                                       continue;
-                               case RxOp.CategoryAnyReverse:
-                                       if (strpos > 0 && str [strpos - 1] != '\n') {
-                                               strpos --;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
-                                       }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.CategoryAnySinglelineReverse:
+                                       return false;
+                               case RxOp.NoCategoryWhiteSpaceReverse:
                                        if (strpos > 0) {
-                                               strpos --;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
+                                               char c = str [strpos - 1];
+                                               if (!((Char.IsWhiteSpace (c)))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.CategoryWordReverse:
+                                       return false;
+                               case RxOp.NoCategoryEcmaWordReverse:
                                        if (strpos > 0) {
                                                char c = str [strpos - 1];
-                                               if (Char.IsLetterOrDigit (c) || Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation) {
-                                                       strpos --;
-                                                       if (char_group_end != 0)
+                                               if (!(('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_'))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
                                                                goto test_char_group_passed;
-                                                       pc++;
+                                                       }
                                                        continue;
                                                }
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.NoCategoryWordReverse:
+                                       return false;
+                               case RxOp.NoCategoryEcmaWhiteSpaceReverse:
                                        if (strpos > 0) {
                                                char c = str [strpos - 1];
-                                               if (!Char.IsLetterOrDigit (c) && Char.GetUnicodeCategory (c) != UnicodeCategory.ConnectorPunctuation) {
-                                                       strpos --;
-                                                       if (char_group_end != 0)
+                                               if (!((c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
                                                                goto test_char_group_passed;
-                                                       pc++;
+                                                       }
                                                        continue;
                                                }
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.CategoryDigitReverse:
-                                       if (strpos > 0 && Char.IsDigit (str [strpos - 1])) {
-                                               strpos --;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
-                                       }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.NoCategoryDigitReverse:
-                                       if (strpos > 0 && !Char.IsDigit (str [strpos - 1])) {
-                                               strpos --;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
+                                       return false;
+                               case RxOp.NoCategoryUnicodeSpecialsReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (!(('\uFEFF' <= c && c <= '\uFEFF' || '\uFFF0' <= c && c <= '\uFFFD'))) {
+                                                       pc += 1;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.CategoryWhiteSpaceReverse:
-                                       if (strpos > 0 && Char.IsWhiteSpace (str [strpos - 1])) {
-                                               strpos --;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
+                                       return false;
+                               case RxOp.NoCategoryUnicodeReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (!((Char.GetUnicodeCategory (c) == (UnicodeCategory)program [pc + 1]))) {
+                                                       pc += 2;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.NoCategoryWhiteSpaceReverse:
-                                       if (strpos > 0 && !Char.IsWhiteSpace (str [strpos - 1])) {
-                                               strpos --;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
+                                       return false;
+                               case RxOp.NoCategoryGeneralReverse:
+                                       if (strpos > 0) {
+                                               char c = str [strpos - 1];
+                                               if (!((CategoryUtils.IsCategory ((Category)program [pc + 1], c)))) {
+                                                       pc += 2;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.CategoryEcmaWordReverse:
+                                       return false;
+                               case RxOp.NoBitmapReverse:
                                        if (strpos > 0) {
-                                               int c = str [strpos - 1];
-                                               if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_') {
-                                                       strpos --;
-                                                       if (char_group_end != 0)
+                                               char c = str [strpos - 1];
+                                               int c2 = (int)c; c2 -= program [pc + 1]; length = program [pc + 2];
+                                               if (!((c2 >= 0 && c2 < (length << 3) && (program [pc + 3 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       pc += 3 + program [pc + 2];
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
                                                                goto test_char_group_passed;
-                                                       pc++;
+                                                       }
                                                        continue;
                                                }
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.NoCategoryEcmaWordReverse:
+                                       return false;
+                               case RxOp.NoUnicodeBitmapReverse:
                                        if (strpos > 0) {
-                                               int c = str [strpos - 1];
-                                               if ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_') {
-                                                       if (char_group_end == 0)
-                                                               return false;
-                                                       pc++;
+                                               char c = str [strpos - 1];
+                                               int c2 = (int)c; c2 -= (program [pc + 1] | ((int)program [pc + 2] << 8)); length = (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                               if (!((c2 >= 0 && c2 < (length << 3) && (program [pc + 5 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       pc += 5 + (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
                                                        continue;
                                                }
-                                               strpos --;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.CategoryEcmaWhiteSpaceReverse:
+                                       return false;
+                               case RxOp.NoCharIgnoreCaseReverse:
                                        if (strpos > 0) {
-                                               int c = str [strpos - 1];
-                                               if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v') {
-                                                       strpos --;
-                                                       if (char_group_end != 0)
+                                               char c = Char.ToLower (str [strpos - 1]);
+                                               if (!((c == program [pc + 1]))) {
+                                                       pc += 2;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
                                                                goto test_char_group_passed;
-                                                       pc++;
+                                                       }
                                                        continue;
                                                }
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.NoCategoryEcmaWhiteSpaceReverse:
+                                       return false;
+                               case RxOp.NoRangeIgnoreCaseReverse:
                                        if (strpos > 0) {
-                                               int c = str [strpos - 1];
-                                               if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v') {
-                                                       if (char_group_end == 0)
-                                                               return false;
-                                                       pc++;
+                                               char c = Char.ToLower (str [strpos - 1]);
+                                               if (!((c >= program [pc + 1] && c <= program [pc + 2]))) {
+                                                       pc += 3;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
                                                        continue;
                                                }
-                                               strpos --;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.CategoryUnicodeSpecialsReverse:
+                                       return false;
+                               case RxOp.NoUnicodeRangeIgnoreCaseReverse:
                                        if (strpos > 0) {
-                                               int c = str [strpos - 1];
-                                               if ('\uFEFF' <= c && c <= '\uFEFF' || '\uFFF0' <= c && c <= '\uFFFD') {
-                                                       strpos --;
-                                                       if (char_group_end != 0)
+                                               char c = Char.ToLower (str [strpos - 1]);
+                                               if (!((c >= (program [pc + 1] | ((int)program [pc + 2] << 8))) && (c <= (program [pc + 3] | ((int)program [pc + 4] << 8))))) {
+                                                       pc += 5;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
                                                                goto test_char_group_passed;
-                                                       pc++;
+                                                       }
                                                        continue;
                                                }
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.NoCategoryUnicodeSpecialsReverse:
+                                       return false;
+                               case RxOp.NoUnicodeCharIgnoreCaseReverse:
                                        if (strpos > 0) {
-                                               int c = str [strpos - 1];
-                                               if ('\uFEFF' <= c && c <= '\uFEFF' || '\uFFF0' <= c && c <= '\uFFFD') {
-                                                       if (char_group_end == 0)
-                                                               return false;
-                                                       pc++;
+                                               char c = Char.ToLower (str [strpos - 1]);
+                                               if (!((c == (program [pc + 1] | ((int)program [pc + 2] << 8))))) {
+                                                       pc += 3;
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
                                                        continue;
                                                }
-                                               strpos --;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc++;
-                                               continue;
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc++;
-                                       continue;
-                               case RxOp.CategoryUnicodeReverse:
-                                       if (strpos > 0 && Char.GetUnicodeCategory (str [strpos - 1]) == (UnicodeCategory)program [pc + 1]) {
-                                               strpos --;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc += 2;
-                                               continue;
+                                       return false;
+                               case RxOp.NoBitmapIgnoreCaseReverse:
+                                       if (strpos > 0) {
+                                               char c = Char.ToLower (str [strpos - 1]);
+                                               int c2 = (int)c; c2 -= program [pc + 1]; length = program [pc + 2];
+                                               if (!((c2 >= 0 && c2 < (length << 3) && (program [pc + 3 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       pc += 3 + program [pc + 2];
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc += 2;
-                                       continue;
-                               case RxOp.NoCategoryUnicodeReverse:
-                                       if (strpos > 0 && Char.GetUnicodeCategory (str [strpos - 1]) != (UnicodeCategory)program [pc + 1]) {
-                                               strpos --;
-                                               if (char_group_end != 0)
-                                                       goto test_char_group_passed;
-                                               pc += 2;
-                                               continue;
+                                       return false;
+                               case RxOp.NoUnicodeBitmapIgnoreCaseReverse:
+                                       if (strpos > 0) {
+                                               char c = Char.ToLower (str [strpos - 1]);
+                                               int c2 = (int)c; c2 -= (program [pc + 1] | ((int)program [pc + 2] << 8)); length = (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                               if (!((c2 >= 0 && c2 < (length << 3) && (program [pc + 5 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0))) {
+                                                       pc += 5 + (program [pc + 3] | ((int)program [pc + 4] << 8));
+                                                       if (char_group_end == 0 || (pc + 1 == char_group_end)) {
+                                                               strpos --;
+                                                       if (pc + 1 == char_group_end)
+                                                               goto test_char_group_passed;
+                                                       }
+                                                       continue;
+                                               }
                                        }
-                                       if (char_group_end == 0)
-                                               return false;
-                                       pc += 2;
-                                       continue;
+                                       return false;
+                               
+                               // END OF GENERATED CODE
 
                                case RxOp.Branch: {
                                        int res = 0;
@@ -1616,8 +2148,8 @@ namespace System.Text.RegularExpressions {
                                                strpos_result = res;
                                                return true;
                                        }
-                                       //Console.WriteLine ("branch offset: {0}", program [pc + 1] | (program [pc + 2] << 8));
-                                       pc += program [pc + 1] | (program [pc + 2] << 8);
+                                       //Console.WriteLine ("branch offset: {0}", program [pc + 1] | ((int)program [pc + 2] << 8));
+                                       pc += program [pc + 1] | ((int)program [pc + 2] << 8);
                                        continue;
                                }
                                case RxOp.Repeat:
@@ -1647,7 +2179,7 @@ namespace System.Text.RegularExpressions {
                                                pc + 11                         // subexpression
                                        );
 
-                                       int until = pc + program [pc + 1] | (program [pc + 2] << 8);
+                                       int until = pc + (program [pc + 1] | ((int)program [pc + 2] << 8));
                                        if (!EvalByteCode (until, strpos, ref res)) {
                                                this.repeat = this.repeat.Previous;
                                                return false;
@@ -1805,7 +2337,7 @@ namespace System.Text.RegularExpressions {
                                         */
                                        bool lazy = program [pc] == (byte)RxOp.FastRepeatLazy;
                                        int res = 0;
-                                       int tail = pc + program [pc + 1] | (program [pc + 2] << 8);
+                                       int tail = pc + (program [pc + 1] | ((int)program [pc + 2] << 8));
                                        start = ReadInt (program, pc + 3);
                                        end = ReadInt (program, pc + 7);
                                        //Console.WriteLine ("min: {0}, max: {1} tail: {2}", start, end, tail);
@@ -1901,4 +2433,3 @@ namespace System.Text.RegularExpressions {
                }
        }
 }
-