Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
RegexNode.cs
Go to the documentation of this file.
2
4
5internal sealed class RegexNode
6{
7 private object Children;
8
10
12
13 public int Type { get; private set; }
14
15 public string Str { get; private set; }
16
17 public char Ch { get; private set; }
18
19 public int M { get; private set; }
20
21 public int N { get; private set; }
22
24 {
25 Type = type;
27 }
28
30 {
31 Type = type;
33 Ch = ch;
34 }
35
36 public RegexNode(int type, RegexOptions options, string str)
37 {
38 Type = type;
40 Str = str;
41 }
42
44 {
45 Type = type;
47 M = m;
48 }
49
50 public RegexNode(int type, RegexOptions options, int m, int n)
51 {
52 Type = type;
54 M = m;
55 N = n;
56 }
57
58 public bool UseOptionR()
59 {
60 return (Options & RegexOptions.RightToLeft) != 0;
61 }
62
64 {
65 if (UseOptionR() && Type == 25 && ChildCount() > 1)
66 {
67 ((List<RegexNode>)Children).Reverse();
68 }
69 return this;
70 }
71
72 private void MakeRep(int type, int min, int max)
73 {
74 Type += type - 9;
75 M = min;
76 N = max;
77 }
78
79 private void MakeLoopAtomic()
80 {
81 switch (Type)
82 {
83 case 3:
84 Type = 43;
85 break;
86 case 4:
87 Type = 44;
88 break;
89 default:
90 Type = 45;
91 break;
92 }
93 }
94
96 {
97 if ((Options & RegexOptions.RightToLeft) == 0)
98 {
101 while (true)
102 {
103 RegexNode next;
104 switch (regexNode.Type)
105 {
106 case 25:
107 case 32:
108 goto IL_006f;
109 case 3:
110 if (regexNode.N != int.MaxValue)
111 {
112 break;
113 }
114 goto IL_00d4;
115 case 43:
116 if (regexNode.N != int.MaxValue)
117 {
118 break;
119 }
120 goto IL_00d4;
121 case 4:
122 if (regexNode.N != int.MaxValue)
123 {
124 break;
125 }
126 goto IL_00d4;
127 case 44:
128 if (regexNode.N != int.MaxValue)
129 {
130 break;
131 }
132 goto IL_00d4;
133 case 5:
134 if (regexNode.N != int.MaxValue)
135 {
136 break;
137 }
138 goto IL_00d4;
139 case 45:
140 {
141 if (regexNode.N != int.MaxValue)
142 {
143 break;
144 }
145 goto IL_00d4;
146 }
147 IL_00d4:
148 next = regexNode.Next;
149 if (next != null && next.Type == 25)
150 {
151 next.InsertChild(1, new RegexNode(46, regexNode.Options));
152 }
153 break;
154 }
155 break;
156 IL_006f:
157 regexNode = regexNode.Child(0);
158 }
159 }
160 while (Child(0).Type == 32)
161 {
162 ReplaceChild(0, Child(0).Child(0));
163 }
164 return this;
165 }
166
168 {
169 if (maxDepth == 0)
170 {
171 return;
172 }
173 while (true)
174 {
175 switch (node.Type)
176 {
177 case 3:
178 case 4:
179 case 5:
180 node.MakeLoopAtomic();
181 return;
182 case 25:
183 case 28:
184 {
185 RegexNode regexNode2 = node.Child(node.ChildCount() - 1);
186 if ((regexNode2.Type == 24 || regexNode2.Type == 26 || regexNode2.Type == 27) && (node.Next == null || node.Next.Type != 32))
187 {
188 RegexNode regexNode3 = new RegexNode(32, regexNode2.Options);
189 regexNode3.AddChild(regexNode2);
190 node.ReplaceChild(node.ChildCount() - 1, regexNode3);
191 }
193 break;
194 }
195 case 24:
196 {
197 int num = node.ChildCount();
198 for (int i = 1; i < num; i++)
199 {
201 }
202 node = node.Child(0);
203 break;
204 }
205 case 26:
206 {
208 if (regexNode != null)
209 {
210 node = regexNode;
211 break;
212 }
213 return;
214 }
215 default:
216 return;
217 }
218 }
219 }
220
221 public bool IsAtomicByParent()
222 {
223 RegexNode next = Next;
224 if (next == null)
225 {
226 return false;
227 }
228 if (next.Type == 32)
229 {
230 return true;
231 }
232 if ((next.Type != 25 && next.Type != 28) || next.Child(next.ChildCount() - 1) != this)
233 {
234 return false;
235 }
236 next = next.Next;
237 if (next != null)
238 {
239 return next.Type == 32;
240 }
241 return false;
242 }
243
245 {
246 switch (Type)
247 {
248 case 24:
249 return ReduceAlternation();
250 case 25:
251 return ReduceConcatenation();
252 case 26:
253 case 27:
254 return ReduceLoops();
255 case 32:
256 return ReduceAtomic();
257 case 29:
258 return ReduceGroup();
259 case 5:
260 case 8:
261 case 11:
262 case 45:
263 return ReduceSet();
264 default:
265 return this;
266 }
267 }
268
270 {
271 return ChildCount() switch
272 {
274 1 => Child(0),
275 _ => this,
276 };
277 }
278
280 {
281 RegexNode regexNode = this;
282 while (regexNode.Type == 29)
283 {
284 regexNode = regexNode.Child(0);
285 }
286 return regexNode;
287 }
288
290 {
291 RegexNode regexNode = this;
293 while (regexNode2.Type == 32)
294 {
296 regexNode2 = regexNode.Child(0);
297 }
298 switch (regexNode2.Type)
299 {
300 case 43:
301 case 44:
302 case 45:
303 return regexNode2;
304 case 3:
305 case 4:
306 case 5:
307 regexNode2.MakeLoopAtomic();
308 return regexNode2;
309 default:
311 return regexNode;
312 }
313 }
314
316 {
317 RegexNode regexNode = this;
318 int type = Type;
319 int num = M;
320 int num2 = N;
321 while (regexNode.ChildCount() > 0)
322 {
323 RegexNode regexNode2 = regexNode.Child(0);
324 if (regexNode2.Type != type)
325 {
326 bool flag = false;
327 if (type == 26)
328 {
329 int type2 = regexNode2.Type;
330 if ((uint)(type2 - 3) <= 2u || (uint)(type2 - 43) <= 2u)
331 {
332 flag = true;
333 }
334 }
335 else
336 {
337 int type3 = regexNode2.Type;
338 if ((uint)(type3 - 6) <= 2u)
339 {
340 flag = true;
341 }
342 }
343 if (!flag)
344 {
345 break;
346 }
347 }
348 if ((regexNode.M == 0 && regexNode2.M > 1) || regexNode2.N < regexNode2.M * 2)
349 {
350 break;
351 }
353 if (regexNode.M > 0)
354 {
355 num = (regexNode.M = ((2147483646 / regexNode.M < num) ? int.MaxValue : (regexNode.M * num)));
356 }
357 if (regexNode.N > 0)
358 {
359 num2 = (regexNode.N = ((2147483646 / regexNode.N < num2) ? int.MaxValue : (regexNode.N * num2)));
360 }
361 }
362 if (num == int.MaxValue)
363 {
364 return new RegexNode(22, Options);
365 }
366 if (regexNode.ChildCount() == 1)
367 {
368 RegexNode regexNode3 = regexNode.Child(0);
369 int type4 = regexNode3.Type;
370 if ((uint)(type4 - 9) <= 2u)
371 {
372 regexNode3.MakeRep((regexNode.Type == 27) ? 6 : 3, regexNode.M, regexNode.N);
374 }
375 }
376 return regexNode;
377 }
378
380 {
382 {
383 Type = 22;
384 Str = null;
385 }
387 {
389 Str = null;
390 Type = ((Type == 11) ? 9 : ((Type == 5) ? 3 : ((Type == 45) ? 43 : 6)));
391 }
393 {
395 Str = null;
396 Type = ((Type == 11) ? 10 : ((Type == 5) ? 4 : ((Type == 45) ? 44 : 7)));
397 }
398 return this;
399 }
400
402 {
403 switch (ChildCount())
404 {
405 case 0:
406 return new RegexNode(22, Options);
407 case 1:
408 return Child(0);
409 default:
410 {
413 if (regexNode == this)
414 {
415 return ExtractCommonPrefix();
416 }
417 return regexNode;
418 }
419 }
421 {
423 if ((Options & RegexOptions.RightToLeft) != 0)
424 {
425 return this;
426 }
428 if (regexNode2 == null)
429 {
430 return this;
431 }
433 string str = regexNode2.Str;
435 if (regexNode2.Type == 9)
436 {
437 Span<char> span = stackalloc char[1] { regexNode2.Ch };
439 }
440 else
441 {
443 }
445 for (int i = 1; i < list.Count; i++)
446 {
448 if (regexNode2 == null || regexNode2.Options != options)
449 {
450 return this;
451 }
452 if (regexNode2.Type == 9)
453 {
454 if (startingSpan2[0] != regexNode2.Ch)
455 {
456 return this;
457 }
458 if (startingSpan2.Length != 1)
459 {
460 startingSpan2 = startingSpan2.Slice(0, 1);
461 }
462 }
463 else
464 {
465 int num = Math.Min(startingSpan2.Length, regexNode2.Str.Length);
466 int j;
467 for (j = 0; j < num && startingSpan2[j] == regexNode2.Str[j]; j++)
468 {
469 }
470 if (j == 0)
471 {
472 return this;
473 }
474 startingSpan2 = startingSpan2.Slice(0, j);
475 }
476 }
477 for (int k = 0; k < list.Count; k++)
478 {
480 if (regexNode3.Type == 25)
481 {
483 ReplaceChild(k, regexNode3.Reduce());
484 }
485 else
486 {
488 }
489 }
490 for (int l = 0; l < list.Count; l++)
491 {
492 if (list[l].Type == 23)
493 {
494 int m = l + 1;
495 int num2 = m;
496 for (; m < list.Count; m++)
497 {
498 if (list[m].Type != 23)
499 {
500 if (num2 != m)
501 {
502 list[num2] = list[m];
503 }
504 num2++;
505 }
506 }
507 if (num2 < m)
508 {
509 list.RemoveRange(num2, m - num2);
510 }
511 break;
512 }
513 }
515 regexNode4.AddChild((startingSpan2.Length == 1) ? new RegexNode(9, options)
516 {
517 Ch = startingSpan2[0]
518 } : new RegexNode(12, options)
519 {
520 Str = ((str?.Length == startingSpan2.Length) ? str : startingSpan2.ToString())
521 });
522 regexNode4.AddChild(this);
523 return regexNode4;
524 }
526 {
527 if (branch.Type == 25)
528 {
529 branch = branch.Child(0);
530 }
531 if (branch.Type != 9 && branch.Type != 12)
532 {
533 return null;
534 }
535 return branch;
536 }
538 {
539 if (node.Type == 9)
540 {
541 node.Type = 23;
542 node.Ch = '\0';
543 }
544 else if (node.Str.Length == startingSpan.Length)
545 {
546 node.Type = 23;
547 node.Str = null;
548 }
549 else if (node.Str.Length - 1 == startingSpan.Length)
550 {
551 node.Type = 9;
552 node.Ch = node.Str[^1];
553 node.Str = null;
554 }
555 else
556 {
557 node.Str = node.Str.Substring(startingSpan.Length);
558 }
559 }
561 {
562 bool flag = false;
563 bool flag2 = false;
566 int n = 0;
567 int num3;
568 for (num3 = 0; n < list2.Count; n++, num3++)
569 {
571 if (num3 < n)
572 {
574 }
575 if (regexNode5.Type == 24)
576 {
577 if (regexNode5.Children is List<RegexNode> list3)
578 {
579 for (int num4 = 0; num4 < list3.Count; num4++)
580 {
581 list3[num4].Next = this;
582 }
583 list2.InsertRange(n + 1, list3);
584 }
585 else
586 {
588 regexNode6.Next = this;
589 list2.Insert(n + 1, regexNode6);
590 }
591 num3--;
592 }
593 else if (regexNode5.Type == 11 || regexNode5.Type == 9)
594 {
595 RegexOptions regexOptions2 = regexNode5.Options & (RegexOptions.IgnoreCase | RegexOptions.RightToLeft);
596 if (regexNode5.Type == 11)
597 {
599 {
600 flag = true;
603 continue;
604 }
605 }
606 else if (!flag || regexOptions != regexOptions2 || flag2)
607 {
608 flag = true;
609 flag2 = false;
611 continue;
612 }
613 num3--;
616 if (regexNode7.Type == 9)
617 {
619 regexCharClass.AddChar(regexNode7.Ch);
620 }
621 else
622 {
624 }
625 if (regexNode5.Type == 9)
626 {
627 regexCharClass.AddChar(regexNode5.Ch);
628 }
629 else
630 {
632 regexCharClass.AddCharClass(cc);
633 }
634 regexNode7.Type = 11;
635 regexNode7.Str = regexCharClass.ToStringClass();
636 }
637 else if (regexNode5.Type == 22)
638 {
639 num3--;
640 }
641 else
642 {
643 flag = false;
644 flag2 = false;
645 }
646 }
647 if (num3 < n)
648 {
649 list2.RemoveRange(num3, n - num3);
650 }
651 }
652 }
653
655 {
656 switch (ChildCount())
657 {
658 case 0:
659 return new RegexNode(23, Options);
660 case 1:
661 return Child(0);
662 default:
665 if ((Options & RegexOptions.RightToLeft) == 0)
666 {
668 }
669 return ReplaceNodeIfUnnecessary(23);
670 }
671 }
672
674 {
675 bool flag = false;
678 int num = 0;
679 int num2 = 0;
680 while (num < list.Count)
681 {
682 RegexNode regexNode = list[num];
683 if (num2 < num)
684 {
686 }
687 if (regexNode.Type == 25 && (regexNode.Options & RegexOptions.RightToLeft) == (Options & RegexOptions.RightToLeft))
688 {
689 if (regexNode.Children is List<RegexNode> list2)
690 {
691 for (int i = 0; i < list2.Count; i++)
692 {
693 list2[i].Next = this;
694 }
695 list.InsertRange(num + 1, list2);
696 }
697 else
698 {
700 regexNode2.Next = this;
701 list.Insert(num + 1, regexNode2);
702 }
703 num2--;
704 }
705 else if (regexNode.Type == 12 || regexNode.Type == 9)
706 {
707 RegexOptions regexOptions2 = regexNode.Options & (RegexOptions.IgnoreCase | RegexOptions.RightToLeft);
708 if (!flag || regexOptions != regexOptions2)
709 {
710 flag = true;
712 }
713 else
714 {
716 if (regexNode3.Type == 9)
717 {
718 regexNode3.Type = 12;
719 regexNode3.Str = regexNode3.Ch.ToString();
720 }
721 if ((regexOptions2 & RegexOptions.RightToLeft) == 0)
722 {
723 regexNode3.Str = ((regexNode.Type == 9) ? $"{regexNode3.Str}{regexNode.Ch}" : (regexNode3.Str + regexNode.Str));
724 }
725 else
726 {
727 regexNode3.Str = ((regexNode.Type == 9) ? $"{regexNode.Ch}{regexNode3.Str}" : (regexNode.Str + regexNode3.Str));
728 }
729 }
730 }
731 else if (regexNode.Type == 23)
732 {
733 num2--;
734 }
735 else
736 {
737 flag = false;
738 }
739 num++;
740 num2++;
741 }
742 if (num2 < num)
743 {
744 list.RemoveRange(num2, num - num2);
745 }
746 }
747
749 {
751 int index = 0;
752 int num = 1;
753 int num2 = 1;
754 while (num < list.Count)
755 {
758 if (regexNode.Options == regexNode2.Options)
759 {
760 switch (regexNode.Type)
761 {
762 case 3:
763 if (regexNode2.Type == 3 && regexNode.Ch == regexNode2.Ch)
764 {
765 goto IL_01de;
766 }
767 if (regexNode2.Type != 9 || regexNode.Ch != regexNode2.Ch)
768 {
769 break;
770 }
771 goto IL_03b2;
772 case 43:
773 if (regexNode2.Type == 43 && regexNode.Ch == regexNode2.Ch)
774 {
775 goto IL_01de;
776 }
777 if (regexNode2.Type != 9 || regexNode.Ch != regexNode2.Ch)
778 {
779 break;
780 }
781 goto IL_03b2;
782 case 6:
783 if (regexNode2.Type == 6 && regexNode.Ch == regexNode2.Ch)
784 {
785 goto IL_01de;
786 }
787 if (regexNode2.Type != 9 || regexNode.Ch != regexNode2.Ch)
788 {
789 break;
790 }
791 goto IL_03b2;
792 case 4:
793 if (regexNode2.Type == 4 && regexNode.Ch == regexNode2.Ch)
794 {
795 goto IL_01de;
796 }
797 if (regexNode2.Type != 10 || regexNode.Ch != regexNode2.Ch)
798 {
799 break;
800 }
801 goto IL_03b2;
802 case 44:
803 if (regexNode2.Type == 44 && regexNode.Ch == regexNode2.Ch)
804 {
805 goto IL_01de;
806 }
807 if (regexNode2.Type != 10 || regexNode.Ch != regexNode2.Ch)
808 {
809 break;
810 }
811 goto IL_03b2;
812 case 7:
813 if (regexNode2.Type == 7 && regexNode.Ch == regexNode2.Ch)
814 {
815 goto IL_01de;
816 }
817 if (regexNode2.Type != 10 || regexNode.Ch != regexNode2.Ch)
818 {
819 break;
820 }
821 goto IL_03b2;
822 case 5:
823 if (regexNode2.Type == 5 && regexNode.Str == regexNode2.Str)
824 {
825 goto IL_01de;
826 }
827 if (regexNode2.Type != 11 || !(regexNode.Str == regexNode2.Str))
828 {
829 break;
830 }
831 goto IL_03b2;
832 case 45:
833 if (regexNode2.Type == 45 && regexNode.Str == regexNode2.Str)
834 {
835 goto IL_01de;
836 }
837 if (regexNode2.Type != 11 || !(regexNode.Str == regexNode2.Str))
838 {
839 break;
840 }
841 goto IL_03b2;
842 case 8:
843 if (regexNode2.Type == 8 && regexNode.Str == regexNode2.Str)
844 {
845 goto IL_01de;
846 }
847 if (regexNode2.Type != 11 || !(regexNode.Str == regexNode2.Str))
848 {
849 break;
850 }
851 goto IL_03b2;
852 case 9:
853 if ((regexNode2.Type == 3 || regexNode2.Type == 43 || regexNode2.Type == 6) && regexNode.Ch == regexNode2.Ch)
854 {
855 goto IL_04b1;
856 }
857 if (regexNode2.Type != 9 || regexNode.Ch != regexNode2.Ch)
858 {
859 break;
860 }
861 goto IL_0571;
862 case 10:
863 if ((regexNode2.Type == 4 || regexNode2.Type == 44 || regexNode2.Type == 7) && regexNode.Ch == regexNode2.Ch)
864 {
865 goto IL_04b1;
866 }
867 if (regexNode2.Type != 10 || regexNode.Ch != regexNode2.Ch)
868 {
869 break;
870 }
871 goto IL_0571;
872 case 11:
873 {
874 if ((regexNode2.Type == 5 || regexNode2.Type == 45 || regexNode2.Type == 8) && regexNode.Str == regexNode2.Str)
875 {
876 goto IL_04b1;
877 }
878 if (regexNode2.Type != 11 || !(regexNode.Str == regexNode2.Str))
879 {
880 break;
881 }
882 goto IL_0571;
883 }
884 IL_0571:
885 regexNode.MakeRep(3, 2, 2);
886 num++;
887 continue;
888 IL_04b1:
889 if (CanCombineCounts(1, 1, regexNode2.M, regexNode2.N))
890 {
891 regexNode.Type = regexNode2.Type;
892 regexNode.M = regexNode2.M + 1;
893 regexNode.N = ((regexNode2.N == int.MaxValue) ? int.MaxValue : (regexNode2.N + 1));
894 num++;
895 continue;
896 }
897 break;
898 IL_03b2:
899 if (CanCombineCounts(regexNode.M, regexNode.N, 1, 1))
900 {
901 regexNode.M++;
902 if (regexNode.N != int.MaxValue)
903 {
904 regexNode.N++;
905 }
906 num++;
907 continue;
908 }
909 break;
910 IL_01de:
912 {
913 regexNode.M += regexNode2.M;
914 if (regexNode.N != int.MaxValue)
915 {
916 regexNode.N = ((regexNode2.N == int.MaxValue) ? int.MaxValue : (regexNode.N + regexNode2.N));
917 }
918 num++;
919 continue;
920 }
921 break;
922 }
923 }
924 list[num2++] = list[num];
925 index = num;
926 num++;
927 }
928 if (num2 < list.Count)
929 {
930 list.RemoveRange(num2, list.Count - num2);
931 }
932 static bool CanCombineCounts(int nodeMin, int nodeMax, int nextMin, int nextMax)
933 {
934 if (nodeMin == int.MaxValue || nextMin == int.MaxValue || (uint)(nodeMin + nextMin) >= 2147483647u)
935 {
936 return false;
937 }
938 if (nodeMax != int.MaxValue && nextMax != int.MaxValue && (uint)(nodeMax + nextMax) >= 2147483647u)
939 {
940 return false;
941 }
942 return true;
943 }
944 }
945
947 {
949 for (int i = 0; i < list.Count - 1; i++)
950 {
951 ProcessNode(list[i], list[i + 1], 20u);
952 }
953 static void ProcessNode(RegexNode node, RegexNode subsequent, uint maxDepth)
954 {
955 while (true)
956 {
957 if (node.Type == 28 || node.Type == 25)
958 {
959 node = node.Child(node.ChildCount() - 1);
960 }
961 else
962 {
963 if (node.Type != 26)
964 {
965 break;
966 }
968 if (regexNode == null)
969 {
970 break;
971 }
972 node = regexNode;
973 }
974 }
975 switch (node.Type)
976 {
977 case 3:
979 {
980 break;
981 }
982 goto IL_0089;
983 case 4:
985 {
986 break;
987 }
988 goto IL_0089;
989 case 5:
991 {
992 break;
993 }
994 goto IL_0089;
995 case 24:
996 {
997 int num = node.ChildCount();
998 for (int j = 0; j < num; j++)
999 {
1000 ProcessNode(node.Child(j), subsequent, maxDepth - 1);
1001 }
1002 break;
1003 }
1004 IL_0089:
1005 node.MakeLoopAtomic();
1006 break;
1007 }
1008 }
1009 }
1010
1012 {
1013 node = node.Child(0);
1014 while (node.Type == 28)
1015 {
1016 node = node.Child(0);
1017 }
1018 if (node.Type == 25)
1019 {
1020 int num = node.ChildCount();
1021 RegexNode regexNode = node.Child(num - 1);
1022 if (CanBeMadeAtomic(regexNode, node.Child(0), maxDepth - 1))
1023 {
1024 return regexNode;
1025 }
1026 }
1027 return null;
1028 }
1029
1031 {
1032 if (maxDepth == 0)
1033 {
1034 return false;
1035 }
1036 for (; subsequent.ChildCount() > 0; subsequent = subsequent.Child(0))
1037 {
1038 switch (subsequent.Type)
1039 {
1040 case 30:
1041 if ((subsequent.Options & RegexOptions.RightToLeft) == 0)
1042 {
1043 continue;
1044 }
1045 break;
1046 case 26:
1047 if (subsequent.M > 0)
1048 {
1049 continue;
1050 }
1051 break;
1052 case 27:
1053 if (subsequent.M > 0)
1054 {
1055 continue;
1056 }
1057 break;
1058 case 25:
1059 case 28:
1060 case 32:
1061 continue;
1062 }
1063 break;
1064 }
1065 if (node.Options != subsequent.Options)
1066 {
1067 return false;
1068 }
1069 if (subsequent.Type == 24)
1070 {
1071 int num = subsequent.ChildCount();
1072 for (int i = 0; i < num; i++)
1073 {
1074 if (!CanBeMadeAtomic(node, subsequent.Child(i), maxDepth - 1))
1075 {
1076 return false;
1077 }
1078 }
1079 return true;
1080 }
1081 switch (node.Type)
1082 {
1083 case 3:
1084 switch (subsequent.Type)
1085 {
1086 case 9:
1087 if (node.Ch == subsequent.Ch)
1088 {
1089 break;
1090 }
1091 goto case 21;
1092 case 6:
1093 if (subsequent.M <= 0 || node.Ch == subsequent.Ch)
1094 {
1095 break;
1096 }
1097 goto case 21;
1098 case 3:
1099 if (subsequent.M <= 0 || node.Ch == subsequent.Ch)
1100 {
1101 break;
1102 }
1103 goto case 21;
1104 case 43:
1105 if (subsequent.M <= 0 || node.Ch == subsequent.Ch)
1106 {
1107 break;
1108 }
1109 goto case 21;
1110 case 10:
1111 if (node.Ch != subsequent.Ch)
1112 {
1113 break;
1114 }
1115 goto case 21;
1116 case 7:
1117 if (subsequent.M <= 0 || node.Ch != subsequent.Ch)
1118 {
1119 break;
1120 }
1121 goto case 21;
1122 case 4:
1123 if (subsequent.M <= 0 || node.Ch != subsequent.Ch)
1124 {
1125 break;
1126 }
1127 goto case 21;
1128 case 44:
1129 if (subsequent.M <= 0 || node.Ch != subsequent.Ch)
1130 {
1131 break;
1132 }
1133 goto case 21;
1134 case 12:
1135 if (node.Ch == subsequent.Str[0])
1136 {
1137 break;
1138 }
1139 goto case 21;
1140 case 11:
1142 {
1143 break;
1144 }
1145 goto case 21;
1146 case 8:
1147 if (subsequent.M <= 0 || RegexCharClass.CharInClass(node.Ch, subsequent.Str))
1148 {
1149 break;
1150 }
1151 goto case 21;
1152 case 5:
1153 if (subsequent.M <= 0 || RegexCharClass.CharInClass(node.Ch, subsequent.Str))
1154 {
1155 break;
1156 }
1157 goto case 21;
1158 case 45:
1159 if (subsequent.M <= 0 || RegexCharClass.CharInClass(node.Ch, subsequent.Str))
1160 {
1161 break;
1162 }
1163 goto case 21;
1164 case 20:
1165 if (node.Ch == '\n')
1166 {
1167 break;
1168 }
1169 goto case 21;
1170 case 15:
1171 if (node.Ch == '\n')
1172 {
1173 break;
1174 }
1175 goto case 21;
1176 case 16:
1178 {
1179 break;
1180 }
1181 goto case 21;
1182 case 17:
1184 {
1185 break;
1186 }
1187 goto case 21;
1188 case 41:
1190 {
1191 break;
1192 }
1193 goto case 21;
1194 case 42:
1196 {
1197 break;
1198 }
1199 goto case 21;
1200 case 21:
1201 return true;
1202 }
1203 break;
1204 case 4:
1205 {
1206 int type = subsequent.Type;
1207 if (type <= 9)
1208 {
1209 if (type != 3)
1210 {
1211 if (type != 6)
1212 {
1213 if (type != 9 || node.Ch != subsequent.Ch)
1214 {
1215 break;
1216 }
1217 }
1218 else if (subsequent.M <= 0 || node.Ch != subsequent.Ch)
1219 {
1220 break;
1221 }
1222 }
1223 else if (subsequent.M <= 0 || node.Ch != subsequent.Ch)
1224 {
1225 break;
1226 }
1227 }
1228 else if (type != 12)
1229 {
1230 if (type != 21 && (type != 43 || subsequent.M <= 0 || node.Ch != subsequent.Ch))
1231 {
1232 break;
1233 }
1234 }
1235 else if (node.Ch != subsequent.Str[0])
1236 {
1237 break;
1238 }
1239 return true;
1240 }
1241 case 5:
1242 switch (subsequent.Type)
1243 {
1244 case 9:
1246 {
1247 break;
1248 }
1249 goto case 21;
1250 case 6:
1251 if (subsequent.M <= 0 || RegexCharClass.CharInClass(subsequent.Ch, node.Str))
1252 {
1253 break;
1254 }
1255 goto case 21;
1256 case 3:
1257 if (subsequent.M <= 0 || RegexCharClass.CharInClass(subsequent.Ch, node.Str))
1258 {
1259 break;
1260 }
1261 goto case 21;
1262 case 43:
1263 if (subsequent.M <= 0 || RegexCharClass.CharInClass(subsequent.Ch, node.Str))
1264 {
1265 break;
1266 }
1267 goto case 21;
1268 case 12:
1269 if (RegexCharClass.CharInClass(subsequent.Str[0], node.Str))
1270 {
1271 break;
1272 }
1273 goto case 21;
1274 case 11:
1276 {
1277 break;
1278 }
1279 goto case 21;
1280 case 8:
1281 if (subsequent.M <= 0 || RegexCharClass.MayOverlap(node.Str, subsequent.Str))
1282 {
1283 break;
1284 }
1285 goto case 21;
1286 case 5:
1287 if (subsequent.M <= 0 || RegexCharClass.MayOverlap(node.Str, subsequent.Str))
1288 {
1289 break;
1290 }
1291 goto case 21;
1292 case 45:
1293 if (subsequent.M <= 0 || RegexCharClass.MayOverlap(node.Str, subsequent.Str))
1294 {
1295 break;
1296 }
1297 goto case 21;
1298 case 20:
1299 if (RegexCharClass.CharInClass('\n', node.Str))
1300 {
1301 break;
1302 }
1303 goto case 21;
1304 case 15:
1305 if (RegexCharClass.CharInClass('\n', node.Str))
1306 {
1307 break;
1308 }
1309 goto case 21;
1310 case 16:
1311 if (!(node.Str == "\0\0\n\0\u0002\u0004\u0005\u0003\u0001\u0006\t\u0013\0") && !(node.Str == "\0\0\u0001\t"))
1312 {
1313 break;
1314 }
1315 goto case 21;
1316 case 17:
1317 if (!(node.Str == "\u0001\0\n\0\u0002\u0004\u0005\u0003\u0001\u0006\t\u0013\0") && !(node.Str == "\0\0\u0001\ufff7"))
1318 {
1319 break;
1320 }
1321 goto case 21;
1322 case 41:
1323 if (!(node.Str == "\0\n\00:A[_`a{İı") && !(node.Str == "\0\u0002\00:"))
1324 {
1325 break;
1326 }
1327 goto case 21;
1328 case 42:
1329 if (!(node.Str == "\u0001\n\00:A[_`a{İı") && !(node.Str == "\0\0\u0001\ufff7"))
1330 {
1331 break;
1332 }
1333 goto case 21;
1334 case 21:
1335 return true;
1336 }
1337 break;
1338 }
1339 return false;
1340 }
1341
1342 public int ComputeMinLength()
1343 {
1344 return ComputeMinLength(this, 20u);
1345 static int ComputeMinLength(RegexNode node, uint maxDepth)
1346 {
1347 if (maxDepth == 0)
1348 {
1349 return 0;
1350 }
1351 switch (node.Type)
1352 {
1353 case 9:
1354 case 10:
1355 case 11:
1356 return 1;
1357 case 12:
1358 return node.Str.Length;
1359 case 3:
1360 case 4:
1361 case 5:
1362 case 6:
1363 case 7:
1364 case 8:
1365 case 43:
1366 case 44:
1367 case 45:
1368 return node.M;
1369 case 26:
1370 case 27:
1371 return (int)Math.Min(2147483647L, (long)node.M * (long)ComputeMinLength(node.Child(0), maxDepth - 1));
1372 case 24:
1373 {
1374 int num3 = node.ChildCount();
1375 int num4 = ComputeMinLength(node.Child(0), maxDepth - 1);
1376 for (int j = 1; j < num3; j++)
1377 {
1378 if (num4 <= 0)
1379 {
1380 break;
1381 }
1382 num4 = Math.Min(num4, ComputeMinLength(node.Child(j), maxDepth - 1));
1383 }
1384 return num4;
1385 }
1386 case 25:
1387 {
1388 long num = 0L;
1389 int num2 = node.ChildCount();
1390 for (int i = 0; i < num2; i++)
1391 {
1392 num += ComputeMinLength(node.Child(i), maxDepth - 1);
1393 }
1394 return (int)Math.Min(2147483647L, num);
1395 }
1396 case 28:
1397 case 29:
1398 case 32:
1399 return ComputeMinLength(node.Child(0), maxDepth - 1);
1400 default:
1401 return 0;
1402 }
1403 }
1404 }
1405
1406 public RegexNode MakeQuantifier(bool lazy, int min, int max)
1407 {
1408 if (min == 0 && max == 0)
1409 {
1410 return new RegexNode(23, Options);
1411 }
1412 if (min == 1 && max == 1)
1413 {
1414 return this;
1415 }
1416 int type = Type;
1417 if ((uint)(type - 9) <= 2u)
1418 {
1419 MakeRep(lazy ? 6 : 3, min, max);
1420 return this;
1421 }
1422 RegexNode regexNode = new RegexNode(lazy ? 27 : 26, Options, min, max);
1423 regexNode.AddChild(this);
1424 return regexNode;
1425 }
1426
1428 {
1429 newChild.Next = this;
1430 newChild = newChild.Reduce();
1431 newChild.Next = this;
1432 if (Children == null)
1433 {
1435 }
1436 else if (Children is RegexNode item)
1437 {
1439 }
1440 else
1441 {
1443 }
1444 }
1445
1447 {
1448 newChild.Next = this;
1449 newChild = newChild.Reduce();
1450 newChild.Next = this;
1452 }
1453
1455 {
1456 newChild.Next = this;
1457 if (Children is RegexNode)
1458 {
1460 }
1461 else
1462 {
1464 }
1465 }
1466
1467 public RegexNode Child(int i)
1468 {
1469 if (Children is RegexNode result)
1470 {
1471 return result;
1472 }
1473 return ((List<RegexNode>)Children)[i];
1474 }
1475
1476 public int ChildCount()
1477 {
1478 if (Children == null)
1479 {
1480 return 0;
1481 }
1483 {
1484 return list.Count;
1485 }
1486 return 1;
1487 }
1488}
void Add(TKey key, TValue value)
static byte Min(byte val1, byte val2)
Definition Math.cs:912
static bool CharInClass(char ch, string set, ref int[] asciiResultCache)
static bool MayOverlap(string set1, string set2)
static RegexCharClass Parse(string charClass)
static bool IsMergeable(string charClass)
void ReplaceChild(int index, RegexNode newChild)
static void EliminateEndingBacktracking(RegexNode node, uint maxDepth)
Definition RegexNode.cs:167
RegexNode(int type, RegexOptions options, string str)
Definition RegexNode.cs:36
RegexNode(int type, RegexOptions options, int m)
Definition RegexNode.cs:43
RegexNode(int type, RegexOptions options, int m, int n)
Definition RegexNode.cs:50
RegexNode ReplaceNodeIfUnnecessary(int emptyTypeIfNoChildren)
Definition RegexNode.cs:269
static RegexNode FindLastExpressionInLoopForAutoAtomic(RegexNode node, uint maxDepth)
static bool CanBeMadeAtomic(RegexNode node, RegexNode subsequent, uint maxDepth)
RegexNode(int type, RegexOptions options, char ch)
Definition RegexNode.cs:29
RegexNode MakeQuantifier(bool lazy, int min, int max)
void AddChild(RegexNode newChild)
void MakeRep(int type, int min, int max)
Definition RegexNode.cs:72
RegexNode(int type, RegexOptions options)
Definition RegexNode.cs:23
void InsertChild(int index, RegexNode newChild)