Remove excessive shortcut key matching in ToolStrip
[mono.git] / mcs / class / System / System.Text.RegularExpressions / gen-interp.cs
1 //
2 // This file is not part of the build. It is used to generate the character related
3 // opcodes in RxInterpreter.cs.
4 //
5
6 using System;
7
8 class Op {
9         public string name, body, cond, len;
10
11         public Op (string name, string body, string cond, string len) {
12                 this.name = name;
13                 this.body = body;
14                 this.cond = cond;
15                 this.len = len;
16         }
17 }
18
19 public class GenInterp
20 {
21         public static int base_indent;
22
23         public static void write (int indent, string format, params string[] args) {
24                 for (int i = 0; i < base_indent + indent; ++i)
25                         Console.Write ("\t");
26                 Console.WriteLine (format, args);
27         }
28
29         public static void Main () {
30                 base_indent = 4;
31
32                 write (0, "// GENERATED BY gen-interp.cs, DO NOT MODIFY");
33
34                 Op[] ops = new Op [] {
35
36                         new Op ("Char", "", "(c == program [pc + 1])", "2"),
37                         new Op ("Range", "", "(c >= program [pc + 1] && c <= program [pc + 2])", "3"),
38                         new Op ("UnicodeRange", "", "(c >= (program [pc + 1] | ((int)program [pc + 2] << 8))) && (c <= (program [pc + 3] | ((int)program [pc + 4] << 8)))", "5"),
39                         new Op ("UnicodeChar", "", "(c == (program [pc + 1] | ((int)program [pc + 2] << 8)))", "3"),
40                         new Op ("CategoryAny", "", @"(c != '\n')", "1"),
41                         new Op ("CategoryAnySingleline", "", "true", "1"),
42                         new Op ("CategoryWord", "", "(Char.IsLetterOrDigit (c) || Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation)", "1"),
43                         new Op ("CategoryDigit", "", "(Char.IsDigit (c))", "1"),
44                         new Op ("CategoryWhiteSpace", "", "(Char.IsWhiteSpace (c))", "1"),
45                         new Op ("CategoryEcmaWord", "", "('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_')", "1"),
46                         new Op ("CategoryEcmaWhiteSpace", "", @"(c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v')", "1"),
47                         new Op ("CategoryUnicodeSpecials", "", @"('\uFEFF' <= c && c <= '\uFEFF' || '\uFFF0' <= c && c <= '\uFFFD')", "1"),
48                         new Op ("CategoryUnicode", "", "(Char.GetUnicodeCategory (c) == (UnicodeCategory)program [pc + 1])", "2"),
49                         new Op ("CategoryGeneral", "", "(CategoryUtils.IsCategory ((Category)program [pc + 1], c))", "2"),
50                         new Op ("Bitmap", "int c2 = (int)c; c2 -= program [pc + 1]; length = program [pc + 2];", "(c2 >= 0 && c2 < (length << 3) && (program [pc + 3 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0)", "3 + program [pc + 2]"),
51                         new Op ("UnicodeBitmap", "int c2 = (int)c; c2 -= (program [pc + 1] | ((int)program [pc + 2] << 8)); length = (program [pc + 3] | ((int)program [pc + 4] << 8));", "(c2 >= 0 && c2 < (length << 3) && (program [pc + 5 + (c2 >> 3)] & (1 << (c2 & 0x7))) != 0)", "5 + (program [pc + 3] | ((int)program [pc + 4] << 8))")
52                 };
53
54                 for (int i1 = 0; i1 < 2; ++i1) {
55                         for (int i2 = 0; i2 < 2; ++i2) {
56                                 for (int i3 = 0; i3 < 2; ++i3) {
57                                         bool reverse = (i1 == 1);
58                                         bool revert = (i2 == 1);
59                                         bool ignore = (i3 == 1);
60
61                                         foreach (Op op in ops) {
62                                                 if (op.name.StartsWith ("Category") && ignore)
63                                                         // These have no IgnoreCase versions
64                                                         continue;
65
66                                                 if (i1 == 0 && i2 == 0 && i3 == 0) {
67                                                         write (0, "");
68                                                         write (0, "/* {0} */", op.name);
69                                                         write (0, "");
70                                                 }                                               
71
72                                                 write (0, "case RxOp.{0}{1}{2}{3}:", revert ? "No" : "", op.name, ignore ? "IgnoreCase" : "", reverse ? "Reverse" : "");
73                                                 if (reverse)
74                                                         write (1, "if (strpos > 0) {{");
75                                                 else
76                                                         write (1, "if (strpos < string_end) {{");
77                                                 if (!ignore) {
78                                                         if (reverse)
79                                                                 write (2, "char c = str [strpos - 1];");
80                                                         else
81                                                                 write (2, "char c = str [strpos];");
82                                                 } else {
83                                                         if (reverse)
84                                                                 write (2, "char c = Char.ToLower (str [strpos - 1]);");
85                                                         else
86                                                                 write (2, "char c = Char.ToLower (str [strpos]);");
87                                                 }
88                                                 if (op.body != String.Empty)
89                                                         write (2, op.body);
90                                                 write (2, "if ({0}({1})) {{", revert ? "!" : "", op.cond);
91                                                 // TRUE case
92                                                 if (!revert) {
93                                                         if (!reverse)
94                                                                 write (3, "strpos ++;");
95                                                         else
96                                                                 write (3, "strpos --;");
97                                                         write (3, "if (char_group_end != 0)");
98                                                         write (4, "goto test_char_group_passed;");
99                                                         write (3, "pc += {0};", "" + op.len);
100                                                         write (3, "continue;");
101                                                 } else {
102                                                         /*
103                                                          * If we are inside a char group, the cases are ANDed 
104                                                          * together, so we have to continue checking the
105                                                          * other cases, and we need to increase strpos after 
106                                                          * the final check.
107                                                          * The char group is termined by a True, hence the
108                                                          * + 1 below.
109                                                          */
110                                                         write (3, "pc += {0};", "" + op.len);
111                                                         write (3, "if (char_group_end == 0 || (pc + 1 == char_group_end)) {{");
112                                                         if (!reverse)
113                                                                 write (4, "strpos ++;");
114                                                         else
115                                                                 write (4, "strpos --;");
116                                                         write (3, "if (pc + 1 == char_group_end)");
117                                                         write (4, "goto test_char_group_passed;");
118                                                         write (3, "}}");
119                                                         write (3, "continue;");
120                                                 }
121                                                 write (2, "}}");
122                                                 write (1, "}}");
123
124                                                 // FALSE case                                                   
125                                                 if (!revert) {
126                                                         write (1, "if (char_group_end == 0)");
127                                                         write (2, "return false;");
128                                                         write (1, "pc += {0};", "" + op.len);
129                                                         write (1, "continue;");
130                                                 } else {
131                                                         /* Fail both inside and outside a char group */
132                                                         write (1, "return false;");
133                                                 }
134
135 #if FALSE
136                                                         if (strpos < string_end && (COND (str [strpos]))) {
137                                                         if (!revert) {
138                                                                 strpos ++;
139                                                                 if (char_group_end != 0)
140                                                                         goto test_char_group_passed;
141                                                                 pc += ins_len;
142                                                                 continue;
143                                                         } else {
144                                                                 /*
145                                                                  * If we are inside a char group, the cases are ANDed 
146                                                                  * together, so we have to continue checking the
147                                                                  * other cases, and we need to increase strpos after 
148                                                                  * the final check.
149                                                                  * The char group is termined by a True, hence the
150                                                                  * + 1 below.
151                                                                  * FIXME: Optimize this.
152                                                                  */
153                                                                 pc += ins_len;
154                                                                 if (char_group_end == 0 || (pc + 1 == char_group_end))
155                                                                         strpos ++;
156                                                                 continue;
157                                                         }
158                                                 } else {
159                                                         if (!revert) {
160                                                                 if (char_group_end == 0)
161                                                                         return false;
162                                                                 pc += ins_len;
163                                                                 continue;
164                                                         } else {
165                                                                 /* Fail both inside and outside a char group */
166                                                                 return false;
167                                                         }
168                                                 }
169                                         } else {
170                                                 // Same as above, but use:
171                                                 // - strpos > 0 instead of strpos < string_len
172                                                 // - COND (str [strpos - 1]) instead of COND (str [strpos])
173                                                 // - strpos -- instead of strpos ++
174                                         }
175 #endif
176                                         }
177                                 }
178                         }
179                 }
180
181         write (0, "");
182         write (0, "// END OF GENERATED CODE");
183         }
184 }