PageRenderTime 67ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/System/System.Text.RegularExpressions/RegexParser.cs

https://bitbucket.org/cosi2/dotnetanywhere-wb
C# | 2076 lines | 1930 code | 145 blank | 1 comment | 533 complexity | 6d64957c101576dacd71fbf712be50d2 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. namespace System.Text.RegularExpressions
  2. {
  3. using System;
  4. using System.Collections;
  5. using System.Globalization;
  6. using System.Text;
  7. using System.Collections.Generic;
  8. internal sealed class RegexParser
  9. {
  10. internal RegexNode _alternation;
  11. internal int _autocap;
  12. internal int _capcount;
  13. internal ArrayList _capnamelist;
  14. internal System.Collections.Generic.Dictionary<object,object> _capnames;
  15. internal object[] _capnumlist;
  16. internal System.Collections.Generic.Dictionary<object,object> _caps;
  17. internal int _capsize;
  18. internal int _captop;
  19. internal static readonly byte[] _category = new byte[] {
  20. 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 2, 2, 0, 0,
  21. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  22. 2, 0, 0, 3, 4, 0, 0, 0, 4, 4, 5, 5, 0, 0, 4, 0,
  23. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
  24. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  25. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, 0,
  26. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  27. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 0, 0, 0
  28. };
  29. internal RegexNode _concatenation;
  30. internal CultureInfo _culture;
  31. internal int _currentPos;
  32. internal RegexNode _group;
  33. internal bool _ignoreNextParen = false;
  34. internal RegexOptions _options;
  35. internal ArrayList _optionsStack;
  36. internal string _pattern;
  37. internal RegexNode _stack;
  38. internal RegexNode _unit;
  39. internal const byte E = 1;
  40. internal const int infinite = 0x7fffffff;
  41. internal const byte Q = 5;
  42. internal const byte S = 4;
  43. internal const byte X = 2;
  44. internal const byte Z = 3;
  45. private RegexParser(CultureInfo culture)
  46. {
  47. this._culture = culture;
  48. this._optionsStack = new ArrayList();
  49. this._caps = new System.Collections.Generic.Dictionary<object,object>();
  50. }
  51. internal void AddAlternate()
  52. {
  53. if ((this._group.Type() == 0x22) || (this._group.Type() == 0x21))
  54. {
  55. this._group.AddChild(this._concatenation.ReverseLeft());
  56. }
  57. else
  58. {
  59. this._alternation.AddChild(this._concatenation.ReverseLeft());
  60. }
  61. this._concatenation = new RegexNode(0x19, this._options);
  62. }
  63. internal void AddConcatenate()
  64. {
  65. this._concatenation.AddChild(this._unit);
  66. this._unit = null;
  67. }
  68. internal void AddConcatenate(int pos, int cch)
  69. {
  70. if (cch != 0)
  71. {
  72. RegexNode node;
  73. if (cch > 1)
  74. {
  75. string str = this._pattern.Substring(pos, cch);
  76. if (this.UseOptionI())
  77. {
  78. str = str.ToLower(this._culture);
  79. }
  80. node = new RegexNode(12, this._options, str);
  81. }
  82. else
  83. {
  84. char c = this._pattern[pos];
  85. if (this.UseOptionI())
  86. {
  87. c = char.ToLower(c, this._culture);
  88. }
  89. node = new RegexNode(9, this._options, c);
  90. }
  91. this._concatenation.AddChild(node);
  92. }
  93. }
  94. internal void AddConcatenate(bool lazy, int min, int max)
  95. {
  96. this._concatenation.AddChild(this._unit.MakeQuantifier(lazy, min, max));
  97. this._unit = null;
  98. }
  99. internal void AddGroup()
  100. {
  101. if ((this._group.Type() == 0x22) || (this._group.Type() == 0x21))
  102. {
  103. this._group.AddChild(this._concatenation.ReverseLeft());
  104. if (((this._group.Type() == 0x21) && (this._group.ChildCount() > 2)) || (this._group.ChildCount() > 3))
  105. {
  106. throw this.MakeException(RegExRes.GetString(0x1c));
  107. }
  108. }
  109. else
  110. {
  111. this._alternation.AddChild(this._concatenation.ReverseLeft());
  112. this._group.AddChild(this._alternation);
  113. }
  114. this._unit = this._group;
  115. }
  116. internal void AddUnitNode(RegexNode node)
  117. {
  118. this._unit = node;
  119. }
  120. internal void AddUnitNotone(char ch)
  121. {
  122. if (this.UseOptionI())
  123. {
  124. ch = char.ToLower(ch, this._culture);
  125. }
  126. this._unit = new RegexNode(10, this._options, ch);
  127. }
  128. internal void AddUnitOne(char ch)
  129. {
  130. if (this.UseOptionI())
  131. {
  132. ch = char.ToLower(ch, this._culture);
  133. }
  134. this._unit = new RegexNode(9, this._options, ch);
  135. }
  136. internal void AddUnitSet(RegexCharClass cc)
  137. {
  138. this._unit = new RegexNode(11, this._options, cc.ToSetCi(this.UseOptionI(), this._culture), cc.Category);
  139. }
  140. internal void AddUnitType(int type)
  141. {
  142. this._unit = new RegexNode(type, this._options);
  143. }
  144. internal void AssignNameSlots()
  145. {
  146. if (this._capnames != null)
  147. {
  148. for (int i = 0; i < this._capnamelist.Count; i++)
  149. {
  150. while (this.IsCaptureSlot(this._autocap))
  151. {
  152. this._autocap++;
  153. }
  154. string str = (string) this._capnamelist[i];
  155. int pos = (int) this._capnames[str];
  156. this._capnames[str] = this._autocap;
  157. this.NoteCaptureSlot(this._autocap, pos);
  158. this._autocap++;
  159. }
  160. }
  161. if (this._capcount < this._captop)
  162. {
  163. this._capnumlist = new object[this._capcount];
  164. int num3 = 0;
  165. IDictionaryEnumerator enumerator = this._caps.GetEnumerator();
  166. while (enumerator.MoveNext())
  167. {
  168. this._capnumlist[num3++] = enumerator.Key;
  169. }
  170. //
  171. Array.Sort(this._capnumlist, 0, this._capnumlist.Length, null);
  172. }
  173. if ((this._capnames != null) || (this._capnumlist != null))
  174. {
  175. ArrayList list;
  176. int num4;
  177. int num5 = 0;
  178. if (this._capnames == null)
  179. {
  180. list = null;
  181. this._capnames = new System.Collections.Generic.Dictionary<object,object>();
  182. this._capnamelist = new ArrayList();
  183. num4 = -1;
  184. }
  185. else
  186. {
  187. list = this._capnamelist;
  188. this._capnamelist = new ArrayList();
  189. num4 = (int) this._capnames[list[0]];
  190. }
  191. for (int j = 0; j < this._capcount; j++)
  192. {
  193. int num7 = (this._capnumlist == null) ? j : ((int) this._capnumlist[j]);
  194. if (num4 == num7)
  195. {
  196. this._capnamelist.Add((string) list[num5++]);
  197. num4 = (num5 == list.Count) ? -1 : ((int) this._capnames[list[num5]]);
  198. }
  199. else
  200. {
  201. string str2 = num7.ToString();// Convert.ToString(num7);
  202. this._capnamelist.Add(str2);
  203. this._capnames[str2] = num7;
  204. }
  205. }
  206. }
  207. }
  208. internal int CaptureSlotFromName(string capname)
  209. {
  210. return (int) this._capnames[capname];
  211. }
  212. internal char CharAt(int i)
  213. {
  214. return this._pattern[i];
  215. }
  216. internal int CharsRight()
  217. {
  218. return (this._pattern.Length - this._currentPos);
  219. }
  220. internal void CountCaptures()
  221. {
  222. this.NoteCaptureSlot(0, 0);
  223. this._autocap = 1;
  224. while (this.CharsRight() > 0)
  225. {
  226. int pos = this.Textpos();
  227. switch (this.RightCharNext())
  228. {
  229. case '(':
  230. if (((this.CharsRight() < 2) || (this.RightChar(1) != '#')) || (this.RightChar() != '?'))
  231. {
  232. break;
  233. }
  234. this.LeftNext();
  235. this.ScanBlank();
  236. goto Label_01C6;
  237. case ')':
  238. {
  239. if (!this.EmptyOptionsStack())
  240. {
  241. this.PopOptions();
  242. }
  243. continue;
  244. }
  245. case '#':
  246. {
  247. if (this.UseOptionX())
  248. {
  249. this.LeftNext();
  250. this.ScanBlank();
  251. }
  252. continue;
  253. }
  254. case '[':
  255. {
  256. this.ScanCharClass(false, true);
  257. continue;
  258. }
  259. case '\\':
  260. {
  261. if (this.CharsRight() > 0)
  262. {
  263. this.RightNext();
  264. }
  265. continue;
  266. }
  267. default:
  268. {
  269. continue;
  270. }
  271. }
  272. this.PushOptions();
  273. if ((this.CharsRight() > 0) && (this.RightChar() == '?'))
  274. {
  275. this.RightNext();
  276. if ((this.CharsRight() > 1) && ((this.RightChar() == '<') || (this.RightChar() == '\'')))
  277. {
  278. this.RightNext();
  279. char ch = this.RightChar();
  280. if ((ch != '0') && RegexCharClass.IsWordChar(ch))
  281. {
  282. if ((ch >= '1') && (ch <= '9'))
  283. {
  284. this.NoteCaptureSlot(this.ScanDecimal(), pos);
  285. }
  286. else
  287. {
  288. this.NoteCaptureName(this.ScanCapname(), pos);
  289. }
  290. }
  291. goto Label_01C6;
  292. }
  293. this.ScanOptions();
  294. if (this.CharsRight() <= 0)
  295. {
  296. goto Label_01C6;
  297. }
  298. if (this.RightChar() == ')')
  299. {
  300. this.RightNext();
  301. this.PopKeepOptions();
  302. goto Label_01C6;
  303. }
  304. if (this.RightChar() != '(')
  305. {
  306. goto Label_01C6;
  307. }
  308. this._ignoreNextParen = true;
  309. continue;
  310. }
  311. if (!this.UseOptionN() && !this._ignoreNextParen)
  312. {
  313. this.NoteCaptureSlot(this._autocap++, pos);
  314. }
  315. Label_01C6:
  316. this._ignoreNextParen = false;
  317. }
  318. this.AssignNameSlots();
  319. }
  320. internal bool EmptyOptionsStack()
  321. {
  322. return (this._optionsStack.Count == 0);
  323. }
  324. internal bool EmptyStack()
  325. {
  326. return (this._stack == null);
  327. }
  328. internal static string Escape(string input)
  329. {
  330. for (int i = 0; i < input.Length; i++)
  331. {
  332. if (!IsMetachar(input[i]))
  333. {
  334. continue;
  335. }
  336. StringBuilder builder = new StringBuilder();
  337. char ch = input[i];
  338. builder.Append(input, 0, i);
  339. do
  340. {
  341. builder.Append('\\');
  342. switch (ch)
  343. {
  344. case '\t':
  345. ch = 't';
  346. break;
  347. case '\n':
  348. ch = 'n';
  349. break;
  350. case '\f':
  351. ch = 'f';
  352. break;
  353. case '\r':
  354. ch = 'r';
  355. break;
  356. }
  357. builder.Append(ch);
  358. i++;
  359. int startIndex = i;
  360. while (i < input.Length)
  361. {
  362. ch = input[i];
  363. if (IsMetachar(ch))
  364. {
  365. break;
  366. }
  367. i++;
  368. }
  369. builder.Append(input, startIndex, i - startIndex);
  370. }
  371. while (i < input.Length);
  372. return builder.ToString();
  373. }
  374. return input;
  375. }
  376. internal static int HexDigit(char ch)
  377. {
  378. int num;
  379. if (((num = ch - '0') <= 9) && (num >= 0))
  380. {
  381. return num;
  382. }
  383. if (((num = ch - 'a') <= 5) && (num >= 0))
  384. {
  385. return (num + 10);
  386. }
  387. if (((num = ch - 'A') <= 5) && (num >= 0))
  388. {
  389. return (num + 10);
  390. }
  391. return -1;
  392. }
  393. internal bool IsCaptureName(string capname)
  394. {
  395. if (this._capnames == null)
  396. {
  397. return false;
  398. }
  399. return this._capnames.ContainsKey(capname);
  400. }
  401. internal bool IsCaptureSlot(int i)
  402. {
  403. if (this._caps != null)
  404. {
  405. return this._caps.ContainsKey(i);
  406. }
  407. return ((i >= 0) && (i < this._capsize));
  408. }
  409. internal static bool IsMetachar(char ch)
  410. {
  411. return ((ch <= '|') && (_category[ch] >= 1));
  412. }
  413. internal bool IsOnlyTopOption(RegexOptions option)
  414. {
  415. if (((option != RegexOptions.RightToLeft) && (option != RegexOptions.Compiled)) && (option != RegexOptions.CultureInvariant))
  416. {
  417. return (option == RegexOptions.ECMAScript);
  418. }
  419. return true;
  420. }
  421. internal static bool IsQuantifier(char ch)
  422. {
  423. return ((ch <= '{') && (_category[ch] >= 5));
  424. }
  425. internal static bool IsSpace(char ch)
  426. {
  427. return ((ch <= ' ') && (_category[ch] == 2));
  428. }
  429. internal static bool IsSpecial(char ch)
  430. {
  431. return ((ch <= '|') && (_category[ch] >= 4));
  432. }
  433. internal static bool IsStopperX(char ch)
  434. {
  435. return ((ch <= '|') && (_category[ch] >= 2));
  436. }
  437. internal bool IsTrueQuantifier()
  438. {
  439. int num = this.CharsRight();
  440. if (num == 0)
  441. {
  442. return false;
  443. }
  444. int i = this.Textpos();
  445. char index = this.CharAt(i);
  446. if (index == '{')
  447. {
  448. int num3 = i;
  449. while (((--num > 0) && ((index = this.CharAt(++num3)) >= '0')) && (index <= '9'))
  450. {
  451. }
  452. if ((num == 0) || ((num3 - i) == 1))
  453. {
  454. return false;
  455. }
  456. if (index == '}')
  457. {
  458. return true;
  459. }
  460. if (index != ',')
  461. {
  462. return false;
  463. }
  464. while (((--num > 0) && ((index = this.CharAt(++num3)) >= '0')) && (index <= '9'))
  465. {
  466. }
  467. return ((num > 0) && (index == '}'));
  468. }
  469. return ((index <= '{') && (_category[index] >= 5));
  470. }
  471. internal void LeftNext()
  472. {
  473. this._currentPos--;
  474. }
  475. internal ArgumentException MakeException()
  476. {
  477. return new ArgumentException();
  478. }
  479. internal ArgumentException MakeException(string message)
  480. {
  481. return new ArgumentException(RegExRes.GetString(0x1d, this._pattern, message), this._pattern);
  482. }
  483. internal void NoteCaptureName(string name, int pos)
  484. {
  485. if (this._capnames == null)
  486. {
  487. this._capnames = new System.Collections.Generic.Dictionary<object,object>();
  488. this._capnamelist = new ArrayList();
  489. }
  490. if (!this._capnames.ContainsKey(name))
  491. {
  492. this._capnames.Add(name, pos);
  493. this._capnamelist.Add(name);
  494. }
  495. }
  496. internal void NoteCaptures(System.Collections.Generic.Dictionary<object,object> caps,
  497. int capsize, System.Collections.Generic.Dictionary<object,object> capnames)
  498. {
  499. this._caps = caps;
  500. this._capsize = capsize;
  501. this._capnames = capnames;
  502. }
  503. internal void NoteCaptureSlot(int i, int pos)
  504. {
  505. if (!this._caps.ContainsKey(i))
  506. {
  507. this._caps.Add(i, pos);
  508. this._capcount++;
  509. if (this._captop <= i)
  510. {
  511. this._captop = i + 1;
  512. }
  513. }
  514. }
  515. internal static RegexOptions OptionFromCode(char ch)
  516. {
  517. if ((ch >= 'A') && (ch <= 'Z'))
  518. {
  519. ch = (char) (ch + ' ');
  520. }
  521. switch (ch)
  522. {
  523. case 'c':
  524. return RegexOptions.Compiled;
  525. case 'e':
  526. return RegexOptions.ECMAScript;
  527. case 'i':
  528. return RegexOptions.IgnoreCase;
  529. case 'm':
  530. return RegexOptions.Multiline;
  531. case 'n':
  532. return RegexOptions.ExplicitCapture;
  533. case 'r':
  534. return RegexOptions.RightToLeft;
  535. case 's':
  536. return RegexOptions.Singleline;
  537. case 'x':
  538. return RegexOptions.IgnorePatternWhitespace;
  539. }
  540. return RegexOptions.None;
  541. }
  542. internal static RegexTree Parse(string re, RegexOptions op)
  543. {
  544. string[] strArray;
  545. RegexParser parser = new RegexParser(((op & RegexOptions.CultureInvariant) != RegexOptions.None) ? CultureInfo.InvariantCulture : CultureInfo.CurrentCulture) {
  546. _options = op
  547. };
  548. parser.SetPattern(re);
  549. parser.CountCaptures();
  550. parser.Reset(op);
  551. RegexNode root = parser.ScanRegex();
  552. if (parser._capnamelist == null)
  553. {
  554. strArray = null;
  555. }
  556. else
  557. {
  558. strArray = new string[parser._capnamelist.Count];
  559. parser._capnamelist.CopyTo(0, strArray, 0, parser._capnamelist.Count);
  560. }
  561. return new RegexTree(root, parser._caps, parser._capnumlist, parser._captop, parser._capnames, strArray, op);
  562. }
  563. internal string ParseProperty()
  564. {
  565. if (this.CharsRight() < 3)
  566. {
  567. throw this.MakeException(RegExRes.GetString(30));
  568. }
  569. if (this.RightCharNext() != '{')
  570. {
  571. throw this.MakeException(RegExRes.GetString(0x1f));
  572. }
  573. string str = this.ScanCapname();
  574. if ((this.CharsRight() == 0) || (this.RightCharNext() != '}'))
  575. {
  576. throw this.MakeException(RegExRes.GetString(30));
  577. }
  578. return str;
  579. }
  580. internal static RegexReplacement ParseReplacement(string rep, System.Collections.Generic.Dictionary<object,object> caps,
  581. int capsize, System.Collections.Generic.Dictionary<object,object> capnames, RegexOptions op)
  582. {
  583. RegexParser parser = new RegexParser(((op & RegexOptions.CultureInvariant) != RegexOptions.None) ? CultureInfo.InvariantCulture : CultureInfo.CurrentCulture);
  584. parser.NoteCaptures(caps, capsize, capnames);
  585. parser.SetPattern(rep);
  586. return new RegexReplacement(rep, parser.ScanReplacement(), caps);
  587. }
  588. internal void PopGroup()
  589. {
  590. this._concatenation = this._stack;
  591. this._alternation = this._concatenation._next;
  592. this._group = this._alternation._next;
  593. this._stack = this._group._next;
  594. if ((this._group.Type() == 0x22) && (this._group.ChildCount() == 0))
  595. {
  596. if (this._unit == null)
  597. {
  598. throw this.MakeException(RegExRes.GetString(0x1b));
  599. }
  600. this._group.AddChild(this._unit);
  601. this._unit = null;
  602. }
  603. }
  604. internal void PopKeepOptions()
  605. {
  606. this._optionsStack.RemoveAt(this._optionsStack.Count - 1);
  607. }
  608. internal void PopOptions()
  609. {
  610. this._options = (RegexOptions) this._optionsStack[this._optionsStack.Count - 1];
  611. this._optionsStack.RemoveAt(this._optionsStack.Count - 1);
  612. }
  613. internal void PushGroup()
  614. {
  615. this._group._next = this._stack;
  616. this._alternation._next = this._group;
  617. this._concatenation._next = this._alternation;
  618. this._stack = this._concatenation;
  619. }
  620. internal void PushOptions()
  621. {
  622. this._optionsStack.Add(this._options);
  623. }
  624. internal void Reset(RegexOptions topopts)
  625. {
  626. this._currentPos = 0;
  627. this._autocap = 1;
  628. this._ignoreNextParen = false;
  629. if (this._optionsStack.Count > 0)
  630. {
  631. object obj2 = this._optionsStack[this._optionsStack.Count - 1];
  632. this._optionsStack.Clear();
  633. this._optionsStack.Add(obj2);
  634. }
  635. this._options = topopts;
  636. this._stack = null;
  637. }
  638. internal char RightChar()
  639. {
  640. return this._pattern[this._currentPos];
  641. }
  642. internal char RightChar(int i)
  643. {
  644. return this._pattern[this._currentPos + i];
  645. }
  646. internal char RightCharNext()
  647. {
  648. return this._pattern[this._currentPos++];
  649. }
  650. internal char RightNext()
  651. {
  652. return this._pattern[this._currentPos++];
  653. }
  654. internal RegexNode ScanBackslash()
  655. {
  656. char ch;
  657. RegexCharClass class2;
  658. if (this.CharsRight() == 0)
  659. {
  660. throw this.MakeException(RegExRes.GetString(0x13));
  661. }
  662. switch ((ch = this.RightChar()))
  663. {
  664. case 'S':
  665. this.RightNext();
  666. if (this.UseOptionE())
  667. {
  668. return new RegexNode(11, this._options, "\0\t\x000e !", string.Empty);
  669. }
  670. return new RegexNode(11, this._options, string.Empty, RegexCharClass.NotSpace);
  671. case 'W':
  672. this.RightNext();
  673. if (this.UseOptionE())
  674. {
  675. return new RegexNode(11, this._options, "\00:A[_`a{??", string.Empty);
  676. }
  677. return new RegexNode(11, this._options, string.Empty, RegexCharClass.NotWord);
  678. case 'Z':
  679. case 'A':
  680. case 'B':
  681. case 'G':
  682. case 'b':
  683. case 'z':
  684. this.RightNext();
  685. return new RegexNode(this.TypeFromCode(ch), this._options);
  686. case 'D':
  687. this.RightNext();
  688. if (!this.UseOptionE())
  689. {
  690. class2 = RegexCharClass.CreateFromCategory("Nd", true, false, this._pattern);
  691. return new RegexNode(11, this._options, string.Empty, class2.Category);
  692. }
  693. return new RegexNode(11, this._options, "\00:", string.Empty);
  694. case 'P':
  695. case 'p':
  696. this.RightNext();
  697. class2 = RegexCharClass.CreateFromCategory(this.ParseProperty(), ch != 'p', this.UseOptionI(), this._pattern);
  698. return new RegexNode(11, this._options, class2.ToSetCi(this.UseOptionI(), this._culture), class2.Category);
  699. case 'd':
  700. this.RightNext();
  701. if (!this.UseOptionE())
  702. {
  703. class2 = RegexCharClass.CreateFromCategory("Nd", false, false, this._pattern);
  704. return new RegexNode(11, this._options, string.Empty, class2.Category);
  705. }
  706. return new RegexNode(11, this._options, "0:", string.Empty);
  707. case 's':
  708. this.RightNext();
  709. if (this.UseOptionE())
  710. {
  711. return new RegexNode(11, this._options, "\t\x000e !", string.Empty);
  712. }
  713. return new RegexNode(11, this._options, string.Empty, RegexCharClass.Space);
  714. case 'w':
  715. this.RightNext();
  716. if (this.UseOptionE())
  717. {
  718. return new RegexNode(11, this._options, "0:A[_`a{??", string.Empty);
  719. }
  720. return new RegexNode(11, this._options, string.Empty, RegexCharClass.Word);
  721. }
  722. return this.ScanBasicBackslash();
  723. }
  724. internal RegexNode ScanBasicBackslash()
  725. {
  726. if (this.CharsRight() == 0)
  727. {
  728. throw this.MakeException(RegExRes.GetString(0x13));
  729. }
  730. bool flag = false;
  731. char ch2 = '\0';
  732. int pos = this.Textpos();
  733. char ch = this.RightChar();
  734. if (ch == 'k')
  735. {
  736. if (this.CharsRight() >= 2)
  737. {
  738. this.RightNext();
  739. ch = this.RightCharNext();
  740. switch (ch)
  741. {
  742. case '<':
  743. case '\'':
  744. flag = true;
  745. ch2 = (ch == '\'') ? '\'' : '>';
  746. break;
  747. }
  748. }
  749. if (!flag)
  750. {
  751. throw this.MakeException(RegExRes.GetString(20));
  752. }
  753. ch = this.RightChar();
  754. }
  755. else if (((ch == '<') || (ch == '\'')) && (this.CharsRight() > 1))
  756. {
  757. flag = true;
  758. ch2 = (ch == '\'') ? '\'' : '>';
  759. this.RightNext();
  760. ch = this.RightChar();
  761. }
  762. if ((flag && (ch >= '0')) && (ch <= '9'))
  763. {
  764. int i = this.ScanDecimal();
  765. if ((this.CharsRight() > 0) && (this.RightCharNext() == ch2))
  766. {
  767. if (!this.IsCaptureSlot(i))
  768. {
  769. throw this.MakeException(RegExRes.GetString(0x15, i.ToString()));
  770. }
  771. return new RegexNode(13, this._options, i);
  772. }
  773. }
  774. else if ((flag || (ch < '1')) || (ch > '9'))
  775. {
  776. if (flag && RegexCharClass.IsWordChar(ch))
  777. {
  778. string capname = this.ScanCapname();
  779. if ((this.CharsRight() > 0) && (this.RightCharNext() == ch2))
  780. {
  781. if (!this.IsCaptureName(capname))
  782. {
  783. throw this.MakeException(RegExRes.GetString(0x16, capname));
  784. }
  785. return new RegexNode(13, this._options, this.CaptureSlotFromName(capname));
  786. }
  787. }
  788. }
  789. else if (!this.UseOptionE())
  790. {
  791. int num6 = this.ScanDecimal();
  792. if (this.IsCaptureSlot(num6))
  793. {
  794. return new RegexNode(13, this._options, num6);
  795. }
  796. if (num6 <= 9)
  797. {
  798. throw this.MakeException(RegExRes.GetString(0x15, num6.ToString()));
  799. }
  800. }
  801. else
  802. {
  803. int m = -1;
  804. int num4 = ch - '0';
  805. int num5 = this.Textpos() - 1;
  806. while (num4 <= this._captop)
  807. {
  808. if (this.IsCaptureSlot(num4) && ((this._caps == null) || (((int) this._caps[num4]) < num5)))
  809. {
  810. m = num4;
  811. }
  812. this.RightNext();
  813. if (((this.CharsRight() == 0) || ((ch = this.RightChar()) < '0')) || (ch > '9'))
  814. {
  815. break;
  816. }
  817. num4 = (num4 * 10) + (ch - '0');
  818. }
  819. if (m >= 0)
  820. {
  821. return new RegexNode(13, this._options, m);
  822. }
  823. }
  824. this.Textto(pos);
  825. ch = this.ScanCharEscape();
  826. if (this.UseOptionI())
  827. {
  828. ch = char.ToLower(ch, this._culture);
  829. }
  830. return new RegexNode(9, this._options, ch);
  831. }
  832. internal void ScanBlank()
  833. {
  834. if (this.UseOptionX())
  835. {
  836. while (true)
  837. {
  838. while ((this.CharsRight() > 0) && IsSpace(this.RightChar()))
  839. {
  840. this.RightNext();
  841. }
  842. if (this.CharsRight() == 0)
  843. {
  844. return;
  845. }
  846. if (this.RightChar() == '#')
  847. {
  848. while ((this.CharsRight() > 0) && (this.RightChar() != '\n'))
  849. {
  850. this.RightNext();
  851. }
  852. }
  853. else
  854. {
  855. if (((this.CharsRight() < 3) || (this.RightChar(2) != '#')) || ((this.RightChar(1) != '?') || (this.RightChar() != '(')))
  856. {
  857. return;
  858. }
  859. while ((this.CharsRight() > 0) && (this.RightChar() != ')'))
  860. {
  861. this.RightNext();
  862. }
  863. if (this.CharsRight() == 0)
  864. {
  865. throw this.MakeException(RegExRes.GetString(0x12));
  866. }
  867. this.RightNext();
  868. }
  869. }
  870. }
  871. while (((this.CharsRight() >= 3) && (this.RightChar(2) == '#')) && ((this.RightChar(1) == '?') && (this.RightChar() == '(')))
  872. {
  873. while ((this.CharsRight() > 0) && (this.RightChar() != ')'))
  874. {
  875. this.RightNext();
  876. }
  877. if (this.CharsRight() == 0)
  878. {
  879. throw this.MakeException(RegExRes.GetString(0x12));
  880. }
  881. this.RightNext();
  882. }
  883. }
  884. internal string ScanCapname()
  885. {
  886. int startIndex = this.Textpos();
  887. while (this.CharsRight() > 0)
  888. {
  889. if (!RegexCharClass.IsWordChar(this.RightCharNext()))
  890. {
  891. this.LeftNext();
  892. break;
  893. }
  894. }
  895. return this._pattern.Substring(startIndex, this.Textpos() - startIndex);
  896. }
  897. internal RegexCharClass ScanCharClass(bool caseInsensitive)
  898. {
  899. return this.ScanCharClass(caseInsensitive, false);
  900. }
  901. internal RegexCharClass ScanCharClass(bool caseInsensitive, bool scanOnly)
  902. {
  903. bool flag2;
  904. char last = '\0';
  905. char first = '\0';
  906. RegexCharClass class2 = scanOnly ? null : new RegexCharClass();
  907. if ((this.CharsRight() > 0) && (this.RightChar() == '^'))
  908. {
  909. this.RightNext();
  910. flag2 = false;
  911. if (!scanOnly)
  912. {
  913. class2.Negate = true;
  914. }
  915. }
  916. bool flag = false;
  917. for (flag2 = true; this.CharsRight() > 0; flag2 = false)
  918. {
  919. char ch3 = last = this.RightCharNext();
  920. switch (ch3)
  921. {
  922. case '[':
  923. if (((this.CharsRight() > 0) && (this.RightChar() == ':')) && !flag)
  924. {
  925. int pos = this.Textpos();
  926. this.RightNext();
  927. this.ScanCapname();
  928. if (((this.CharsRight() < 2) || (this.RightCharNext() != ':')) || (this.RightCharNext() != ']'))
  929. {
  930. this.Textto(pos);
  931. }
  932. }
  933. goto Label_0360;
  934. case '\\':
  935. if (this.CharsRight() <= 0)
  936. {
  937. goto Label_0360;
  938. }
  939. ch3 = last = this.RightCharNext();
  940. if (ch3 > 'W')
  941. {
  942. goto Label_00C7;
  943. }
  944. if (ch3 > 'P')
  945. {
  946. break;
  947. }
  948. switch (ch3)
  949. {
  950. case 'D':
  951. goto Label_0148;
  952. case 'P':
  953. goto Label_02B8;
  954. }
  955. goto Label_0300;
  956. case ']':
  957. if (flag2)
  958. {
  959. goto Label_0360;
  960. }
  961. this.LeftNext();
  962. return class2;
  963. default:
  964. goto Label_0360;
  965. }
  966. switch (ch3)
  967. {
  968. case 'S':
  969. {
  970. if (!scanOnly)
  971. {
  972. if (flag)
  973. {
  974. throw this.MakeException(RegExRes.GetString(13, last.ToString()));
  975. }
  976. if (this.UseOptionE())
  977. {
  978. class2.AddSet("\0\t\x000e !");
  979. }
  980. else
  981. {
  982. class2.AddCategory(RegexCharClass.NotSpace);
  983. }
  984. }
  985. continue;
  986. }
  987. case 'W':
  988. {
  989. if (!scanOnly)
  990. {
  991. if (flag)
  992. {
  993. throw this.MakeException(RegExRes.GetString(13, last.ToString()));
  994. }
  995. if (this.UseOptionE())
  996. {
  997. class2.AddSet("\00:A[_`a{??");
  998. }
  999. else
  1000. {
  1001. class2.AddCategory(RegexCharClass.NotWord);
  1002. }
  1003. }
  1004. continue;
  1005. }
  1006. default:
  1007. goto Label_0300;
  1008. }
  1009. Label_00C7:
  1010. if (ch3 <= 'p')
  1011. {
  1012. switch (ch3)
  1013. {
  1014. case 'd':
  1015. goto Label_00F8;
  1016. case 'p':
  1017. goto Label_02B8;
  1018. }
  1019. }
  1020. else
  1021. {
  1022. switch (ch3)
  1023. {
  1024. case 's':
  1025. goto Label_0198;
  1026. case 'w':
  1027. goto Label_0228;
  1028. }
  1029. }
  1030. goto Label_0300;
  1031. Label_00F8:
  1032. if (!scanOnly)
  1033. {
  1034. if (flag)
  1035. {
  1036. throw this.MakeException(RegExRes.GetString(13, last.ToString()));
  1037. }
  1038. if (this.UseOptionE())
  1039. {
  1040. class2.AddSet("0:");
  1041. }
  1042. else
  1043. {
  1044. class2.AddCategoryFromName("Nd", false, false, this._pattern);
  1045. }
  1046. }
  1047. continue;
  1048. Label_0148:
  1049. if (!scanOnly)
  1050. {
  1051. if (flag)
  1052. {
  1053. throw this.MakeException(RegExRes.GetString(13, last.ToString()));
  1054. }
  1055. if (this.UseOptionE())
  1056. {
  1057. class2.AddSet("\00:");
  1058. }
  1059. else
  1060. {
  1061. class2.AddCategoryFromName("Nd", true, false, this._pattern);
  1062. }
  1063. }
  1064. continue;
  1065. Label_0198:
  1066. if (!scanOnly)
  1067. {
  1068. if (flag)
  1069. {
  1070. throw this.MakeException(RegExRes.GetString(13, last.ToString()));
  1071. }
  1072. if (this.UseOptionE())
  1073. {
  1074. class2.AddSet("\t\x000e !");
  1075. }
  1076. else
  1077. {
  1078. class2.AddCategory(RegexCharClass.Space);
  1079. }
  1080. }
  1081. continue;
  1082. Label_0228:
  1083. if (!scanOnly)
  1084. {
  1085. if (flag)
  1086. {
  1087. throw this.MakeException(RegExRes.GetString(13, last.ToString()));
  1088. }
  1089. if (this.UseOptionE())
  1090. {
  1091. class2.AddSet("0:A[_`a{??");
  1092. }
  1093. else
  1094. {
  1095. class2.AddCategory(RegexCharClass.Word);
  1096. }
  1097. }
  1098. continue;
  1099. Label_02B8:
  1100. if (!scanOnly)
  1101. {
  1102. if (flag)
  1103. {
  1104. throw this.MakeException(RegExRes.GetString(13, last.ToString()));
  1105. }
  1106. class2.AddCategoryFromName(this.ParseProperty(), last != 'p', caseInsensitive, this._pattern);
  1107. }
  1108. else
  1109. {
  1110. this.ParseProperty();
  1111. }
  1112. continue;
  1113. Label_0300:
  1114. this.LeftNext();
  1115. last = this.ScanCharEscape();
  1116. Label_0360:
  1117. if (flag)
  1118. {
  1119. flag = false;
  1120. if (!scanOnly)
  1121. {
  1122. if (first > last)
  1123. {
  1124. throw this.MakeException(RegExRes.GetString(14));
  1125. }
  1126. class2.AddRange(first, last);
  1127. }
  1128. }
  1129. else if (((this.CharsRight() >= 2) && (this.RightChar() == '-')) && (this.RightChar(1) != ']'))
  1130. {
  1131. first = last;
  1132. flag = true;
  1133. this.RightNext();
  1134. }
  1135. else if (!scanOnly)
  1136. {
  1137. class2.AddRange(last, last);
  1138. }
  1139. }
  1140. return class2;
  1141. }
  1142. internal char ScanCharEscape()
  1143. {
  1144. char ch = this.RightCharNext();
  1145. if ((ch >= '0') && (ch <= '7'))
  1146. {
  1147. this.LeftNext();
  1148. return this.ScanOctal();
  1149. }
  1150. switch (ch)
  1151. {
  1152. case 'a':
  1153. return '\a';
  1154. case 'b':
  1155. return '\b';
  1156. case 'c':
  1157. return this.ScanControl();
  1158. case 'e':
  1159. return '\x001b';
  1160. case 'f':
  1161. return '\f';
  1162. case 'n':
  1163. return '\n';
  1164. case 'r':
  1165. return '\r';
  1166. case 't':
  1167. return '\t';
  1168. case 'u':
  1169. return this.ScanHex(4);
  1170. case 'v':
  1171. return '\v';
  1172. case 'x':
  1173. return this.ScanHex(2);
  1174. }
  1175. if (!this.UseOptionE() && RegexCharClass.IsWordChar(ch))
  1176. {
  1177. throw this.MakeException(RegExRes.GetString(0x1a, ch.ToString()));
  1178. }
  1179. return ch;
  1180. }
  1181. internal char ScanControl()
  1182. {
  1183. if (this.CharsRight() <= 0)
  1184. {
  1185. throw this.MakeException(RegExRes.GetString(0x18));
  1186. }
  1187. char ch = this.RightCharNext();
  1188. if ((ch >= 'a') && (ch <= 'z'))
  1189. {
  1190. ch = (char) (ch - ' ');
  1191. }
  1192. if (((ch = (char) (ch - '@')) >= ' ') || (ch < '\0'))
  1193. {
  1194. throw this.MakeException(RegExRes.GetString(0x19));
  1195. }
  1196. return ch;
  1197. }
  1198. internal int ScanDecimal()
  1199. {
  1200. int num2;
  1201. int num = 0;
  1202. while (((this.CharsRight() > 0) && ((num2 = this.RightChar() - '0') <= 9)) && (num2 >= 0))
  1203. {
  1204. this.RightNext();
  1205. if ((num > 0xccccccc) || ((num == 0xccccccc) && (num2 > 7)))
  1206. {
  1207. num = 0x7fffffff;
  1208. }
  1209. num *= 10;
  1210. num += num2;
  1211. }
  1212. return num;
  1213. }
  1214. internal RegexNode ScanDollar()
  1215. {
  1216. if (this.CharsRight() != 0)
  1217. {
  1218. bool flag;
  1219. int pos = this.Textpos();
  1220. char ch = this.RightChar();
  1221. if ((ch == '{') && (this.CharsRight() > 1))
  1222. {
  1223. flag = true;
  1224. this.RightNext();
  1225. ch = this.RightChar();
  1226. }
  1227. else
  1228. {
  1229. flag = false;
  1230. }
  1231. if ((ch >= '0') && (ch <= '9'))
  1232. {
  1233. int i = this.ScanDecimal();
  1234. if ((!flag || ((this.CharsRight() > 0) && (this.RightCharNext() == '}'))) && this.IsCaptureSlot(i))
  1235. {
  1236. return new RegexNode(13, this._options, i);
  1237. }
  1238. }
  1239. else if (flag && RegexCharClass.IsWordChar(ch))
  1240. {
  1241. string capname = this.ScanCapname();
  1242. if (((this.CharsRight() > 0) && (this.RightCharNext() == '}')) && this.IsCaptureName(capname))
  1243. {
  1244. return new RegexNode(13, this._options, this.CaptureSlotFromName(capname));
  1245. }
  1246. }
  1247. else if (!flag)
  1248. {
  1249. int m = 1;
  1250. switch (ch)
  1251. {
  1252. case '$':
  1253. this.RightNext();
  1254. return new RegexNode(9, this._options, '$');
  1255. case '&':
  1256. m = 0;
  1257. break;
  1258. case '\'':
  1259. m = -2;
  1260. break;
  1261. case '+':
  1262. m = -3;
  1263. break;
  1264. case '_':
  1265. m = -4;
  1266. break;
  1267. case '`':
  1268. m = -1;
  1269. break;
  1270. }
  1271. if (m != 1)
  1272. {
  1273. this.RightNext();
  1274. return new RegexNode(13, this._options, m);
  1275. }
  1276. }
  1277. this.Textto(pos);
  1278. }
  1279. return new RegexNode(9, this._options, '$');
  1280. }
  1281. internal RegexNode ScanGroupOpen()
  1282. {
  1283. int num;
  1284. char ch = '\0';
  1285. char ch2 = '>';
  1286. if (((this.CharsRight() == 0) || (this.RightChar() != '?')) || ((this.RightChar() == '?') && (this.RightChar(1) == ')')))
  1287. {
  1288. if (!this.UseOptionN() && !this._ignoreNextParen)
  1289. {
  1290. return new RegexNode(0x1c, this._options, this._autocap++, -1);
  1291. }
  1292. this._ignoreNextParen = false;
  1293. return new RegexNode(0x1d, this._options);
  1294. }
  1295. this.RightNext();
  1296. if (this.CharsRight() == 0)
  1297. {
  1298. goto Label_04C6;
  1299. }
  1300. switch ((ch = this.RightCharNext()))
  1301. {
  1302. case '\'':
  1303. ch2 = '\'';
  1304. break;
  1305. case '(':
  1306. {
  1307. int num4 = this.Textpos();
  1308. ch = this.RightChar();
  1309. if ((ch < '0') || (ch > '9'))
  1310. {
  1311. if (RegexCharClass.IsWordChar(ch))
  1312. {
  1313. string capname = this.ScanCapname();
  1314. if ((this.IsCaptureName(capname) && (this.CharsRight() > 0)) && (this.RightCharNext() == ')'))
  1315. {
  1316. return new RegexNode(0x21, this._options, this.CaptureSlotFromName(capname));
  1317. }
  1318. }
  1319. num = 0x22;
  1320. this.Textto(num4 - 1);
  1321. this._ignoreNextParen = true;
  1322. int num6 = this.CharsRight();
  1323. if ((num6 >= 3) && (this.RightChar(1) == '?'))
  1324. {
  1325. char ch3 = this.RightChar(2);
  1326. switch (ch3)
  1327. {
  1328. case '#':
  1329. throw this.MakeException(RegExRes.GetString(0x23));
  1330. case '\'':
  1331. throw this.MakeException(RegExRes.GetString(0x22));
  1332. }
  1333. if (((num6 >= 4) && (ch3 == '<')) && ((this.RightChar(3) != '!') && (this.RightChar(3) != '=')))

Large files files are truncated, but you can click here to view the full file