oxipng/doc/src/regex/compile.rs.html
2016-04-08 13:52:15 -04:00

2230 lines
No EOL
162 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="rustdoc">
<meta name="description" content="Source to the Rust file `/Users/holmerj/.cargo/registry/src/github.com-88ac128001ac3a9a/regex-0.1.63/src/compile.rs`.">
<meta name="keywords" content="rust, rustlang, rust-lang">
<title>compile.rs.html -- source</title>
<link rel="stylesheet" type="text/css" href="../../rustdoc.css">
<link rel="stylesheet" type="text/css" href="../../main.css">
<link rel="shortcut icon" href="https://www.rust-lang.org/favicon.ico">
</head>
<body class="rustdoc">
<!--[if lte IE 8]>
<div class="warning">
This old browser is unsupported and will most likely display funky
things.
</div>
<![endif]-->
<nav class="sidebar">
<a href='../../regex/index.html'><img src='https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png' alt='logo' width='100'></a>
</nav>
<nav class="sub">
<form class="search-form js-only">
<div class="search-container">
<input class="search-input" name="search"
autocomplete="off"
placeholder="Click or press S to search, ? for more options…"
type="search">
</div>
</form>
</nav>
<section id='main' class="content source"><pre class="line-numbers"><span id="1"> 1</span>
<span id="2"> 2</span>
<span id="3"> 3</span>
<span id="4"> 4</span>
<span id="5"> 5</span>
<span id="6"> 6</span>
<span id="7"> 7</span>
<span id="8"> 8</span>
<span id="9"> 9</span>
<span id="10"> 10</span>
<span id="11"> 11</span>
<span id="12"> 12</span>
<span id="13"> 13</span>
<span id="14"> 14</span>
<span id="15"> 15</span>
<span id="16"> 16</span>
<span id="17"> 17</span>
<span id="18"> 18</span>
<span id="19"> 19</span>
<span id="20"> 20</span>
<span id="21"> 21</span>
<span id="22"> 22</span>
<span id="23"> 23</span>
<span id="24"> 24</span>
<span id="25"> 25</span>
<span id="26"> 26</span>
<span id="27"> 27</span>
<span id="28"> 28</span>
<span id="29"> 29</span>
<span id="30"> 30</span>
<span id="31"> 31</span>
<span id="32"> 32</span>
<span id="33"> 33</span>
<span id="34"> 34</span>
<span id="35"> 35</span>
<span id="36"> 36</span>
<span id="37"> 37</span>
<span id="38"> 38</span>
<span id="39"> 39</span>
<span id="40"> 40</span>
<span id="41"> 41</span>
<span id="42"> 42</span>
<span id="43"> 43</span>
<span id="44"> 44</span>
<span id="45"> 45</span>
<span id="46"> 46</span>
<span id="47"> 47</span>
<span id="48"> 48</span>
<span id="49"> 49</span>
<span id="50"> 50</span>
<span id="51"> 51</span>
<span id="52"> 52</span>
<span id="53"> 53</span>
<span id="54"> 54</span>
<span id="55"> 55</span>
<span id="56"> 56</span>
<span id="57"> 57</span>
<span id="58"> 58</span>
<span id="59"> 59</span>
<span id="60"> 60</span>
<span id="61"> 61</span>
<span id="62"> 62</span>
<span id="63"> 63</span>
<span id="64"> 64</span>
<span id="65"> 65</span>
<span id="66"> 66</span>
<span id="67"> 67</span>
<span id="68"> 68</span>
<span id="69"> 69</span>
<span id="70"> 70</span>
<span id="71"> 71</span>
<span id="72"> 72</span>
<span id="73"> 73</span>
<span id="74"> 74</span>
<span id="75"> 75</span>
<span id="76"> 76</span>
<span id="77"> 77</span>
<span id="78"> 78</span>
<span id="79"> 79</span>
<span id="80"> 80</span>
<span id="81"> 81</span>
<span id="82"> 82</span>
<span id="83"> 83</span>
<span id="84"> 84</span>
<span id="85"> 85</span>
<span id="86"> 86</span>
<span id="87"> 87</span>
<span id="88"> 88</span>
<span id="89"> 89</span>
<span id="90"> 90</span>
<span id="91"> 91</span>
<span id="92"> 92</span>
<span id="93"> 93</span>
<span id="94"> 94</span>
<span id="95"> 95</span>
<span id="96"> 96</span>
<span id="97"> 97</span>
<span id="98"> 98</span>
<span id="99"> 99</span>
<span id="100"> 100</span>
<span id="101"> 101</span>
<span id="102"> 102</span>
<span id="103"> 103</span>
<span id="104"> 104</span>
<span id="105"> 105</span>
<span id="106"> 106</span>
<span id="107"> 107</span>
<span id="108"> 108</span>
<span id="109"> 109</span>
<span id="110"> 110</span>
<span id="111"> 111</span>
<span id="112"> 112</span>
<span id="113"> 113</span>
<span id="114"> 114</span>
<span id="115"> 115</span>
<span id="116"> 116</span>
<span id="117"> 117</span>
<span id="118"> 118</span>
<span id="119"> 119</span>
<span id="120"> 120</span>
<span id="121"> 121</span>
<span id="122"> 122</span>
<span id="123"> 123</span>
<span id="124"> 124</span>
<span id="125"> 125</span>
<span id="126"> 126</span>
<span id="127"> 127</span>
<span id="128"> 128</span>
<span id="129"> 129</span>
<span id="130"> 130</span>
<span id="131"> 131</span>
<span id="132"> 132</span>
<span id="133"> 133</span>
<span id="134"> 134</span>
<span id="135"> 135</span>
<span id="136"> 136</span>
<span id="137"> 137</span>
<span id="138"> 138</span>
<span id="139"> 139</span>
<span id="140"> 140</span>
<span id="141"> 141</span>
<span id="142"> 142</span>
<span id="143"> 143</span>
<span id="144"> 144</span>
<span id="145"> 145</span>
<span id="146"> 146</span>
<span id="147"> 147</span>
<span id="148"> 148</span>
<span id="149"> 149</span>
<span id="150"> 150</span>
<span id="151"> 151</span>
<span id="152"> 152</span>
<span id="153"> 153</span>
<span id="154"> 154</span>
<span id="155"> 155</span>
<span id="156"> 156</span>
<span id="157"> 157</span>
<span id="158"> 158</span>
<span id="159"> 159</span>
<span id="160"> 160</span>
<span id="161"> 161</span>
<span id="162"> 162</span>
<span id="163"> 163</span>
<span id="164"> 164</span>
<span id="165"> 165</span>
<span id="166"> 166</span>
<span id="167"> 167</span>
<span id="168"> 168</span>
<span id="169"> 169</span>
<span id="170"> 170</span>
<span id="171"> 171</span>
<span id="172"> 172</span>
<span id="173"> 173</span>
<span id="174"> 174</span>
<span id="175"> 175</span>
<span id="176"> 176</span>
<span id="177"> 177</span>
<span id="178"> 178</span>
<span id="179"> 179</span>
<span id="180"> 180</span>
<span id="181"> 181</span>
<span id="182"> 182</span>
<span id="183"> 183</span>
<span id="184"> 184</span>
<span id="185"> 185</span>
<span id="186"> 186</span>
<span id="187"> 187</span>
<span id="188"> 188</span>
<span id="189"> 189</span>
<span id="190"> 190</span>
<span id="191"> 191</span>
<span id="192"> 192</span>
<span id="193"> 193</span>
<span id="194"> 194</span>
<span id="195"> 195</span>
<span id="196"> 196</span>
<span id="197"> 197</span>
<span id="198"> 198</span>
<span id="199"> 199</span>
<span id="200"> 200</span>
<span id="201"> 201</span>
<span id="202"> 202</span>
<span id="203"> 203</span>
<span id="204"> 204</span>
<span id="205"> 205</span>
<span id="206"> 206</span>
<span id="207"> 207</span>
<span id="208"> 208</span>
<span id="209"> 209</span>
<span id="210"> 210</span>
<span id="211"> 211</span>
<span id="212"> 212</span>
<span id="213"> 213</span>
<span id="214"> 214</span>
<span id="215"> 215</span>
<span id="216"> 216</span>
<span id="217"> 217</span>
<span id="218"> 218</span>
<span id="219"> 219</span>
<span id="220"> 220</span>
<span id="221"> 221</span>
<span id="222"> 222</span>
<span id="223"> 223</span>
<span id="224"> 224</span>
<span id="225"> 225</span>
<span id="226"> 226</span>
<span id="227"> 227</span>
<span id="228"> 228</span>
<span id="229"> 229</span>
<span id="230"> 230</span>
<span id="231"> 231</span>
<span id="232"> 232</span>
<span id="233"> 233</span>
<span id="234"> 234</span>
<span id="235"> 235</span>
<span id="236"> 236</span>
<span id="237"> 237</span>
<span id="238"> 238</span>
<span id="239"> 239</span>
<span id="240"> 240</span>
<span id="241"> 241</span>
<span id="242"> 242</span>
<span id="243"> 243</span>
<span id="244"> 244</span>
<span id="245"> 245</span>
<span id="246"> 246</span>
<span id="247"> 247</span>
<span id="248"> 248</span>
<span id="249"> 249</span>
<span id="250"> 250</span>
<span id="251"> 251</span>
<span id="252"> 252</span>
<span id="253"> 253</span>
<span id="254"> 254</span>
<span id="255"> 255</span>
<span id="256"> 256</span>
<span id="257"> 257</span>
<span id="258"> 258</span>
<span id="259"> 259</span>
<span id="260"> 260</span>
<span id="261"> 261</span>
<span id="262"> 262</span>
<span id="263"> 263</span>
<span id="264"> 264</span>
<span id="265"> 265</span>
<span id="266"> 266</span>
<span id="267"> 267</span>
<span id="268"> 268</span>
<span id="269"> 269</span>
<span id="270"> 270</span>
<span id="271"> 271</span>
<span id="272"> 272</span>
<span id="273"> 273</span>
<span id="274"> 274</span>
<span id="275"> 275</span>
<span id="276"> 276</span>
<span id="277"> 277</span>
<span id="278"> 278</span>
<span id="279"> 279</span>
<span id="280"> 280</span>
<span id="281"> 281</span>
<span id="282"> 282</span>
<span id="283"> 283</span>
<span id="284"> 284</span>
<span id="285"> 285</span>
<span id="286"> 286</span>
<span id="287"> 287</span>
<span id="288"> 288</span>
<span id="289"> 289</span>
<span id="290"> 290</span>
<span id="291"> 291</span>
<span id="292"> 292</span>
<span id="293"> 293</span>
<span id="294"> 294</span>
<span id="295"> 295</span>
<span id="296"> 296</span>
<span id="297"> 297</span>
<span id="298"> 298</span>
<span id="299"> 299</span>
<span id="300"> 300</span>
<span id="301"> 301</span>
<span id="302"> 302</span>
<span id="303"> 303</span>
<span id="304"> 304</span>
<span id="305"> 305</span>
<span id="306"> 306</span>
<span id="307"> 307</span>
<span id="308"> 308</span>
<span id="309"> 309</span>
<span id="310"> 310</span>
<span id="311"> 311</span>
<span id="312"> 312</span>
<span id="313"> 313</span>
<span id="314"> 314</span>
<span id="315"> 315</span>
<span id="316"> 316</span>
<span id="317"> 317</span>
<span id="318"> 318</span>
<span id="319"> 319</span>
<span id="320"> 320</span>
<span id="321"> 321</span>
<span id="322"> 322</span>
<span id="323"> 323</span>
<span id="324"> 324</span>
<span id="325"> 325</span>
<span id="326"> 326</span>
<span id="327"> 327</span>
<span id="328"> 328</span>
<span id="329"> 329</span>
<span id="330"> 330</span>
<span id="331"> 331</span>
<span id="332"> 332</span>
<span id="333"> 333</span>
<span id="334"> 334</span>
<span id="335"> 335</span>
<span id="336"> 336</span>
<span id="337"> 337</span>
<span id="338"> 338</span>
<span id="339"> 339</span>
<span id="340"> 340</span>
<span id="341"> 341</span>
<span id="342"> 342</span>
<span id="343"> 343</span>
<span id="344"> 344</span>
<span id="345"> 345</span>
<span id="346"> 346</span>
<span id="347"> 347</span>
<span id="348"> 348</span>
<span id="349"> 349</span>
<span id="350"> 350</span>
<span id="351"> 351</span>
<span id="352"> 352</span>
<span id="353"> 353</span>
<span id="354"> 354</span>
<span id="355"> 355</span>
<span id="356"> 356</span>
<span id="357"> 357</span>
<span id="358"> 358</span>
<span id="359"> 359</span>
<span id="360"> 360</span>
<span id="361"> 361</span>
<span id="362"> 362</span>
<span id="363"> 363</span>
<span id="364"> 364</span>
<span id="365"> 365</span>
<span id="366"> 366</span>
<span id="367"> 367</span>
<span id="368"> 368</span>
<span id="369"> 369</span>
<span id="370"> 370</span>
<span id="371"> 371</span>
<span id="372"> 372</span>
<span id="373"> 373</span>
<span id="374"> 374</span>
<span id="375"> 375</span>
<span id="376"> 376</span>
<span id="377"> 377</span>
<span id="378"> 378</span>
<span id="379"> 379</span>
<span id="380"> 380</span>
<span id="381"> 381</span>
<span id="382"> 382</span>
<span id="383"> 383</span>
<span id="384"> 384</span>
<span id="385"> 385</span>
<span id="386"> 386</span>
<span id="387"> 387</span>
<span id="388"> 388</span>
<span id="389"> 389</span>
<span id="390"> 390</span>
<span id="391"> 391</span>
<span id="392"> 392</span>
<span id="393"> 393</span>
<span id="394"> 394</span>
<span id="395"> 395</span>
<span id="396"> 396</span>
<span id="397"> 397</span>
<span id="398"> 398</span>
<span id="399"> 399</span>
<span id="400"> 400</span>
<span id="401"> 401</span>
<span id="402"> 402</span>
<span id="403"> 403</span>
<span id="404"> 404</span>
<span id="405"> 405</span>
<span id="406"> 406</span>
<span id="407"> 407</span>
<span id="408"> 408</span>
<span id="409"> 409</span>
<span id="410"> 410</span>
<span id="411"> 411</span>
<span id="412"> 412</span>
<span id="413"> 413</span>
<span id="414"> 414</span>
<span id="415"> 415</span>
<span id="416"> 416</span>
<span id="417"> 417</span>
<span id="418"> 418</span>
<span id="419"> 419</span>
<span id="420"> 420</span>
<span id="421"> 421</span>
<span id="422"> 422</span>
<span id="423"> 423</span>
<span id="424"> 424</span>
<span id="425"> 425</span>
<span id="426"> 426</span>
<span id="427"> 427</span>
<span id="428"> 428</span>
<span id="429"> 429</span>
<span id="430"> 430</span>
<span id="431"> 431</span>
<span id="432"> 432</span>
<span id="433"> 433</span>
<span id="434"> 434</span>
<span id="435"> 435</span>
<span id="436"> 436</span>
<span id="437"> 437</span>
<span id="438"> 438</span>
<span id="439"> 439</span>
<span id="440"> 440</span>
<span id="441"> 441</span>
<span id="442"> 442</span>
<span id="443"> 443</span>
<span id="444"> 444</span>
<span id="445"> 445</span>
<span id="446"> 446</span>
<span id="447"> 447</span>
<span id="448"> 448</span>
<span id="449"> 449</span>
<span id="450"> 450</span>
<span id="451"> 451</span>
<span id="452"> 452</span>
<span id="453"> 453</span>
<span id="454"> 454</span>
<span id="455"> 455</span>
<span id="456"> 456</span>
<span id="457"> 457</span>
<span id="458"> 458</span>
<span id="459"> 459</span>
<span id="460"> 460</span>
<span id="461"> 461</span>
<span id="462"> 462</span>
<span id="463"> 463</span>
<span id="464"> 464</span>
<span id="465"> 465</span>
<span id="466"> 466</span>
<span id="467"> 467</span>
<span id="468"> 468</span>
<span id="469"> 469</span>
<span id="470"> 470</span>
<span id="471"> 471</span>
<span id="472"> 472</span>
<span id="473"> 473</span>
<span id="474"> 474</span>
<span id="475"> 475</span>
<span id="476"> 476</span>
<span id="477"> 477</span>
<span id="478"> 478</span>
<span id="479"> 479</span>
<span id="480"> 480</span>
<span id="481"> 481</span>
<span id="482"> 482</span>
<span id="483"> 483</span>
<span id="484"> 484</span>
<span id="485"> 485</span>
<span id="486"> 486</span>
<span id="487"> 487</span>
<span id="488"> 488</span>
<span id="489"> 489</span>
<span id="490"> 490</span>
<span id="491"> 491</span>
<span id="492"> 492</span>
<span id="493"> 493</span>
<span id="494"> 494</span>
<span id="495"> 495</span>
<span id="496"> 496</span>
<span id="497"> 497</span>
<span id="498"> 498</span>
<span id="499"> 499</span>
<span id="500"> 500</span>
<span id="501"> 501</span>
<span id="502"> 502</span>
<span id="503"> 503</span>
<span id="504"> 504</span>
<span id="505"> 505</span>
<span id="506"> 506</span>
<span id="507"> 507</span>
<span id="508"> 508</span>
<span id="509"> 509</span>
<span id="510"> 510</span>
<span id="511"> 511</span>
<span id="512"> 512</span>
<span id="513"> 513</span>
<span id="514"> 514</span>
<span id="515"> 515</span>
<span id="516"> 516</span>
<span id="517"> 517</span>
<span id="518"> 518</span>
<span id="519"> 519</span>
<span id="520"> 520</span>
<span id="521"> 521</span>
<span id="522"> 522</span>
<span id="523"> 523</span>
<span id="524"> 524</span>
<span id="525"> 525</span>
<span id="526"> 526</span>
<span id="527"> 527</span>
<span id="528"> 528</span>
<span id="529"> 529</span>
<span id="530"> 530</span>
<span id="531"> 531</span>
<span id="532"> 532</span>
<span id="533"> 533</span>
<span id="534"> 534</span>
<span id="535"> 535</span>
<span id="536"> 536</span>
<span id="537"> 537</span>
<span id="538"> 538</span>
<span id="539"> 539</span>
<span id="540"> 540</span>
<span id="541"> 541</span>
<span id="542"> 542</span>
<span id="543"> 543</span>
<span id="544"> 544</span>
<span id="545"> 545</span>
<span id="546"> 546</span>
<span id="547"> 547</span>
<span id="548"> 548</span>
<span id="549"> 549</span>
<span id="550"> 550</span>
<span id="551"> 551</span>
<span id="552"> 552</span>
<span id="553"> 553</span>
<span id="554"> 554</span>
<span id="555"> 555</span>
<span id="556"> 556</span>
<span id="557"> 557</span>
<span id="558"> 558</span>
<span id="559"> 559</span>
<span id="560"> 560</span>
<span id="561"> 561</span>
<span id="562"> 562</span>
<span id="563"> 563</span>
<span id="564"> 564</span>
<span id="565"> 565</span>
<span id="566"> 566</span>
<span id="567"> 567</span>
<span id="568"> 568</span>
<span id="569"> 569</span>
<span id="570"> 570</span>
<span id="571"> 571</span>
<span id="572"> 572</span>
<span id="573"> 573</span>
<span id="574"> 574</span>
<span id="575"> 575</span>
<span id="576"> 576</span>
<span id="577"> 577</span>
<span id="578"> 578</span>
<span id="579"> 579</span>
<span id="580"> 580</span>
<span id="581"> 581</span>
<span id="582"> 582</span>
<span id="583"> 583</span>
<span id="584"> 584</span>
<span id="585"> 585</span>
<span id="586"> 586</span>
<span id="587"> 587</span>
<span id="588"> 588</span>
<span id="589"> 589</span>
<span id="590"> 590</span>
<span id="591"> 591</span>
<span id="592"> 592</span>
<span id="593"> 593</span>
<span id="594"> 594</span>
<span id="595"> 595</span>
<span id="596"> 596</span>
<span id="597"> 597</span>
<span id="598"> 598</span>
<span id="599"> 599</span>
<span id="600"> 600</span>
<span id="601"> 601</span>
<span id="602"> 602</span>
<span id="603"> 603</span>
<span id="604"> 604</span>
<span id="605"> 605</span>
<span id="606"> 606</span>
<span id="607"> 607</span>
<span id="608"> 608</span>
<span id="609"> 609</span>
<span id="610"> 610</span>
<span id="611"> 611</span>
<span id="612"> 612</span>
<span id="613"> 613</span>
<span id="614"> 614</span>
<span id="615"> 615</span>
<span id="616"> 616</span>
<span id="617"> 617</span>
<span id="618"> 618</span>
<span id="619"> 619</span>
<span id="620"> 620</span>
<span id="621"> 621</span>
<span id="622"> 622</span>
<span id="623"> 623</span>
<span id="624"> 624</span>
<span id="625"> 625</span>
<span id="626"> 626</span>
<span id="627"> 627</span>
<span id="628"> 628</span>
<span id="629"> 629</span>
<span id="630"> 630</span>
<span id="631"> 631</span>
<span id="632"> 632</span>
<span id="633"> 633</span>
<span id="634"> 634</span>
<span id="635"> 635</span>
<span id="636"> 636</span>
<span id="637"> 637</span>
<span id="638"> 638</span>
<span id="639"> 639</span>
<span id="640"> 640</span>
<span id="641"> 641</span>
<span id="642"> 642</span>
<span id="643"> 643</span>
<span id="644"> 644</span>
<span id="645"> 645</span>
<span id="646"> 646</span>
<span id="647"> 647</span>
<span id="648"> 648</span>
<span id="649"> 649</span>
<span id="650"> 650</span>
<span id="651"> 651</span>
<span id="652"> 652</span>
<span id="653"> 653</span>
<span id="654"> 654</span>
<span id="655"> 655</span>
<span id="656"> 656</span>
<span id="657"> 657</span>
<span id="658"> 658</span>
<span id="659"> 659</span>
<span id="660"> 660</span>
<span id="661"> 661</span>
<span id="662"> 662</span>
<span id="663"> 663</span>
<span id="664"> 664</span>
<span id="665"> 665</span>
<span id="666"> 666</span>
<span id="667"> 667</span>
<span id="668"> 668</span>
<span id="669"> 669</span>
<span id="670"> 670</span>
<span id="671"> 671</span>
<span id="672"> 672</span>
<span id="673"> 673</span>
<span id="674"> 674</span>
<span id="675"> 675</span>
<span id="676"> 676</span>
<span id="677"> 677</span>
<span id="678"> 678</span>
<span id="679"> 679</span>
<span id="680"> 680</span>
<span id="681"> 681</span>
<span id="682"> 682</span>
<span id="683"> 683</span>
<span id="684"> 684</span>
<span id="685"> 685</span>
<span id="686"> 686</span>
<span id="687"> 687</span>
<span id="688"> 688</span>
<span id="689"> 689</span>
<span id="690"> 690</span>
<span id="691"> 691</span>
<span id="692"> 692</span>
<span id="693"> 693</span>
<span id="694"> 694</span>
<span id="695"> 695</span>
<span id="696"> 696</span>
<span id="697"> 697</span>
<span id="698"> 698</span>
<span id="699"> 699</span>
<span id="700"> 700</span>
<span id="701"> 701</span>
<span id="702"> 702</span>
<span id="703"> 703</span>
<span id="704"> 704</span>
<span id="705"> 705</span>
<span id="706"> 706</span>
<span id="707"> 707</span>
<span id="708"> 708</span>
<span id="709"> 709</span>
<span id="710"> 710</span>
<span id="711"> 711</span>
<span id="712"> 712</span>
<span id="713"> 713</span>
<span id="714"> 714</span>
<span id="715"> 715</span>
<span id="716"> 716</span>
<span id="717"> 717</span>
<span id="718"> 718</span>
<span id="719"> 719</span>
<span id="720"> 720</span>
<span id="721"> 721</span>
<span id="722"> 722</span>
<span id="723"> 723</span>
<span id="724"> 724</span>
<span id="725"> 725</span>
<span id="726"> 726</span>
<span id="727"> 727</span>
<span id="728"> 728</span>
<span id="729"> 729</span>
<span id="730"> 730</span>
<span id="731"> 731</span>
<span id="732"> 732</span>
<span id="733"> 733</span>
<span id="734"> 734</span>
<span id="735"> 735</span>
<span id="736"> 736</span>
<span id="737"> 737</span>
<span id="738"> 738</span>
<span id="739"> 739</span>
<span id="740"> 740</span>
<span id="741"> 741</span>
<span id="742"> 742</span>
<span id="743"> 743</span>
<span id="744"> 744</span>
<span id="745"> 745</span>
<span id="746"> 746</span>
<span id="747"> 747</span>
<span id="748"> 748</span>
<span id="749"> 749</span>
<span id="750"> 750</span>
<span id="751"> 751</span>
<span id="752"> 752</span>
<span id="753"> 753</span>
<span id="754"> 754</span>
<span id="755"> 755</span>
<span id="756"> 756</span>
<span id="757"> 757</span>
<span id="758"> 758</span>
<span id="759"> 759</span>
<span id="760"> 760</span>
<span id="761"> 761</span>
<span id="762"> 762</span>
<span id="763"> 763</span>
<span id="764"> 764</span>
<span id="765"> 765</span>
<span id="766"> 766</span>
<span id="767"> 767</span>
<span id="768"> 768</span>
<span id="769"> 769</span>
<span id="770"> 770</span>
<span id="771"> 771</span>
<span id="772"> 772</span>
<span id="773"> 773</span>
<span id="774"> 774</span>
<span id="775"> 775</span>
<span id="776"> 776</span>
<span id="777"> 777</span>
<span id="778"> 778</span>
<span id="779"> 779</span>
<span id="780"> 780</span>
<span id="781"> 781</span>
<span id="782"> 782</span>
<span id="783"> 783</span>
<span id="784"> 784</span>
<span id="785"> 785</span>
<span id="786"> 786</span>
<span id="787"> 787</span>
<span id="788"> 788</span>
<span id="789"> 789</span>
<span id="790"> 790</span>
<span id="791"> 791</span>
<span id="792"> 792</span>
<span id="793"> 793</span>
<span id="794"> 794</span>
<span id="795"> 795</span>
<span id="796"> 796</span>
<span id="797"> 797</span>
<span id="798"> 798</span>
<span id="799"> 799</span>
<span id="800"> 800</span>
<span id="801"> 801</span>
<span id="802"> 802</span>
<span id="803"> 803</span>
<span id="804"> 804</span>
<span id="805"> 805</span>
<span id="806"> 806</span>
<span id="807"> 807</span>
<span id="808"> 808</span>
<span id="809"> 809</span>
<span id="810"> 810</span>
<span id="811"> 811</span>
<span id="812"> 812</span>
<span id="813"> 813</span>
<span id="814"> 814</span>
<span id="815"> 815</span>
<span id="816"> 816</span>
<span id="817"> 817</span>
<span id="818"> 818</span>
<span id="819"> 819</span>
<span id="820"> 820</span>
<span id="821"> 821</span>
<span id="822"> 822</span>
<span id="823"> 823</span>
<span id="824"> 824</span>
<span id="825"> 825</span>
<span id="826"> 826</span>
<span id="827"> 827</span>
<span id="828"> 828</span>
<span id="829"> 829</span>
<span id="830"> 830</span>
<span id="831"> 831</span>
<span id="832"> 832</span>
<span id="833"> 833</span>
<span id="834"> 834</span>
<span id="835"> 835</span>
<span id="836"> 836</span>
<span id="837"> 837</span>
<span id="838"> 838</span>
<span id="839"> 839</span>
<span id="840"> 840</span>
<span id="841"> 841</span>
<span id="842"> 842</span>
<span id="843"> 843</span>
<span id="844"> 844</span>
<span id="845"> 845</span>
<span id="846"> 846</span>
<span id="847"> 847</span>
<span id="848"> 848</span>
<span id="849"> 849</span>
<span id="850"> 850</span>
<span id="851"> 851</span>
<span id="852"> 852</span>
<span id="853"> 853</span>
<span id="854"> 854</span>
<span id="855"> 855</span>
<span id="856"> 856</span>
<span id="857"> 857</span>
<span id="858"> 858</span>
<span id="859"> 859</span>
<span id="860"> 860</span>
<span id="861"> 861</span>
<span id="862"> 862</span>
<span id="863"> 863</span>
<span id="864"> 864</span>
<span id="865"> 865</span>
<span id="866"> 866</span>
<span id="867"> 867</span>
<span id="868"> 868</span>
<span id="869"> 869</span>
<span id="870"> 870</span>
<span id="871"> 871</span>
<span id="872"> 872</span>
<span id="873"> 873</span>
<span id="874"> 874</span>
<span id="875"> 875</span>
<span id="876"> 876</span>
<span id="877"> 877</span>
<span id="878"> 878</span>
<span id="879"> 879</span>
<span id="880"> 880</span>
<span id="881"> 881</span>
<span id="882"> 882</span>
<span id="883"> 883</span>
<span id="884"> 884</span>
<span id="885"> 885</span>
<span id="886"> 886</span>
<span id="887"> 887</span>
<span id="888"> 888</span>
<span id="889"> 889</span>
<span id="890"> 890</span>
<span id="891"> 891</span>
<span id="892"> 892</span>
<span id="893"> 893</span>
<span id="894"> 894</span>
<span id="895"> 895</span>
<span id="896"> 896</span>
<span id="897"> 897</span>
<span id="898"> 898</span>
<span id="899"> 899</span>
<span id="900"> 900</span>
<span id="901"> 901</span>
<span id="902"> 902</span>
<span id="903"> 903</span>
<span id="904"> 904</span>
<span id="905"> 905</span>
<span id="906"> 906</span>
<span id="907"> 907</span>
<span id="908"> 908</span>
<span id="909"> 909</span>
<span id="910"> 910</span>
<span id="911"> 911</span>
<span id="912"> 912</span>
<span id="913"> 913</span>
<span id="914"> 914</span>
<span id="915"> 915</span>
<span id="916"> 916</span>
<span id="917"> 917</span>
<span id="918"> 918</span>
<span id="919"> 919</span>
<span id="920"> 920</span>
<span id="921"> 921</span>
<span id="922"> 922</span>
<span id="923"> 923</span>
<span id="924"> 924</span>
<span id="925"> 925</span>
<span id="926"> 926</span>
<span id="927"> 927</span>
<span id="928"> 928</span>
<span id="929"> 929</span>
<span id="930"> 930</span>
<span id="931"> 931</span>
<span id="932"> 932</span>
<span id="933"> 933</span>
<span id="934"> 934</span>
<span id="935"> 935</span>
<span id="936"> 936</span>
<span id="937"> 937</span>
<span id="938"> 938</span>
<span id="939"> 939</span>
<span id="940"> 940</span>
<span id="941"> 941</span>
<span id="942"> 942</span>
<span id="943"> 943</span>
<span id="944"> 944</span>
<span id="945"> 945</span>
<span id="946"> 946</span>
<span id="947"> 947</span>
<span id="948"> 948</span>
<span id="949"> 949</span>
<span id="950"> 950</span>
<span id="951"> 951</span>
<span id="952"> 952</span>
<span id="953"> 953</span>
<span id="954"> 954</span>
<span id="955"> 955</span>
<span id="956"> 956</span>
<span id="957"> 957</span>
<span id="958"> 958</span>
<span id="959"> 959</span>
<span id="960"> 960</span>
<span id="961"> 961</span>
<span id="962"> 962</span>
<span id="963"> 963</span>
<span id="964"> 964</span>
<span id="965"> 965</span>
<span id="966"> 966</span>
<span id="967"> 967</span>
<span id="968"> 968</span>
<span id="969"> 969</span>
<span id="970"> 970</span>
<span id="971"> 971</span>
<span id="972"> 972</span>
<span id="973"> 973</span>
<span id="974"> 974</span>
<span id="975"> 975</span>
<span id="976"> 976</span>
<span id="977"> 977</span>
<span id="978"> 978</span>
<span id="979"> 979</span>
<span id="980"> 980</span>
<span id="981"> 981</span>
<span id="982"> 982</span>
<span id="983"> 983</span>
<span id="984"> 984</span>
<span id="985"> 985</span>
<span id="986"> 986</span>
<span id="987"> 987</span>
<span id="988"> 988</span>
<span id="989"> 989</span>
<span id="990"> 990</span>
<span id="991"> 991</span>
<span id="992"> 992</span>
<span id="993"> 993</span>
<span id="994"> 994</span>
<span id="995"> 995</span>
<span id="996"> 996</span>
<span id="997"> 997</span>
<span id="998"> 998</span>
<span id="999"> 999</span>
<span id="1000">1000</span>
<span id="1001">1001</span>
<span id="1002">1002</span>
<span id="1003">1003</span>
<span id="1004">1004</span>
<span id="1005">1005</span>
<span id="1006">1006</span>
<span id="1007">1007</span>
<span id="1008">1008</span>
<span id="1009">1009</span>
<span id="1010">1010</span>
<span id="1011">1011</span>
<span id="1012">1012</span>
<span id="1013">1013</span>
<span id="1014">1014</span>
<span id="1015">1015</span>
<span id="1016">1016</span>
<span id="1017">1017</span>
<span id="1018">1018</span>
<span id="1019">1019</span>
<span id="1020">1020</span>
<span id="1021">1021</span>
<span id="1022">1022</span>
<span id="1023">1023</span>
<span id="1024">1024</span>
<span id="1025">1025</span>
<span id="1026">1026</span>
<span id="1027">1027</span>
<span id="1028">1028</span>
<span id="1029">1029</span>
<span id="1030">1030</span>
<span id="1031">1031</span>
<span id="1032">1032</span>
<span id="1033">1033</span>
<span id="1034">1034</span>
<span id="1035">1035</span>
<span id="1036">1036</span>
<span id="1037">1037</span>
<span id="1038">1038</span>
<span id="1039">1039</span>
<span id="1040">1040</span>
<span id="1041">1041</span>
<span id="1042">1042</span>
<span id="1043">1043</span>
<span id="1044">1044</span>
<span id="1045">1045</span>
<span id="1046">1046</span>
<span id="1047">1047</span>
<span id="1048">1048</span>
<span id="1049">1049</span>
<span id="1050">1050</span>
<span id="1051">1051</span>
<span id="1052">1052</span>
<span id="1053">1053</span>
<span id="1054">1054</span>
<span id="1055">1055</span>
<span id="1056">1056</span>
<span id="1057">1057</span>
<span id="1058">1058</span>
<span id="1059">1059</span>
<span id="1060">1060</span>
<span id="1061">1061</span>
</pre><pre class='rust '>
<span class='comment'>// Copyright 2014-2016 The Rust Project Developers. See the COPYRIGHT</span>
<span class='comment'>// file at the top-level directory of this distribution and at</span>
<span class='comment'>// http://rust-lang.org/COPYRIGHT.</span>
<span class='comment'>//</span>
<span class='comment'>// Licensed under the Apache License, Version 2.0 &lt;LICENSE-APACHE or</span>
<span class='comment'>// http://www.apache.org/licenses/LICENSE-2.0&gt; or the MIT license</span>
<span class='comment'>// &lt;LICENSE-MIT or http://opensource.org/licenses/MIT&gt;, at your</span>
<span class='comment'>// option. This file may not be copied, modified, or distributed</span>
<span class='comment'>// except according to those terms.</span>
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>collections</span>::<span class='ident'>HashMap</span>;
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>iter</span>;
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>result</span>;
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>sync</span>::<span class='ident'>Arc</span>;
<span class='kw'>use</span> <span class='ident'>syntax</span>::{<span class='ident'>Expr</span>, <span class='ident'>Repeater</span>, <span class='ident'>CharClass</span>, <span class='ident'>ClassRange</span>, <span class='ident'>ByteClass</span>, <span class='ident'>ByteRange</span>};
<span class='kw'>use</span> <span class='ident'>utf8_ranges</span>::{<span class='ident'>Utf8Range</span>, <span class='ident'>Utf8Sequence</span>, <span class='ident'>Utf8Sequences</span>};
<span class='kw'>use</span> <span class='ident'>prog</span>::{
<span class='ident'>Program</span>, <span class='ident'>Inst</span>, <span class='ident'>InstPtr</span>, <span class='ident'>EmptyLook</span>,
<span class='ident'>InstSave</span>, <span class='ident'>InstSplit</span>, <span class='ident'>InstEmptyLook</span>, <span class='ident'>InstChar</span>, <span class='ident'>InstRanges</span>, <span class='ident'>InstBytes</span>,
};
<span class='kw'>use</span> <span class='ident'>Error</span>;
<span class='kw'>type</span> <span class='ident'>InstHoleIdx</span> <span class='op'>=</span> <span class='ident'>InstPtr</span>;
<span class='kw'>type</span> <span class='prelude-ty'>Result</span> <span class='op'>=</span> <span class='ident'>result</span>::<span class='prelude-ty'>Result</span><span class='op'>&lt;</span><span class='ident'>Patch</span>, <span class='ident'>Error</span><span class='op'>&gt;</span>;
<span class='attribute'>#[<span class='ident'>derive</span>(<span class='ident'>Debug</span>)]</span>
<span class='kw'>struct</span> <span class='ident'>Patch</span> {
<span class='ident'>hole</span>: <span class='ident'>Hole</span>,
<span class='ident'>entry</span>: <span class='ident'>InstPtr</span>,
}
<span class='doccomment'>/// A compiler translates a regular expression AST to a sequence of</span>
<span class='doccomment'>/// instructions. The sequence of instructions represents an NFA.</span>
<span class='kw'>pub</span> <span class='kw'>struct</span> <span class='ident'>Compiler</span> {
<span class='ident'>insts</span>: <span class='ident'>Vec</span><span class='op'>&lt;</span><span class='ident'>MaybeInst</span><span class='op'>&gt;</span>,
<span class='ident'>compiled</span>: <span class='ident'>Program</span>,
<span class='ident'>capture_name_idx</span>: <span class='ident'>HashMap</span><span class='op'>&lt;</span><span class='ident'>String</span>, <span class='ident'>usize</span><span class='op'>&gt;</span>,
<span class='ident'>num_exprs</span>: <span class='ident'>usize</span>,
<span class='ident'>size_limit</span>: <span class='ident'>usize</span>,
<span class='ident'>suffix_cache</span>: <span class='ident'>SuffixCache</span>,
<span class='ident'>utf8_seqs</span>: <span class='prelude-ty'>Option</span><span class='op'>&lt;</span><span class='ident'>Utf8Sequences</span><span class='op'>&gt;</span>,
<span class='ident'>byte_classes</span>: <span class='ident'>ByteClassSet</span>,
}
<span class='kw'>impl</span> <span class='ident'>Compiler</span> {
<span class='doccomment'>/// Create a new regular expression compiler.</span>
<span class='doccomment'>///</span>
<span class='doccomment'>/// Various options can be set before calling `compile` on an expression.</span>
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>new</span>() <span class='op'>-&gt;</span> <span class='kw'>Self</span> {
<span class='ident'>Compiler</span> {
<span class='ident'>insts</span>: <span class='macro'>vec</span><span class='macro'>!</span>[],
<span class='ident'>compiled</span>: <span class='ident'>Program</span>::<span class='ident'>new</span>(),
<span class='ident'>capture_name_idx</span>: <span class='ident'>HashMap</span>::<span class='ident'>new</span>(),
<span class='ident'>num_exprs</span>: <span class='number'>0</span>,
<span class='ident'>size_limit</span>: <span class='number'>10</span> <span class='op'>*</span> (<span class='number'>1</span> <span class='op'>&lt;&lt;</span> <span class='number'>20</span>),
<span class='ident'>suffix_cache</span>: <span class='ident'>SuffixCache</span>::<span class='ident'>new</span>(<span class='number'>1000</span>),
<span class='ident'>utf8_seqs</span>: <span class='prelude-val'>Some</span>(<span class='ident'>Utf8Sequences</span>::<span class='ident'>new</span>(<span class='string'>&#39;\x00&#39;</span>, <span class='string'>&#39;\x00&#39;</span>)),
<span class='ident'>byte_classes</span>: <span class='ident'>ByteClassSet</span>::<span class='ident'>new</span>(),
}
}
<span class='doccomment'>/// The size of the resulting program is limited by size_limit. If</span>
<span class='doccomment'>/// the program approximately exceeds the given size (in bytes), then</span>
<span class='doccomment'>/// compilation will stop and return an error.</span>
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>size_limit</span>(<span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>size_limit</span>: <span class='ident'>usize</span>) <span class='op'>-&gt;</span> <span class='kw'>Self</span> {
<span class='self'>self</span>.<span class='ident'>size_limit</span> <span class='op'>=</span> <span class='ident'>size_limit</span>;
<span class='self'>self</span>
}
<span class='doccomment'>/// If bytes is true, then the program is compiled as a byte based</span>
<span class='doccomment'>/// automaton, which incorporates UTF-8 decoding into the machine. If it&#39;s</span>
<span class='doccomment'>/// false, then the automaton is Unicode scalar value based, e.g., an</span>
<span class='doccomment'>/// engine utilizing such an automaton is resposible for UTF-8 decoding.</span>
<span class='doccomment'>///</span>
<span class='doccomment'>/// The specific invariant is that when returning a byte based machine,</span>
<span class='doccomment'>/// the neither the `Char` nor `Ranges` instructions are produced.</span>
<span class='doccomment'>/// Conversely, when producing a Unicode scalar value machine, the `Bytes`</span>
<span class='doccomment'>/// instruction is never produced.</span>
<span class='doccomment'>///</span>
<span class='doccomment'>/// Note that `dfa(true)` implies `bytes(true)`.</span>
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>bytes</span>(<span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>yes</span>: <span class='ident'>bool</span>) <span class='op'>-&gt;</span> <span class='kw'>Self</span> {
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_bytes</span> <span class='op'>=</span> <span class='ident'>yes</span>;
<span class='self'>self</span>
}
<span class='doccomment'>/// When disabled, the program compiled may match arbitrary bytes.</span>
<span class='doccomment'>///</span>
<span class='doccomment'>/// When enabled (the default), all compiled programs exclusively match</span>
<span class='doccomment'>/// valid UTF-8 bytes.</span>
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>only_utf8</span>(<span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>yes</span>: <span class='ident'>bool</span>) <span class='op'>-&gt;</span> <span class='kw'>Self</span> {
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>only_utf8</span> <span class='op'>=</span> <span class='ident'>yes</span>;
<span class='self'>self</span>
}
<span class='doccomment'>/// When set, the machine returned is suitable for use in the DFA matching</span>
<span class='doccomment'>/// engine.</span>
<span class='doccomment'>///</span>
<span class='doccomment'>/// In particular, this ensures that if the regex is not anchored in the</span>
<span class='doccomment'>/// beginning, then a preceding `.*?` is included in the program. (The NFA</span>
<span class='doccomment'>/// based engines handle the preceding `.*?` explicitly, which is difficult</span>
<span class='doccomment'>/// or impossible in the DFA engine.)</span>
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>dfa</span>(<span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>yes</span>: <span class='ident'>bool</span>) <span class='op'>-&gt;</span> <span class='kw'>Self</span> {
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_dfa</span> <span class='op'>=</span> <span class='ident'>yes</span>;
<span class='self'>self</span>
}
<span class='doccomment'>/// When set, the machine returned is suitable for matching text in</span>
<span class='doccomment'>/// reverse. In particular, all concatenations are flipped.</span>
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>reverse</span>(<span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>yes</span>: <span class='ident'>bool</span>) <span class='op'>-&gt;</span> <span class='kw'>Self</span> {
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_reverse</span> <span class='op'>=</span> <span class='ident'>yes</span>;
<span class='self'>self</span>
}
<span class='doccomment'>/// Compile a regular expression given its AST.</span>
<span class='doccomment'>///</span>
<span class='doccomment'>/// The compiler is guaranteed to succeed unless the program exceeds the</span>
<span class='doccomment'>/// specified size limit. If the size limit is exceeded, then compilation</span>
<span class='doccomment'>/// stops and returns an error.</span>
<span class='kw'>pub</span> <span class='kw'>fn</span> <span class='ident'>compile</span>(
<span class='kw-2'>mut</span> <span class='self'>self</span>,
<span class='ident'>exprs</span>: <span class='kw-2'>&amp;</span>[<span class='ident'>Expr</span>],
) <span class='op'>-&gt;</span> <span class='ident'>result</span>::<span class='prelude-ty'>Result</span><span class='op'>&lt;</span><span class='ident'>Program</span>, <span class='ident'>Error</span><span class='op'>&gt;</span> {
<span class='macro'>debug_assert</span><span class='macro'>!</span>(<span class='ident'>exprs</span>.<span class='ident'>len</span>() <span class='op'>&gt;=</span> <span class='number'>1</span>);
<span class='self'>self</span>.<span class='ident'>num_exprs</span> <span class='op'>=</span> <span class='ident'>exprs</span>.<span class='ident'>len</span>();
<span class='kw'>if</span> <span class='ident'>exprs</span>.<span class='ident'>len</span>() <span class='op'>==</span> <span class='number'>1</span> {
<span class='self'>self</span>.<span class='ident'>compile_one</span>(<span class='kw-2'>&amp;</span><span class='ident'>exprs</span>[<span class='number'>0</span>])
} <span class='kw'>else</span> {
<span class='self'>self</span>.<span class='ident'>compile_many</span>(<span class='ident'>exprs</span>)
}
}
<span class='kw'>fn</span> <span class='ident'>compile_one</span>(<span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>expr</span>: <span class='kw-2'>&amp;</span><span class='ident'>Expr</span>) <span class='op'>-&gt;</span> <span class='ident'>result</span>::<span class='prelude-ty'>Result</span><span class='op'>&lt;</span><span class='ident'>Program</span>, <span class='ident'>Error</span><span class='op'>&gt;</span> {
<span class='comment'>// If we&#39;re compiling a forward DFA and we aren&#39;t anchored, then</span>
<span class='comment'>// add a `.*?` before the first capture group.</span>
<span class='comment'>// Other matching engines handle this by baking the logic into the</span>
<span class='comment'>// matching engine itself.</span>
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>dotstar_patch</span> <span class='op'>=</span> <span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>Hole</span>::<span class='prelude-val'>None</span>, <span class='ident'>entry</span>: <span class='number'>0</span> };
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_anchored_start</span> <span class='op'>=</span> <span class='ident'>expr</span>.<span class='ident'>is_anchored_start</span>();
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_anchored_end</span> <span class='op'>=</span> <span class='ident'>expr</span>.<span class='ident'>is_anchored_end</span>();
<span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>needs_dotstar</span>() {
<span class='ident'>dotstar_patch</span> <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_dotstar</span>());
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>start</span> <span class='op'>=</span> <span class='ident'>dotstar_patch</span>.<span class='ident'>entry</span>;
}
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>captures</span> <span class='op'>=</span> <span class='macro'>vec</span><span class='macro'>!</span>[<span class='prelude-val'>None</span>];
<span class='kw'>let</span> <span class='ident'>patch</span> <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_capture</span>(<span class='number'>0</span>, <span class='ident'>expr</span>));
<span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>needs_dotstar</span>() {
<span class='self'>self</span>.<span class='ident'>fill</span>(<span class='ident'>dotstar_patch</span>.<span class='ident'>hole</span>, <span class='ident'>patch</span>.<span class='ident'>entry</span>);
} <span class='kw'>else</span> {
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>start</span> <span class='op'>=</span> <span class='ident'>patch</span>.<span class='ident'>entry</span>;
}
<span class='self'>self</span>.<span class='ident'>fill_to_next</span>(<span class='ident'>patch</span>.<span class='ident'>hole</span>);
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>matches</span> <span class='op'>=</span> <span class='macro'>vec</span><span class='macro'>!</span>[<span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>()];
<span class='self'>self</span>.<span class='ident'>push_compiled</span>(<span class='ident'>Inst</span>::<span class='ident'>Match</span>(<span class='number'>0</span>));
<span class='self'>self</span>.<span class='ident'>compile_finish</span>()
}
<span class='kw'>fn</span> <span class='ident'>compile_many</span>(
<span class='kw-2'>mut</span> <span class='self'>self</span>,
<span class='ident'>exprs</span>: <span class='kw-2'>&amp;</span>[<span class='ident'>Expr</span>],
) <span class='op'>-&gt;</span> <span class='ident'>result</span>::<span class='prelude-ty'>Result</span><span class='op'>&lt;</span><span class='ident'>Program</span>, <span class='ident'>Error</span><span class='op'>&gt;</span> {
<span class='macro'>debug_assert</span><span class='macro'>!</span>(<span class='ident'>exprs</span>.<span class='ident'>len</span>() <span class='op'>&gt;</span> <span class='number'>1</span>);
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_anchored_start</span> <span class='op'>=</span>
<span class='ident'>exprs</span>.<span class='ident'>iter</span>().<span class='ident'>all</span>(<span class='op'>|</span><span class='ident'>e</span><span class='op'>|</span> <span class='ident'>e</span>.<span class='ident'>is_anchored_start</span>());
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_anchored_end</span> <span class='op'>=</span>
<span class='ident'>exprs</span>.<span class='ident'>iter</span>().<span class='ident'>all</span>(<span class='op'>|</span><span class='ident'>e</span><span class='op'>|</span> <span class='ident'>e</span>.<span class='ident'>is_anchored_end</span>());
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>dotstar_patch</span> <span class='op'>=</span> <span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>Hole</span>::<span class='prelude-val'>None</span>, <span class='ident'>entry</span>: <span class='number'>0</span> };
<span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>needs_dotstar</span>() {
<span class='ident'>dotstar_patch</span> <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_dotstar</span>());
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>start</span> <span class='op'>=</span> <span class='ident'>dotstar_patch</span>.<span class='ident'>entry</span>;
} <span class='kw'>else</span> {
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>start</span> <span class='op'>=</span> <span class='number'>0</span>; <span class='comment'>// first instruction is always split</span>
}
<span class='self'>self</span>.<span class='ident'>fill_to_next</span>(<span class='ident'>dotstar_patch</span>.<span class='ident'>hole</span>);
<span class='kw'>for</span> (<span class='ident'>i</span>, <span class='ident'>expr</span>) <span class='kw'>in</span> <span class='ident'>exprs</span>[<span class='number'>0</span>..<span class='ident'>exprs</span>.<span class='ident'>len</span>() <span class='op'>-</span> <span class='number'>1</span>].<span class='ident'>iter</span>().<span class='ident'>enumerate</span>() {
<span class='kw'>let</span> <span class='ident'>split</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>push_split_hole</span>();
<span class='kw'>let</span> <span class='ident'>Patch</span> { <span class='ident'>hole</span>, <span class='ident'>entry</span> } <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_capture</span>(<span class='number'>0</span>, <span class='ident'>expr</span>));
<span class='self'>self</span>.<span class='ident'>fill_to_next</span>(<span class='ident'>hole</span>);
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>matches</span>.<span class='ident'>push</span>(<span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>());
<span class='self'>self</span>.<span class='ident'>push_compiled</span>(<span class='ident'>Inst</span>::<span class='ident'>Match</span>(<span class='ident'>i</span>));
<span class='kw'>let</span> <span class='ident'>next</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>();
<span class='self'>self</span>.<span class='ident'>fill_split</span>(<span class='ident'>split</span>, <span class='prelude-val'>Some</span>(<span class='ident'>entry</span>), <span class='prelude-val'>Some</span>(<span class='ident'>next</span>));
}
<span class='kw'>let</span> <span class='ident'>i</span> <span class='op'>=</span> <span class='ident'>exprs</span>.<span class='ident'>len</span>() <span class='op'>-</span> <span class='number'>1</span>;
<span class='kw'>let</span> <span class='ident'>Patch</span> { <span class='ident'>hole</span>, .. } <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_capture</span>(<span class='number'>0</span>, <span class='kw-2'>&amp;</span><span class='ident'>exprs</span>[<span class='ident'>i</span>]));
<span class='self'>self</span>.<span class='ident'>fill_to_next</span>(<span class='ident'>hole</span>);
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>matches</span>.<span class='ident'>push</span>(<span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>());
<span class='self'>self</span>.<span class='ident'>push_compiled</span>(<span class='ident'>Inst</span>::<span class='ident'>Match</span>(<span class='ident'>i</span>));
<span class='self'>self</span>.<span class='ident'>compile_finish</span>()
}
<span class='kw'>fn</span> <span class='ident'>compile_finish</span>(<span class='kw-2'>mut</span> <span class='self'>self</span>) <span class='op'>-&gt;</span> <span class='ident'>result</span>::<span class='prelude-ty'>Result</span><span class='op'>&lt;</span><span class='ident'>Program</span>, <span class='ident'>Error</span><span class='op'>&gt;</span> {
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>insts</span> <span class='op'>=</span>
<span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>into_iter</span>().<span class='ident'>map</span>(<span class='op'>|</span><span class='ident'>inst</span><span class='op'>|</span> <span class='ident'>inst</span>.<span class='ident'>unwrap</span>()).<span class='ident'>collect</span>();
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>byte_classes</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>byte_classes</span>.<span class='ident'>byte_classes</span>();
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>capture_name_idx</span> <span class='op'>=</span> <span class='ident'>Arc</span>::<span class='ident'>new</span>(<span class='self'>self</span>.<span class='ident'>capture_name_idx</span>);
<span class='prelude-val'>Ok</span>(<span class='self'>self</span>.<span class='ident'>compiled</span>)
}
<span class='kw'>fn</span> <span class='ident'>c</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>expr</span>: <span class='kw-2'>&amp;</span><span class='ident'>Expr</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>use</span> <span class='ident'>prog</span>;
<span class='kw'>use</span> <span class='ident'>syntax</span>::<span class='ident'>Expr</span>::<span class='op'>*</span>;
<span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>check_size</span>());
<span class='kw'>match</span> <span class='op'>*</span><span class='ident'>expr</span> {
<span class='ident'>Empty</span> <span class='op'>=&gt;</span> <span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>Hole</span>::<span class='prelude-val'>None</span>, <span class='ident'>entry</span>: <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>() }),
<span class='ident'>Literal</span> { <span class='kw-2'>ref</span> <span class='ident'>chars</span>, <span class='ident'>casei</span> } <span class='op'>=&gt;</span> <span class='self'>self</span>.<span class='ident'>c_literal</span>(<span class='ident'>chars</span>, <span class='ident'>casei</span>),
<span class='ident'>LiteralBytes</span> { <span class='kw-2'>ref</span> <span class='ident'>bytes</span>, <span class='ident'>casei</span> } <span class='op'>=&gt;</span> <span class='self'>self</span>.<span class='ident'>c_bytes</span>(<span class='ident'>bytes</span>, <span class='ident'>casei</span>),
<span class='ident'>AnyChar</span> <span class='op'>=&gt;</span> <span class='self'>self</span>.<span class='ident'>c_class</span>(<span class='kw-2'>&amp;</span>[<span class='ident'>ClassRange</span> {
<span class='ident'>start</span>: <span class='string'>&#39;\x00&#39;</span>,
<span class='ident'>end</span>: <span class='string'>&#39;\u{10ffff}&#39;</span>,
}]),
<span class='ident'>AnyCharNoNL</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_class</span>(<span class='kw-2'>&amp;</span>[
<span class='ident'>ClassRange</span> { <span class='ident'>start</span>: <span class='string'>&#39;\x00&#39;</span>, <span class='ident'>end</span>: <span class='string'>&#39;\x09&#39;</span> },
<span class='ident'>ClassRange</span> { <span class='ident'>start</span>: <span class='string'>&#39;\x0b&#39;</span>, <span class='ident'>end</span>: <span class='string'>&#39;\u{10ffff}&#39;</span> },
])
}
<span class='ident'>AnyByte</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_class_bytes</span>(<span class='kw-2'>&amp;</span>[<span class='ident'>ByteRange</span> { <span class='ident'>start</span>: <span class='number'>0</span>, <span class='ident'>end</span>: <span class='number'>0xFF</span> }])
}
<span class='ident'>AnyByteNoNL</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_class_bytes</span>(<span class='kw-2'>&amp;</span>[
<span class='ident'>ByteRange</span> { <span class='ident'>start</span>: <span class='number'>0</span>, <span class='ident'>end</span>: <span class='number'>0x9</span> },
<span class='ident'>ByteRange</span> { <span class='ident'>start</span>: <span class='number'>0xB</span>, <span class='ident'>end</span>: <span class='number'>0xFF</span> },
])
}
<span class='ident'>Class</span>(<span class='kw-2'>ref</span> <span class='ident'>cls</span>) <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_class</span>(<span class='ident'>cls</span>)
}
<span class='ident'>ClassBytes</span>(<span class='kw-2'>ref</span> <span class='ident'>cls</span>) <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_class_bytes</span>(<span class='ident'>cls</span>)
}
<span class='ident'>StartLine</span> <span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_reverse</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>byte_classes</span>.<span class='ident'>set_range</span>(<span class='string'>b&#39;\n&#39;</span>, <span class='string'>b&#39;\n&#39;</span>);
<span class='self'>self</span>.<span class='ident'>c_empty_look</span>(<span class='ident'>prog</span>::<span class='ident'>EmptyLook</span>::<span class='ident'>EndLine</span>)
}
<span class='ident'>StartLine</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>byte_classes</span>.<span class='ident'>set_range</span>(<span class='string'>b&#39;\n&#39;</span>, <span class='string'>b&#39;\n&#39;</span>);
<span class='self'>self</span>.<span class='ident'>c_empty_look</span>(<span class='ident'>prog</span>::<span class='ident'>EmptyLook</span>::<span class='ident'>StartLine</span>)
}
<span class='ident'>EndLine</span> <span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_reverse</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>byte_classes</span>.<span class='ident'>set_range</span>(<span class='string'>b&#39;\n&#39;</span>, <span class='string'>b&#39;\n&#39;</span>);
<span class='self'>self</span>.<span class='ident'>c_empty_look</span>(<span class='ident'>prog</span>::<span class='ident'>EmptyLook</span>::<span class='ident'>StartLine</span>)
}
<span class='ident'>EndLine</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>byte_classes</span>.<span class='ident'>set_range</span>(<span class='string'>b&#39;\n&#39;</span>, <span class='string'>b&#39;\n&#39;</span>);
<span class='self'>self</span>.<span class='ident'>c_empty_look</span>(<span class='ident'>prog</span>::<span class='ident'>EmptyLook</span>::<span class='ident'>EndLine</span>)
}
<span class='ident'>StartText</span> <span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_reverse</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_empty_look</span>(<span class='ident'>prog</span>::<span class='ident'>EmptyLook</span>::<span class='ident'>EndText</span>)
}
<span class='ident'>StartText</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_empty_look</span>(<span class='ident'>prog</span>::<span class='ident'>EmptyLook</span>::<span class='ident'>StartText</span>)
}
<span class='ident'>EndText</span> <span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_reverse</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_empty_look</span>(<span class='ident'>prog</span>::<span class='ident'>EmptyLook</span>::<span class='ident'>StartText</span>)
}
<span class='ident'>EndText</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_empty_look</span>(<span class='ident'>prog</span>::<span class='ident'>EmptyLook</span>::<span class='ident'>EndText</span>)
}
<span class='ident'>WordBoundary</span> <span class='op'>=&gt;</span> <span class='self'>self</span>.<span class='ident'>c_empty_look</span>(<span class='ident'>prog</span>::<span class='ident'>EmptyLook</span>::<span class='ident'>WordBoundary</span>),
<span class='ident'>NotWordBoundary</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_empty_look</span>(<span class='ident'>prog</span>::<span class='ident'>EmptyLook</span>::<span class='ident'>NotWordBoundary</span>)
}
<span class='ident'>WordBoundaryAscii</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_empty_look</span>(<span class='ident'>prog</span>::<span class='ident'>EmptyLook</span>::<span class='ident'>WordBoundaryAscii</span>)
}
<span class='ident'>NotWordBoundaryAscii</span> <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_empty_look</span>(<span class='ident'>prog</span>::<span class='ident'>EmptyLook</span>::<span class='ident'>NotWordBoundaryAscii</span>)
}
<span class='ident'>Group</span> { <span class='kw-2'>ref</span> <span class='ident'>e</span>, <span class='ident'>i</span>: <span class='prelude-val'>None</span>, <span class='ident'>name</span>: <span class='prelude-val'>None</span> } <span class='op'>=&gt;</span> <span class='self'>self</span>.<span class='ident'>c</span>(<span class='ident'>e</span>),
<span class='ident'>Group</span> { <span class='kw-2'>ref</span> <span class='ident'>e</span>, <span class='ident'>i</span>, <span class='kw-2'>ref</span> <span class='ident'>name</span> } <span class='op'>=&gt;</span> {
<span class='comment'>// it&#39;s impossible to have a named capture without an index</span>
<span class='kw'>let</span> <span class='ident'>i</span> <span class='op'>=</span> <span class='ident'>i</span>.<span class='ident'>expect</span>(<span class='string'>&quot;capture index&quot;</span>);
<span class='kw'>if</span> <span class='ident'>i</span> <span class='op'>&gt;=</span> <span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>captures</span>.<span class='ident'>len</span>() {
<span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>captures</span>.<span class='ident'>push</span>(<span class='ident'>name</span>.<span class='ident'>clone</span>());
<span class='kw'>if</span> <span class='kw'>let</span> <span class='prelude-val'>Some</span>(<span class='kw-2'>ref</span> <span class='ident'>name</span>) <span class='op'>=</span> <span class='op'>*</span><span class='ident'>name</span> {
<span class='self'>self</span>.<span class='ident'>capture_name_idx</span>.<span class='ident'>insert</span>(<span class='ident'>name</span>.<span class='ident'>to_owned</span>(), <span class='ident'>i</span>);
}
}
<span class='self'>self</span>.<span class='ident'>c_capture</span>(<span class='number'>2</span> <span class='op'>*</span> <span class='ident'>i</span>, <span class='ident'>e</span>)
}
<span class='ident'>Concat</span>(<span class='kw-2'>ref</span> <span class='ident'>es</span>) <span class='op'>=&gt;</span> {
<span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_reverse</span> {
<span class='self'>self</span>.<span class='ident'>c_concat</span>(<span class='ident'>es</span>.<span class='ident'>iter</span>().<span class='ident'>rev</span>())
} <span class='kw'>else</span> {
<span class='self'>self</span>.<span class='ident'>c_concat</span>(<span class='ident'>es</span>)
}
}
<span class='ident'>Alternate</span>(<span class='kw-2'>ref</span> <span class='ident'>es</span>) <span class='op'>=&gt;</span> <span class='self'>self</span>.<span class='ident'>c_alternate</span>(<span class='kw-2'>&amp;</span><span class='op'>*</span><span class='op'>*</span><span class='ident'>es</span>),
<span class='ident'>Repeat</span> { <span class='kw-2'>ref</span> <span class='ident'>e</span>, <span class='ident'>r</span>, <span class='ident'>greedy</span> } <span class='op'>=&gt;</span> <span class='self'>self</span>.<span class='ident'>c_repeat</span>(<span class='ident'>e</span>, <span class='ident'>r</span>, <span class='ident'>greedy</span>),
}
}
<span class='kw'>fn</span> <span class='ident'>c_capture</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>first_slot</span>: <span class='ident'>usize</span>, <span class='ident'>expr</span>: <span class='kw-2'>&amp;</span><span class='ident'>Expr</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>num_exprs</span> <span class='op'>&gt;</span> <span class='number'>1</span> <span class='op'>||</span> <span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_dfa</span> {
<span class='comment'>// Don&#39;t ever compile Save instructions for regex sets because</span>
<span class='comment'>// they are never used. They are also never used in DFA programs</span>
<span class='comment'>// because DFAs can&#39;t handle captures.</span>
<span class='self'>self</span>.<span class='ident'>c</span>(<span class='ident'>expr</span>)
} <span class='kw'>else</span> {
<span class='kw'>let</span> <span class='ident'>entry</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>();
<span class='kw'>let</span> <span class='ident'>hole</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>push_hole</span>(<span class='ident'>InstHole</span>::<span class='ident'>Save</span> { <span class='ident'>slot</span>: <span class='ident'>first_slot</span> });
<span class='kw'>let</span> <span class='ident'>patch</span> <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c</span>(<span class='ident'>expr</span>));
<span class='self'>self</span>.<span class='ident'>fill</span>(<span class='ident'>hole</span>, <span class='ident'>patch</span>.<span class='ident'>entry</span>);
<span class='self'>self</span>.<span class='ident'>fill_to_next</span>(<span class='ident'>patch</span>.<span class='ident'>hole</span>);
<span class='kw'>let</span> <span class='ident'>hole</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>push_hole</span>(<span class='ident'>InstHole</span>::<span class='ident'>Save</span> { <span class='ident'>slot</span>: <span class='ident'>first_slot</span> <span class='op'>+</span> <span class='number'>1</span> });
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>hole</span>, <span class='ident'>entry</span>: <span class='ident'>entry</span> })
}
}
<span class='kw'>fn</span> <span class='ident'>c_dotstar</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='prelude-val'>Ok</span>(<span class='kw'>if</span> <span class='op'>!</span><span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>only_utf8</span>() {
<span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c</span>(<span class='kw-2'>&amp;</span><span class='ident'>Expr</span>::<span class='ident'>Repeat</span> {
<span class='ident'>e</span>: <span class='ident'>Box</span>::<span class='ident'>new</span>(<span class='ident'>Expr</span>::<span class='ident'>AnyByte</span>),
<span class='ident'>r</span>: <span class='ident'>Repeater</span>::<span class='ident'>ZeroOrMore</span>,
<span class='ident'>greedy</span>: <span class='boolval'>false</span>,
}))
} <span class='kw'>else</span> {
<span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c</span>(<span class='kw-2'>&amp;</span><span class='ident'>Expr</span>::<span class='ident'>Repeat</span> {
<span class='ident'>e</span>: <span class='ident'>Box</span>::<span class='ident'>new</span>(<span class='ident'>Expr</span>::<span class='ident'>AnyChar</span>),
<span class='ident'>r</span>: <span class='ident'>Repeater</span>::<span class='ident'>ZeroOrMore</span>,
<span class='ident'>greedy</span>: <span class='boolval'>false</span>,
}))
})
}
<span class='kw'>fn</span> <span class='ident'>c_literal</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>chars</span>: <span class='kw-2'>&amp;</span>[<span class='ident'>char</span>], <span class='ident'>casei</span>: <span class='ident'>bool</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='macro'>debug_assert</span><span class='macro'>!</span>(<span class='op'>!</span><span class='ident'>chars</span>.<span class='ident'>is_empty</span>());
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>chars</span>: <span class='ident'>Box</span><span class='op'>&lt;</span><span class='ident'>Iterator</span><span class='op'>&lt;</span><span class='ident'>Item</span><span class='op'>=</span><span class='kw-2'>&amp;</span><span class='ident'>char</span><span class='op'>&gt;&gt;</span> <span class='op'>=</span>
<span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_reverse</span> {
<span class='ident'>Box</span>::<span class='ident'>new</span>(<span class='ident'>chars</span>.<span class='ident'>iter</span>().<span class='ident'>rev</span>())
} <span class='kw'>else</span> {
<span class='ident'>Box</span>::<span class='ident'>new</span>(<span class='ident'>chars</span>.<span class='ident'>iter</span>())
};
<span class='kw'>let</span> <span class='ident'>first</span> <span class='op'>=</span> <span class='op'>*</span><span class='ident'>chars</span>.<span class='ident'>next</span>().<span class='ident'>expect</span>(<span class='string'>&quot;non-empty literal&quot;</span>);
<span class='kw'>let</span> <span class='ident'>Patch</span> { <span class='kw-2'>mut</span> <span class='ident'>hole</span>, <span class='ident'>entry</span> } <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_char</span>(<span class='ident'>first</span>, <span class='ident'>casei</span>));
<span class='kw'>for</span> <span class='kw-2'>&amp;</span><span class='ident'>c</span> <span class='kw'>in</span> <span class='ident'>chars</span> {
<span class='kw'>let</span> <span class='ident'>p</span> <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_char</span>(<span class='ident'>c</span>, <span class='ident'>casei</span>));
<span class='self'>self</span>.<span class='ident'>fill</span>(<span class='ident'>hole</span>, <span class='ident'>p</span>.<span class='ident'>entry</span>);
<span class='ident'>hole</span> <span class='op'>=</span> <span class='ident'>p</span>.<span class='ident'>hole</span>;
}
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>hole</span>, <span class='ident'>entry</span>: <span class='ident'>entry</span> })
}
<span class='kw'>fn</span> <span class='ident'>c_char</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>c</span>: <span class='ident'>char</span>, <span class='ident'>casei</span>: <span class='ident'>bool</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>if</span> <span class='ident'>casei</span> {
<span class='self'>self</span>.<span class='ident'>c_class</span>(<span class='kw-2'>&amp;</span><span class='ident'>CharClass</span>::<span class='ident'>new</span>(<span class='macro'>vec</span><span class='macro'>!</span>[
<span class='ident'>ClassRange</span> { <span class='ident'>start</span>: <span class='ident'>c</span>, <span class='ident'>end</span>: <span class='ident'>c</span> },
]).<span class='ident'>case_fold</span>())
} <span class='kw'>else</span> {
<span class='self'>self</span>.<span class='ident'>c_class</span>(<span class='kw-2'>&amp;</span>[<span class='ident'>ClassRange</span> { <span class='ident'>start</span>: <span class='ident'>c</span>, <span class='ident'>end</span>: <span class='ident'>c</span> }])
}
}
<span class='kw'>fn</span> <span class='ident'>c_class</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>ranges</span>: <span class='kw-2'>&amp;</span>[<span class='ident'>ClassRange</span>]) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>uses_bytes</span>() {
<span class='ident'>CompileClass</span> {
<span class='ident'>c</span>: <span class='self'>self</span>,
<span class='ident'>ranges</span>: <span class='ident'>ranges</span>,
}.<span class='ident'>compile</span>()
} <span class='kw'>else</span> {
<span class='kw'>let</span> <span class='ident'>ranges</span>: <span class='ident'>Vec</span><span class='op'>&lt;</span>(<span class='ident'>char</span>, <span class='ident'>char</span>)<span class='op'>&gt;</span> <span class='op'>=</span>
<span class='ident'>ranges</span>.<span class='ident'>iter</span>().<span class='ident'>map</span>(<span class='op'>|</span><span class='ident'>r</span><span class='op'>|</span> (<span class='ident'>r</span>.<span class='ident'>start</span>, <span class='ident'>r</span>.<span class='ident'>end</span>)).<span class='ident'>collect</span>();
<span class='kw'>let</span> <span class='ident'>hole</span> <span class='op'>=</span> <span class='kw'>if</span> <span class='ident'>ranges</span>.<span class='ident'>len</span>() <span class='op'>==</span> <span class='number'>1</span> <span class='op'>&amp;&amp;</span> <span class='ident'>ranges</span>[<span class='number'>0</span>].<span class='number'>0</span> <span class='op'>==</span> <span class='ident'>ranges</span>[<span class='number'>0</span>].<span class='number'>1</span> {
<span class='self'>self</span>.<span class='ident'>push_hole</span>(<span class='ident'>InstHole</span>::<span class='ident'>Char</span> { <span class='ident'>c</span>: <span class='ident'>ranges</span>[<span class='number'>0</span>].<span class='number'>0</span> })
} <span class='kw'>else</span> {
<span class='self'>self</span>.<span class='ident'>push_hole</span>(<span class='ident'>InstHole</span>::<span class='ident'>Ranges</span> { <span class='ident'>ranges</span>: <span class='ident'>ranges</span> })
};
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>hole</span>, <span class='ident'>entry</span>: <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>() <span class='op'>-</span> <span class='number'>1</span> })
}
}
<span class='kw'>fn</span> <span class='ident'>c_bytes</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>bytes</span>: <span class='kw-2'>&amp;</span>[<span class='ident'>u8</span>], <span class='ident'>casei</span>: <span class='ident'>bool</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='macro'>debug_assert</span><span class='macro'>!</span>(<span class='op'>!</span><span class='ident'>bytes</span>.<span class='ident'>is_empty</span>());
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>bytes</span>: <span class='ident'>Box</span><span class='op'>&lt;</span><span class='ident'>Iterator</span><span class='op'>&lt;</span><span class='ident'>Item</span><span class='op'>=</span><span class='kw-2'>&amp;</span><span class='ident'>u8</span><span class='op'>&gt;&gt;</span> <span class='op'>=</span>
<span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>compiled</span>.<span class='ident'>is_reverse</span> {
<span class='ident'>Box</span>::<span class='ident'>new</span>(<span class='ident'>bytes</span>.<span class='ident'>iter</span>().<span class='ident'>rev</span>())
} <span class='kw'>else</span> {
<span class='ident'>Box</span>::<span class='ident'>new</span>(<span class='ident'>bytes</span>.<span class='ident'>iter</span>())
};
<span class='kw'>let</span> <span class='ident'>first</span> <span class='op'>=</span> <span class='op'>*</span><span class='ident'>bytes</span>.<span class='ident'>next</span>().<span class='ident'>expect</span>(<span class='string'>&quot;non-empty literal&quot;</span>);
<span class='kw'>let</span> <span class='ident'>Patch</span> { <span class='kw-2'>mut</span> <span class='ident'>hole</span>, <span class='ident'>entry</span> } <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_byte</span>(<span class='ident'>first</span>, <span class='ident'>casei</span>));
<span class='kw'>for</span> <span class='kw-2'>&amp;</span><span class='ident'>b</span> <span class='kw'>in</span> <span class='ident'>bytes</span> {
<span class='kw'>let</span> <span class='ident'>p</span> <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_byte</span>(<span class='ident'>b</span>, <span class='ident'>casei</span>));
<span class='self'>self</span>.<span class='ident'>fill</span>(<span class='ident'>hole</span>, <span class='ident'>p</span>.<span class='ident'>entry</span>);
<span class='ident'>hole</span> <span class='op'>=</span> <span class='ident'>p</span>.<span class='ident'>hole</span>;
}
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>hole</span>, <span class='ident'>entry</span>: <span class='ident'>entry</span> })
}
<span class='kw'>fn</span> <span class='ident'>c_byte</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>b</span>: <span class='ident'>u8</span>, <span class='ident'>casei</span>: <span class='ident'>bool</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>if</span> <span class='ident'>casei</span> {
<span class='self'>self</span>.<span class='ident'>c_class_bytes</span>(<span class='kw-2'>&amp;</span><span class='ident'>ByteClass</span>::<span class='ident'>new</span>(<span class='macro'>vec</span><span class='macro'>!</span>[
<span class='ident'>ByteRange</span> { <span class='ident'>start</span>: <span class='ident'>b</span>, <span class='ident'>end</span>: <span class='ident'>b</span> },
]).<span class='ident'>case_fold</span>())
} <span class='kw'>else</span> {
<span class='self'>self</span>.<span class='ident'>c_class_bytes</span>(<span class='kw-2'>&amp;</span>[<span class='ident'>ByteRange</span> { <span class='ident'>start</span>: <span class='ident'>b</span>, <span class='ident'>end</span>: <span class='ident'>b</span> }])
}
}
<span class='kw'>fn</span> <span class='ident'>c_class_bytes</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>ranges</span>: <span class='kw-2'>&amp;</span>[<span class='ident'>ByteRange</span>]) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='macro'>debug_assert</span><span class='macro'>!</span>(<span class='op'>!</span><span class='ident'>ranges</span>.<span class='ident'>is_empty</span>());
<span class='kw'>let</span> <span class='ident'>first_split_entry</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>();
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>holes</span> <span class='op'>=</span> <span class='macro'>vec</span><span class='macro'>!</span>[];
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>prev_hole</span> <span class='op'>=</span> <span class='ident'>Hole</span>::<span class='prelude-val'>None</span>;
<span class='kw'>for</span> <span class='ident'>r</span> <span class='kw'>in</span> <span class='kw-2'>&amp;</span><span class='ident'>ranges</span>[<span class='number'>0</span>..<span class='ident'>ranges</span>.<span class='ident'>len</span>() <span class='op'>-</span> <span class='number'>1</span>] {
<span class='self'>self</span>.<span class='ident'>fill_to_next</span>(<span class='ident'>prev_hole</span>);
<span class='kw'>let</span> <span class='ident'>split</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>push_split_hole</span>();
<span class='kw'>let</span> <span class='ident'>next</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>();
<span class='self'>self</span>.<span class='ident'>byte_classes</span>.<span class='ident'>set_range</span>(<span class='ident'>r</span>.<span class='ident'>start</span>, <span class='ident'>r</span>.<span class='ident'>end</span>);
<span class='ident'>holes</span>.<span class='ident'>push</span>(<span class='self'>self</span>.<span class='ident'>push_hole</span>(<span class='ident'>InstHole</span>::<span class='ident'>Bytes</span> {
<span class='ident'>start</span>: <span class='ident'>r</span>.<span class='ident'>start</span>, <span class='ident'>end</span>: <span class='ident'>r</span>.<span class='ident'>end</span>,
}));
<span class='ident'>prev_hole</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>fill_split</span>(<span class='ident'>split</span>, <span class='prelude-val'>Some</span>(<span class='ident'>next</span>), <span class='prelude-val'>None</span>);
}
<span class='kw'>let</span> <span class='ident'>next</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>();
<span class='kw'>let</span> <span class='ident'>r</span> <span class='op'>=</span> <span class='kw-2'>&amp;</span><span class='ident'>ranges</span>[<span class='ident'>ranges</span>.<span class='ident'>len</span>() <span class='op'>-</span> <span class='number'>1</span>];
<span class='self'>self</span>.<span class='ident'>byte_classes</span>.<span class='ident'>set_range</span>(<span class='ident'>r</span>.<span class='ident'>start</span>, <span class='ident'>r</span>.<span class='ident'>end</span>);
<span class='ident'>holes</span>.<span class='ident'>push</span>(<span class='self'>self</span>.<span class='ident'>push_hole</span>(<span class='ident'>InstHole</span>::<span class='ident'>Bytes</span> {
<span class='ident'>start</span>: <span class='ident'>r</span>.<span class='ident'>start</span>, <span class='ident'>end</span>: <span class='ident'>r</span>.<span class='ident'>end</span>,
}));
<span class='self'>self</span>.<span class='ident'>fill</span>(<span class='ident'>prev_hole</span>, <span class='ident'>next</span>);
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>Hole</span>::<span class='ident'>Many</span>(<span class='ident'>holes</span>), <span class='ident'>entry</span>: <span class='ident'>first_split_entry</span> })
}
<span class='kw'>fn</span> <span class='ident'>c_empty_look</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>look</span>: <span class='ident'>EmptyLook</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>let</span> <span class='ident'>hole</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>push_hole</span>(<span class='ident'>InstHole</span>::<span class='ident'>EmptyLook</span> { <span class='ident'>look</span>: <span class='ident'>look</span> });
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>hole</span>, <span class='ident'>entry</span>: <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>() <span class='op'>-</span> <span class='number'>1</span> })
}
<span class='kw'>fn</span> <span class='ident'>c_concat</span><span class='op'>&lt;</span><span class='lifetime'>&#39;a</span>, <span class='ident'>I</span><span class='op'>&gt;</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>exprs</span>: <span class='ident'>I</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span>
<span class='kw'>where</span> <span class='ident'>I</span>: <span class='ident'>IntoIterator</span><span class='op'>&lt;</span><span class='ident'>Item</span><span class='op'>=</span><span class='kw-2'>&amp;</span><span class='lifetime'>&#39;a</span> <span class='ident'>Expr</span><span class='op'>&gt;</span> {
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>exprs</span> <span class='op'>=</span> <span class='ident'>exprs</span>.<span class='ident'>into_iter</span>();
<span class='kw'>let</span> <span class='ident'>first</span> <span class='op'>=</span> <span class='kw'>match</span> <span class='ident'>exprs</span>.<span class='ident'>next</span>() {
<span class='prelude-val'>Some</span>(<span class='ident'>expr</span>) <span class='op'>=&gt;</span> <span class='ident'>expr</span>,
<span class='prelude-val'>None</span> <span class='op'>=&gt;</span> {
<span class='kw'>return</span> <span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>Hole</span>::<span class='prelude-val'>None</span>, <span class='ident'>entry</span>: <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>() })
}
};
<span class='kw'>let</span> <span class='ident'>Patch</span> { <span class='kw-2'>mut</span> <span class='ident'>hole</span>, <span class='ident'>entry</span> } <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c</span>(<span class='ident'>first</span>));
<span class='kw'>for</span> <span class='ident'>e</span> <span class='kw'>in</span> <span class='ident'>exprs</span> {
<span class='kw'>let</span> <span class='ident'>p</span> <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c</span>(<span class='ident'>e</span>));
<span class='self'>self</span>.<span class='ident'>fill</span>(<span class='ident'>hole</span>, <span class='ident'>p</span>.<span class='ident'>entry</span>);
<span class='ident'>hole</span> <span class='op'>=</span> <span class='ident'>p</span>.<span class='ident'>hole</span>;
}
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>hole</span>, <span class='ident'>entry</span>: <span class='ident'>entry</span> })
}
<span class='kw'>fn</span> <span class='ident'>c_alternate</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>exprs</span>: <span class='kw-2'>&amp;</span>[<span class='ident'>Expr</span>]) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='macro'>debug_assert</span><span class='macro'>!</span>(
<span class='ident'>exprs</span>.<span class='ident'>len</span>() <span class='op'>&gt;=</span> <span class='number'>2</span>, <span class='string'>&quot;alternates must have at least 2 exprs&quot;</span>);
<span class='comment'>// Initial entry point is always the first split.</span>
<span class='kw'>let</span> <span class='ident'>first_split_entry</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>();
<span class='comment'>// Save up all of the holes from each alternate. They will all get</span>
<span class='comment'>// patched to point to the same location.</span>
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>holes</span> <span class='op'>=</span> <span class='macro'>vec</span><span class='macro'>!</span>[];
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>prev_hole</span> <span class='op'>=</span> <span class='ident'>Hole</span>::<span class='prelude-val'>None</span>;
<span class='kw'>for</span> <span class='ident'>e</span> <span class='kw'>in</span> <span class='kw-2'>&amp;</span><span class='ident'>exprs</span>[<span class='number'>0</span>..<span class='ident'>exprs</span>.<span class='ident'>len</span>() <span class='op'>-</span> <span class='number'>1</span>] {
<span class='self'>self</span>.<span class='ident'>fill_to_next</span>(<span class='ident'>prev_hole</span>);
<span class='kw'>let</span> <span class='ident'>split</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>push_split_hole</span>();
<span class='kw'>let</span> <span class='ident'>Patch</span> { <span class='ident'>hole</span>, <span class='ident'>entry</span> } <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c</span>(<span class='ident'>e</span>));
<span class='ident'>holes</span>.<span class='ident'>push</span>(<span class='ident'>hole</span>);
<span class='ident'>prev_hole</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>fill_split</span>(<span class='ident'>split</span>, <span class='prelude-val'>Some</span>(<span class='ident'>entry</span>), <span class='prelude-val'>None</span>);
}
<span class='kw'>let</span> <span class='ident'>Patch</span> { <span class='ident'>hole</span>, <span class='ident'>entry</span> } <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c</span>(<span class='kw-2'>&amp;</span><span class='ident'>exprs</span>[<span class='ident'>exprs</span>.<span class='ident'>len</span>() <span class='op'>-</span> <span class='number'>1</span>]));
<span class='ident'>holes</span>.<span class='ident'>push</span>(<span class='ident'>hole</span>);
<span class='self'>self</span>.<span class='ident'>fill</span>(<span class='ident'>prev_hole</span>, <span class='ident'>entry</span>);
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>Hole</span>::<span class='ident'>Many</span>(<span class='ident'>holes</span>), <span class='ident'>entry</span>: <span class='ident'>first_split_entry</span> })
}
<span class='kw'>fn</span> <span class='ident'>c_repeat</span>(
<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>,
<span class='ident'>expr</span>: <span class='kw-2'>&amp;</span><span class='ident'>Expr</span>,
<span class='ident'>kind</span>: <span class='ident'>Repeater</span>,
<span class='ident'>greedy</span>: <span class='ident'>bool</span>,
) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>match</span> <span class='ident'>kind</span> {
<span class='ident'>Repeater</span>::<span class='ident'>ZeroOrOne</span> <span class='op'>=&gt;</span> <span class='self'>self</span>.<span class='ident'>c_repeat_zero_or_one</span>(<span class='ident'>expr</span>, <span class='ident'>greedy</span>),
<span class='ident'>Repeater</span>::<span class='ident'>ZeroOrMore</span> <span class='op'>=&gt;</span> <span class='self'>self</span>.<span class='ident'>c_repeat_zero_or_more</span>(<span class='ident'>expr</span>, <span class='ident'>greedy</span>),
<span class='ident'>Repeater</span>::<span class='ident'>OneOrMore</span> <span class='op'>=&gt;</span> <span class='self'>self</span>.<span class='ident'>c_repeat_one_or_more</span>(<span class='ident'>expr</span>, <span class='ident'>greedy</span>),
<span class='ident'>Repeater</span>::<span class='ident'>Range</span> { <span class='ident'>min</span>, <span class='ident'>max</span>: <span class='prelude-val'>None</span> } <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_repeat_range_min_or_more</span>(<span class='ident'>expr</span>, <span class='ident'>greedy</span>, <span class='ident'>min</span>)
}
<span class='ident'>Repeater</span>::<span class='ident'>Range</span> { <span class='ident'>min</span>, <span class='ident'>max</span>: <span class='prelude-val'>Some</span>(<span class='ident'>max</span>) } <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>c_repeat_range</span>(<span class='ident'>expr</span>, <span class='ident'>greedy</span>, <span class='ident'>min</span>, <span class='ident'>max</span>)
}
}
}
<span class='kw'>fn</span> <span class='ident'>c_repeat_zero_or_one</span>(
<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>,
<span class='ident'>expr</span>: <span class='kw-2'>&amp;</span><span class='ident'>Expr</span>,
<span class='ident'>greedy</span>: <span class='ident'>bool</span>,
) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>let</span> <span class='ident'>split_entry</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>();
<span class='kw'>let</span> <span class='ident'>split</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>push_split_hole</span>();
<span class='kw'>let</span> <span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>hole_rep</span>, <span class='ident'>entry</span>: <span class='ident'>entry_rep</span> } <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c</span>(<span class='ident'>expr</span>));
<span class='kw'>let</span> <span class='ident'>split_hole</span> <span class='op'>=</span> <span class='kw'>if</span> <span class='ident'>greedy</span> {
<span class='self'>self</span>.<span class='ident'>fill_split</span>(<span class='ident'>split</span>, <span class='prelude-val'>Some</span>(<span class='ident'>entry_rep</span>), <span class='prelude-val'>None</span>)
} <span class='kw'>else</span> {
<span class='self'>self</span>.<span class='ident'>fill_split</span>(<span class='ident'>split</span>, <span class='prelude-val'>None</span>, <span class='prelude-val'>Some</span>(<span class='ident'>entry_rep</span>))
};
<span class='kw'>let</span> <span class='ident'>holes</span> <span class='op'>=</span> <span class='macro'>vec</span><span class='macro'>!</span>[<span class='ident'>hole_rep</span>, <span class='ident'>split_hole</span>];
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>Hole</span>::<span class='ident'>Many</span>(<span class='ident'>holes</span>), <span class='ident'>entry</span>: <span class='ident'>split_entry</span> })
}
<span class='kw'>fn</span> <span class='ident'>c_repeat_zero_or_more</span>(
<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>,
<span class='ident'>expr</span>: <span class='kw-2'>&amp;</span><span class='ident'>Expr</span>,
<span class='ident'>greedy</span>: <span class='ident'>bool</span>,
) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>let</span> <span class='ident'>split_entry</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>();
<span class='kw'>let</span> <span class='ident'>split</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>push_split_hole</span>();
<span class='kw'>let</span> <span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>hole_rep</span>, <span class='ident'>entry</span>: <span class='ident'>entry_rep</span> } <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c</span>(<span class='ident'>expr</span>));
<span class='self'>self</span>.<span class='ident'>fill</span>(<span class='ident'>hole_rep</span>, <span class='ident'>split_entry</span>);
<span class='kw'>let</span> <span class='ident'>split_hole</span> <span class='op'>=</span> <span class='kw'>if</span> <span class='ident'>greedy</span> {
<span class='self'>self</span>.<span class='ident'>fill_split</span>(<span class='ident'>split</span>, <span class='prelude-val'>Some</span>(<span class='ident'>entry_rep</span>), <span class='prelude-val'>None</span>)
} <span class='kw'>else</span> {
<span class='self'>self</span>.<span class='ident'>fill_split</span>(<span class='ident'>split</span>, <span class='prelude-val'>None</span>, <span class='prelude-val'>Some</span>(<span class='ident'>entry_rep</span>))
};
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>split_hole</span>, <span class='ident'>entry</span>: <span class='ident'>split_entry</span> })
}
<span class='kw'>fn</span> <span class='ident'>c_repeat_one_or_more</span>(
<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>,
<span class='ident'>expr</span>: <span class='kw-2'>&amp;</span><span class='ident'>Expr</span>,
<span class='ident'>greedy</span>: <span class='ident'>bool</span>,
) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>let</span> <span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>hole_rep</span>, <span class='ident'>entry</span>: <span class='ident'>entry_rep</span> } <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c</span>(<span class='ident'>expr</span>));
<span class='self'>self</span>.<span class='ident'>fill_to_next</span>(<span class='ident'>hole_rep</span>);
<span class='kw'>let</span> <span class='ident'>split</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>push_split_hole</span>();
<span class='kw'>let</span> <span class='ident'>split_hole</span> <span class='op'>=</span> <span class='kw'>if</span> <span class='ident'>greedy</span> {
<span class='self'>self</span>.<span class='ident'>fill_split</span>(<span class='ident'>split</span>, <span class='prelude-val'>Some</span>(<span class='ident'>entry_rep</span>), <span class='prelude-val'>None</span>)
} <span class='kw'>else</span> {
<span class='self'>self</span>.<span class='ident'>fill_split</span>(<span class='ident'>split</span>, <span class='prelude-val'>None</span>, <span class='prelude-val'>Some</span>(<span class='ident'>entry_rep</span>))
};
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>split_hole</span>, <span class='ident'>entry</span>: <span class='ident'>entry_rep</span> })
}
<span class='kw'>fn</span> <span class='ident'>c_repeat_range_min_or_more</span>(
<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>,
<span class='ident'>expr</span>: <span class='kw-2'>&amp;</span><span class='ident'>Expr</span>,
<span class='ident'>greedy</span>: <span class='ident'>bool</span>,
<span class='ident'>min</span>: <span class='ident'>u32</span>,
) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>let</span> <span class='ident'>min</span> <span class='op'>=</span> <span class='ident'>u32_to_usize</span>(<span class='ident'>min</span>);
<span class='kw'>let</span> <span class='ident'>patch_concat</span> <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_concat</span>(<span class='ident'>iter</span>::<span class='ident'>repeat</span>(<span class='ident'>expr</span>).<span class='ident'>take</span>(<span class='ident'>min</span>)));
<span class='kw'>let</span> <span class='ident'>patch_rep</span> <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_repeat_zero_or_more</span>(<span class='ident'>expr</span>, <span class='ident'>greedy</span>));
<span class='self'>self</span>.<span class='ident'>fill</span>(<span class='ident'>patch_concat</span>.<span class='ident'>hole</span>, <span class='ident'>patch_rep</span>.<span class='ident'>entry</span>);
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>patch_rep</span>.<span class='ident'>hole</span>, <span class='ident'>entry</span>: <span class='ident'>patch_concat</span>.<span class='ident'>entry</span> })
}
<span class='kw'>fn</span> <span class='ident'>c_repeat_range</span>(
<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>,
<span class='ident'>expr</span>: <span class='kw-2'>&amp;</span><span class='ident'>Expr</span>,
<span class='ident'>greedy</span>: <span class='ident'>bool</span>,
<span class='ident'>min</span>: <span class='ident'>u32</span>,
<span class='ident'>max</span>: <span class='ident'>u32</span>,
) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>let</span> (<span class='ident'>min</span>, <span class='ident'>max</span>) <span class='op'>=</span> (<span class='ident'>u32_to_usize</span>(<span class='ident'>min</span>), <span class='ident'>u32_to_usize</span>(<span class='ident'>max</span>));
<span class='kw'>let</span> <span class='ident'>patch_concat</span> <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_concat</span>(<span class='ident'>iter</span>::<span class='ident'>repeat</span>(<span class='ident'>expr</span>).<span class='ident'>take</span>(<span class='ident'>min</span>)));
<span class='kw'>let</span> <span class='ident'>initial_entry</span> <span class='op'>=</span> <span class='ident'>patch_concat</span>.<span class='ident'>entry</span>;
<span class='kw'>if</span> <span class='ident'>min</span> <span class='op'>==</span> <span class='ident'>max</span> {
<span class='kw'>return</span> <span class='prelude-val'>Ok</span>(<span class='ident'>patch_concat</span>);
}
<span class='comment'>// It is much simpler to compile, e.g., `a{2,5}` as:</span>
<span class='comment'>//</span>
<span class='comment'>// aaa?a?a?</span>
<span class='comment'>//</span>
<span class='comment'>// But you end up with a sequence of instructions like this:</span>
<span class='comment'>//</span>
<span class='comment'>// 0: &#39;a&#39;</span>
<span class='comment'>// 1: &#39;a&#39;,</span>
<span class='comment'>// 2: split(3, 4)</span>
<span class='comment'>// 3: &#39;a&#39;</span>
<span class='comment'>// 4: split(5, 6)</span>
<span class='comment'>// 5: &#39;a&#39;</span>
<span class='comment'>// 6: split(7, 8)</span>
<span class='comment'>// 7: &#39;a&#39;</span>
<span class='comment'>// 8: MATCH</span>
<span class='comment'>//</span>
<span class='comment'>// This is *incredibly* inefficient because the splits end</span>
<span class='comment'>// up forming a chain, which has to be resolved everything a</span>
<span class='comment'>// transition is followed.</span>
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>holes</span> <span class='op'>=</span> <span class='macro'>vec</span><span class='macro'>!</span>[];
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>prev_hole</span> <span class='op'>=</span> <span class='ident'>patch_concat</span>.<span class='ident'>hole</span>;
<span class='kw'>for</span> _ <span class='kw'>in</span> <span class='ident'>min</span>..<span class='ident'>max</span> {
<span class='self'>self</span>.<span class='ident'>fill_to_next</span>(<span class='ident'>prev_hole</span>);
<span class='kw'>let</span> <span class='ident'>split</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>push_split_hole</span>();
<span class='kw'>let</span> <span class='ident'>Patch</span> { <span class='ident'>hole</span>, <span class='ident'>entry</span> } <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c</span>(<span class='ident'>expr</span>));
<span class='ident'>prev_hole</span> <span class='op'>=</span> <span class='ident'>hole</span>;
<span class='kw'>if</span> <span class='ident'>greedy</span> {
<span class='ident'>holes</span>.<span class='ident'>push</span>(<span class='self'>self</span>.<span class='ident'>fill_split</span>(<span class='ident'>split</span>, <span class='prelude-val'>Some</span>(<span class='ident'>entry</span>), <span class='prelude-val'>None</span>));
} <span class='kw'>else</span> {
<span class='ident'>holes</span>.<span class='ident'>push</span>(<span class='self'>self</span>.<span class='ident'>fill_split</span>(<span class='ident'>split</span>, <span class='prelude-val'>None</span>, <span class='prelude-val'>Some</span>(<span class='ident'>entry</span>)));
}
}
<span class='ident'>holes</span>.<span class='ident'>push</span>(<span class='ident'>prev_hole</span>);
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>Hole</span>::<span class='ident'>Many</span>(<span class='ident'>holes</span>), <span class='ident'>entry</span>: <span class='ident'>initial_entry</span> })
}
<span class='kw'>fn</span> <span class='ident'>fill</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>hole</span>: <span class='ident'>Hole</span>, <span class='ident'>goto</span>: <span class='ident'>InstPtr</span>) {
<span class='kw'>match</span> <span class='ident'>hole</span> {
<span class='ident'>Hole</span>::<span class='prelude-val'>None</span> <span class='op'>=&gt;</span> {}
<span class='ident'>Hole</span>::<span class='ident'>One</span>(<span class='ident'>pc</span>) <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>insts</span>[<span class='ident'>pc</span>].<span class='ident'>fill</span>(<span class='ident'>goto</span>);
}
<span class='ident'>Hole</span>::<span class='ident'>Many</span>(<span class='ident'>holes</span>) <span class='op'>=&gt;</span> {
<span class='kw'>for</span> <span class='ident'>hole</span> <span class='kw'>in</span> <span class='ident'>holes</span> {
<span class='self'>self</span>.<span class='ident'>fill</span>(<span class='ident'>hole</span>, <span class='ident'>goto</span>);
}
}
}
}
<span class='kw'>fn</span> <span class='ident'>fill_to_next</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>hole</span>: <span class='ident'>Hole</span>) {
<span class='kw'>let</span> <span class='ident'>next</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>();
<span class='self'>self</span>.<span class='ident'>fill</span>(<span class='ident'>hole</span>, <span class='ident'>next</span>);
}
<span class='kw'>fn</span> <span class='ident'>fill_split</span>(
<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>,
<span class='ident'>hole</span>: <span class='ident'>Hole</span>,
<span class='ident'>goto1</span>: <span class='prelude-ty'>Option</span><span class='op'>&lt;</span><span class='ident'>InstPtr</span><span class='op'>&gt;</span>,
<span class='ident'>goto2</span>: <span class='prelude-ty'>Option</span><span class='op'>&lt;</span><span class='ident'>InstPtr</span><span class='op'>&gt;</span>,
) <span class='op'>-&gt;</span> <span class='ident'>Hole</span> {
<span class='kw'>match</span> <span class='ident'>hole</span> {
<span class='ident'>Hole</span>::<span class='prelude-val'>None</span> <span class='op'>=&gt;</span> <span class='ident'>Hole</span>::<span class='prelude-val'>None</span>,
<span class='ident'>Hole</span>::<span class='ident'>One</span>(<span class='ident'>pc</span>) <span class='op'>=&gt;</span> {
<span class='kw'>match</span> (<span class='ident'>goto1</span>, <span class='ident'>goto2</span>) {
(<span class='prelude-val'>Some</span>(<span class='ident'>goto1</span>), <span class='prelude-val'>Some</span>(<span class='ident'>goto2</span>)) <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>insts</span>[<span class='ident'>pc</span>].<span class='ident'>fill_split</span>(<span class='ident'>goto1</span>, <span class='ident'>goto2</span>);
<span class='ident'>Hole</span>::<span class='prelude-val'>None</span>
}
(<span class='prelude-val'>Some</span>(<span class='ident'>goto1</span>), <span class='prelude-val'>None</span>) <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>insts</span>[<span class='ident'>pc</span>].<span class='ident'>half_fill_split_goto1</span>(<span class='ident'>goto1</span>);
<span class='ident'>Hole</span>::<span class='ident'>One</span>(<span class='ident'>pc</span>)
}
(<span class='prelude-val'>None</span>, <span class='prelude-val'>Some</span>(<span class='ident'>goto2</span>)) <span class='op'>=&gt;</span> {
<span class='self'>self</span>.<span class='ident'>insts</span>[<span class='ident'>pc</span>].<span class='ident'>half_fill_split_goto2</span>(<span class='ident'>goto2</span>);
<span class='ident'>Hole</span>::<span class='ident'>One</span>(<span class='ident'>pc</span>)
}
(<span class='prelude-val'>None</span>, <span class='prelude-val'>None</span>) <span class='op'>=&gt;</span> <span class='macro'>unreachable</span><span class='macro'>!</span>(<span class='string'>&quot;at least one of the split \
holes must be filled&quot;</span>),
}
}
<span class='ident'>Hole</span>::<span class='ident'>Many</span>(<span class='ident'>holes</span>) <span class='op'>=&gt;</span> {
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>new_holes</span> <span class='op'>=</span> <span class='macro'>vec</span><span class='macro'>!</span>[];
<span class='kw'>for</span> <span class='ident'>hole</span> <span class='kw'>in</span> <span class='ident'>holes</span> {
<span class='ident'>new_holes</span>.<span class='ident'>push</span>(<span class='self'>self</span>.<span class='ident'>fill_split</span>(<span class='ident'>hole</span>, <span class='ident'>goto1</span>, <span class='ident'>goto2</span>));
}
<span class='kw'>if</span> <span class='ident'>new_holes</span>.<span class='ident'>is_empty</span>() {
<span class='ident'>Hole</span>::<span class='prelude-val'>None</span>
} <span class='kw'>else</span> <span class='kw'>if</span> <span class='ident'>new_holes</span>.<span class='ident'>len</span>() <span class='op'>==</span> <span class='number'>1</span> {
<span class='ident'>new_holes</span>.<span class='ident'>pop</span>().<span class='ident'>unwrap</span>()
} <span class='kw'>else</span> {
<span class='ident'>Hole</span>::<span class='ident'>Many</span>(<span class='ident'>new_holes</span>)
}
}
}
}
<span class='kw'>fn</span> <span class='ident'>push_compiled</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>inst</span>: <span class='ident'>Inst</span>) {
<span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>push</span>(<span class='ident'>MaybeInst</span>::<span class='ident'>Compiled</span>(<span class='ident'>inst</span>));
}
<span class='kw'>fn</span> <span class='ident'>push_hole</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>inst</span>: <span class='ident'>InstHole</span>) <span class='op'>-&gt;</span> <span class='ident'>Hole</span> {
<span class='kw'>let</span> <span class='ident'>hole</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>();
<span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>push</span>(<span class='ident'>MaybeInst</span>::<span class='ident'>Uncompiled</span>(<span class='ident'>inst</span>));
<span class='ident'>Hole</span>::<span class='ident'>One</span>(<span class='ident'>hole</span>)
}
<span class='kw'>fn</span> <span class='ident'>push_split_hole</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>) <span class='op'>-&gt;</span> <span class='ident'>Hole</span> {
<span class='kw'>let</span> <span class='ident'>hole</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>();
<span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>push</span>(<span class='ident'>MaybeInst</span>::<span class='ident'>Split</span>);
<span class='ident'>Hole</span>::<span class='ident'>One</span>(<span class='ident'>hole</span>)
}
<span class='kw'>fn</span> <span class='ident'>check_size</span>(<span class='kw-2'>&amp;</span><span class='self'>self</span>) <span class='op'>-&gt;</span> <span class='ident'>result</span>::<span class='prelude-ty'>Result</span><span class='op'>&lt;</span>(), <span class='ident'>Error</span><span class='op'>&gt;</span> {
<span class='kw'>use</span> <span class='ident'>std</span>::<span class='ident'>mem</span>::<span class='ident'>size_of</span>;
<span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>() <span class='op'>*</span> <span class='ident'>size_of</span>::<span class='op'>&lt;</span><span class='ident'>Inst</span><span class='op'>&gt;</span>() <span class='op'>&gt;</span> <span class='self'>self</span>.<span class='ident'>size_limit</span> {
<span class='prelude-val'>Err</span>(<span class='ident'>Error</span>::<span class='ident'>CompiledTooBig</span>(<span class='self'>self</span>.<span class='ident'>size_limit</span>))
} <span class='kw'>else</span> {
<span class='prelude-val'>Ok</span>(())
}
}
}
<span class='attribute'>#[<span class='ident'>derive</span>(<span class='ident'>Debug</span>)]</span>
<span class='kw'>enum</span> <span class='ident'>Hole</span> {
<span class='prelude-val'>None</span>,
<span class='ident'>One</span>(<span class='ident'>InstPtr</span>),
<span class='ident'>Many</span>(<span class='ident'>Vec</span><span class='op'>&lt;</span><span class='ident'>Hole</span><span class='op'>&gt;</span>),
}
<span class='attribute'>#[<span class='ident'>derive</span>(<span class='ident'>Clone</span>, <span class='ident'>Debug</span>)]</span>
<span class='kw'>enum</span> <span class='ident'>MaybeInst</span> {
<span class='ident'>Compiled</span>(<span class='ident'>Inst</span>),
<span class='ident'>Uncompiled</span>(<span class='ident'>InstHole</span>),
<span class='ident'>Split</span>,
<span class='ident'>Split1</span>(<span class='ident'>InstPtr</span>),
<span class='ident'>Split2</span>(<span class='ident'>InstPtr</span>),
}
<span class='kw'>impl</span> <span class='ident'>MaybeInst</span> {
<span class='kw'>fn</span> <span class='ident'>fill</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>goto</span>: <span class='ident'>InstPtr</span>) {
<span class='kw'>let</span> <span class='ident'>filled</span> <span class='op'>=</span> <span class='kw'>match</span> <span class='op'>*</span><span class='self'>self</span> {
<span class='ident'>MaybeInst</span>::<span class='ident'>Uncompiled</span>(<span class='kw-2'>ref</span> <span class='ident'>inst</span>) <span class='op'>=&gt;</span> <span class='ident'>inst</span>.<span class='ident'>fill</span>(<span class='ident'>goto</span>),
<span class='ident'>MaybeInst</span>::<span class='ident'>Split1</span>(<span class='ident'>goto1</span>) <span class='op'>=&gt;</span> {
<span class='ident'>Inst</span>::<span class='ident'>Split</span>(<span class='ident'>InstSplit</span> { <span class='ident'>goto1</span>: <span class='ident'>goto1</span>, <span class='ident'>goto2</span>: <span class='ident'>goto</span> })
}
<span class='ident'>MaybeInst</span>::<span class='ident'>Split2</span>(<span class='ident'>goto2</span>) <span class='op'>=&gt;</span> {
<span class='ident'>Inst</span>::<span class='ident'>Split</span>(<span class='ident'>InstSplit</span> { <span class='ident'>goto1</span>: <span class='ident'>goto</span>, <span class='ident'>goto2</span>: <span class='ident'>goto2</span> })
}
_ <span class='op'>=&gt;</span> <span class='macro'>unreachable</span><span class='macro'>!</span>(<span class='string'>&quot;not all instructions were compiled! \
found uncompiled instruction: {:?}&quot;</span>, <span class='self'>self</span>),
};
<span class='op'>*</span><span class='self'>self</span> <span class='op'>=</span> <span class='ident'>MaybeInst</span>::<span class='ident'>Compiled</span>(<span class='ident'>filled</span>);
}
<span class='kw'>fn</span> <span class='ident'>fill_split</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>goto1</span>: <span class='ident'>InstPtr</span>, <span class='ident'>goto2</span>: <span class='ident'>InstPtr</span>) {
<span class='kw'>let</span> <span class='ident'>filled</span> <span class='op'>=</span> <span class='kw'>match</span> <span class='op'>*</span><span class='self'>self</span> {
<span class='ident'>MaybeInst</span>::<span class='ident'>Split</span> <span class='op'>=&gt;</span> {
<span class='ident'>Inst</span>::<span class='ident'>Split</span>(<span class='ident'>InstSplit</span> { <span class='ident'>goto1</span>: <span class='ident'>goto1</span>, <span class='ident'>goto2</span>: <span class='ident'>goto2</span> })
}
_ <span class='op'>=&gt;</span> <span class='macro'>unreachable</span><span class='macro'>!</span>(<span class='string'>&quot;must be called on Split instruction, \
instead it was called on: {:?}&quot;</span>, <span class='self'>self</span>),
};
<span class='op'>*</span><span class='self'>self</span> <span class='op'>=</span> <span class='ident'>MaybeInst</span>::<span class='ident'>Compiled</span>(<span class='ident'>filled</span>);
}
<span class='kw'>fn</span> <span class='ident'>half_fill_split_goto1</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>goto1</span>: <span class='ident'>InstPtr</span>) {
<span class='kw'>let</span> <span class='ident'>half_filled</span> <span class='op'>=</span> <span class='kw'>match</span> <span class='op'>*</span><span class='self'>self</span> {
<span class='ident'>MaybeInst</span>::<span class='ident'>Split</span> <span class='op'>=&gt;</span> <span class='ident'>goto1</span>,
_ <span class='op'>=&gt;</span> <span class='macro'>unreachable</span><span class='macro'>!</span>(<span class='string'>&quot;must be called on Split instruction, \
instead it was called on: {:?}&quot;</span>, <span class='self'>self</span>),
};
<span class='op'>*</span><span class='self'>self</span> <span class='op'>=</span> <span class='ident'>MaybeInst</span>::<span class='ident'>Split1</span>(<span class='ident'>half_filled</span>);
}
<span class='kw'>fn</span> <span class='ident'>half_fill_split_goto2</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>goto2</span>: <span class='ident'>InstPtr</span>) {
<span class='kw'>let</span> <span class='ident'>half_filled</span> <span class='op'>=</span> <span class='kw'>match</span> <span class='op'>*</span><span class='self'>self</span> {
<span class='ident'>MaybeInst</span>::<span class='ident'>Split</span> <span class='op'>=&gt;</span> <span class='ident'>goto2</span>,
_ <span class='op'>=&gt;</span> <span class='macro'>unreachable</span><span class='macro'>!</span>(<span class='string'>&quot;must be called on Split instruction, \
instead it was called on: {:?}&quot;</span>, <span class='self'>self</span>),
};
<span class='op'>*</span><span class='self'>self</span> <span class='op'>=</span> <span class='ident'>MaybeInst</span>::<span class='ident'>Split2</span>(<span class='ident'>half_filled</span>);
}
<span class='kw'>fn</span> <span class='ident'>unwrap</span>(<span class='self'>self</span>) <span class='op'>-&gt;</span> <span class='ident'>Inst</span> {
<span class='kw'>match</span> <span class='self'>self</span> {
<span class='ident'>MaybeInst</span>::<span class='ident'>Compiled</span>(<span class='ident'>inst</span>) <span class='op'>=&gt;</span> <span class='ident'>inst</span>,
_ <span class='op'>=&gt;</span> <span class='macro'>unreachable</span><span class='macro'>!</span>(<span class='string'>&quot;must be called on a compiled instruction, \
instead it was called on: {:?}&quot;</span>, <span class='self'>self</span>),
}
}
}
<span class='attribute'>#[<span class='ident'>derive</span>(<span class='ident'>Clone</span>, <span class='ident'>Debug</span>)]</span>
<span class='kw'>enum</span> <span class='ident'>InstHole</span> {
<span class='ident'>Save</span> { <span class='ident'>slot</span>: <span class='ident'>usize</span> },
<span class='ident'>EmptyLook</span> { <span class='ident'>look</span>: <span class='ident'>EmptyLook</span> },
<span class='ident'>Char</span> { <span class='ident'>c</span>: <span class='ident'>char</span> },
<span class='ident'>Ranges</span> { <span class='ident'>ranges</span>: <span class='ident'>Vec</span><span class='op'>&lt;</span>(<span class='ident'>char</span>, <span class='ident'>char</span>)<span class='op'>&gt;</span> },
<span class='ident'>Bytes</span> { <span class='ident'>start</span>: <span class='ident'>u8</span>, <span class='ident'>end</span>: <span class='ident'>u8</span> },
}
<span class='kw'>impl</span> <span class='ident'>InstHole</span> {
<span class='kw'>fn</span> <span class='ident'>fill</span>(<span class='kw-2'>&amp;</span><span class='self'>self</span>, <span class='ident'>goto</span>: <span class='ident'>InstPtr</span>) <span class='op'>-&gt;</span> <span class='ident'>Inst</span> {
<span class='kw'>match</span> <span class='op'>*</span><span class='self'>self</span> {
<span class='ident'>InstHole</span>::<span class='ident'>Save</span> { <span class='ident'>slot</span> } <span class='op'>=&gt;</span> <span class='ident'>Inst</span>::<span class='ident'>Save</span>(<span class='ident'>InstSave</span> {
<span class='ident'>goto</span>: <span class='ident'>goto</span>,
<span class='ident'>slot</span>: <span class='ident'>slot</span>,
}),
<span class='ident'>InstHole</span>::<span class='ident'>EmptyLook</span> { <span class='ident'>look</span> } <span class='op'>=&gt;</span> <span class='ident'>Inst</span>::<span class='ident'>EmptyLook</span>(<span class='ident'>InstEmptyLook</span> {
<span class='ident'>goto</span>: <span class='ident'>goto</span>,
<span class='ident'>look</span>: <span class='ident'>look</span>,
}),
<span class='ident'>InstHole</span>::<span class='ident'>Char</span> { <span class='ident'>c</span> } <span class='op'>=&gt;</span> <span class='ident'>Inst</span>::<span class='ident'>Char</span>(<span class='ident'>InstChar</span> {
<span class='ident'>goto</span>: <span class='ident'>goto</span>,
<span class='ident'>c</span>: <span class='ident'>c</span>,
}),
<span class='ident'>InstHole</span>::<span class='ident'>Ranges</span> { <span class='kw-2'>ref</span> <span class='ident'>ranges</span> } <span class='op'>=&gt;</span> <span class='ident'>Inst</span>::<span class='ident'>Ranges</span>(<span class='ident'>InstRanges</span> {
<span class='ident'>goto</span>: <span class='ident'>goto</span>,
<span class='ident'>ranges</span>: <span class='ident'>ranges</span>.<span class='ident'>clone</span>(),
}),
<span class='ident'>InstHole</span>::<span class='ident'>Bytes</span> { <span class='ident'>start</span>, <span class='ident'>end</span> } <span class='op'>=&gt;</span> <span class='ident'>Inst</span>::<span class='ident'>Bytes</span>(<span class='ident'>InstBytes</span> {
<span class='ident'>goto</span>: <span class='ident'>goto</span>,
<span class='ident'>start</span>: <span class='ident'>start</span>,
<span class='ident'>end</span>: <span class='ident'>end</span>,
}),
}
}
}
<span class='kw'>struct</span> <span class='ident'>CompileClass</span><span class='op'>&lt;</span><span class='lifetime'>&#39;a</span>, <span class='lifetime'>&#39;b</span><span class='op'>&gt;</span> {
<span class='ident'>c</span>: <span class='kw-2'>&amp;</span><span class='lifetime'>&#39;a</span> <span class='kw-2'>mut</span> <span class='ident'>Compiler</span>,
<span class='ident'>ranges</span>: <span class='kw-2'>&amp;</span><span class='lifetime'>&#39;b</span> [<span class='ident'>ClassRange</span>],
}
<span class='kw'>impl</span><span class='op'>&lt;</span><span class='lifetime'>&#39;a</span>, <span class='lifetime'>&#39;b</span><span class='op'>&gt;</span> <span class='ident'>CompileClass</span><span class='op'>&lt;</span><span class='lifetime'>&#39;a</span>, <span class='lifetime'>&#39;b</span><span class='op'>&gt;</span> {
<span class='kw'>fn</span> <span class='ident'>compile</span>(<span class='kw-2'>mut</span> <span class='self'>self</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>holes</span> <span class='op'>=</span> <span class='macro'>vec</span><span class='macro'>!</span>[];
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>initial_entry</span> <span class='op'>=</span> <span class='prelude-val'>None</span>;
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>last_split</span> <span class='op'>=</span> <span class='ident'>Hole</span>::<span class='prelude-val'>None</span>;
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>utf8_seqs</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>utf8_seqs</span>.<span class='ident'>take</span>().<span class='ident'>unwrap</span>();
<span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>suffix_cache</span>.<span class='ident'>clear</span>();
<span class='kw'>for</span> (<span class='ident'>i</span>, <span class='kw-2'>ref</span> <span class='ident'>range</span>) <span class='kw'>in</span> <span class='self'>self</span>.<span class='ident'>ranges</span>.<span class='ident'>iter</span>().<span class='ident'>enumerate</span>() {
<span class='kw'>let</span> <span class='ident'>is_last_range</span> <span class='op'>=</span> <span class='ident'>i</span> <span class='op'>+</span> <span class='number'>1</span> <span class='op'>==</span> <span class='self'>self</span>.<span class='ident'>ranges</span>.<span class='ident'>len</span>();
<span class='ident'>utf8_seqs</span>.<span class='ident'>reset</span>(<span class='ident'>range</span>.<span class='ident'>start</span>, <span class='ident'>range</span>.<span class='ident'>end</span>);
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>it</span> <span class='op'>=</span> (<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='ident'>utf8_seqs</span>).<span class='ident'>peekable</span>();
<span class='kw'>loop</span> {
<span class='kw'>let</span> <span class='ident'>utf8_seq</span> <span class='op'>=</span> <span class='kw'>match</span> <span class='ident'>it</span>.<span class='ident'>next</span>() {
<span class='prelude-val'>None</span> <span class='op'>=&gt;</span> <span class='kw'>break</span>,
<span class='prelude-val'>Some</span>(<span class='ident'>utf8_seq</span>) <span class='op'>=&gt;</span> <span class='ident'>utf8_seq</span>,
};
<span class='kw'>if</span> <span class='ident'>is_last_range</span> <span class='op'>&amp;&amp;</span> <span class='ident'>it</span>.<span class='ident'>peek</span>().<span class='ident'>is_none</span>() {
<span class='kw'>let</span> <span class='ident'>Patch</span> { <span class='ident'>hole</span>, <span class='ident'>entry</span> } <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_utf8_seq</span>(<span class='kw-2'>&amp;</span><span class='ident'>utf8_seq</span>));
<span class='ident'>holes</span>.<span class='ident'>push</span>(<span class='ident'>hole</span>);
<span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>fill</span>(<span class='ident'>last_split</span>, <span class='ident'>entry</span>);
<span class='ident'>last_split</span> <span class='op'>=</span> <span class='ident'>Hole</span>::<span class='prelude-val'>None</span>;
<span class='kw'>if</span> <span class='ident'>initial_entry</span>.<span class='ident'>is_none</span>() {
<span class='ident'>initial_entry</span> <span class='op'>=</span> <span class='prelude-val'>Some</span>(<span class='ident'>entry</span>);
}
} <span class='kw'>else</span> {
<span class='kw'>if</span> <span class='ident'>initial_entry</span>.<span class='ident'>is_none</span>() {
<span class='ident'>initial_entry</span> <span class='op'>=</span> <span class='prelude-val'>Some</span>(<span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>());
}
<span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>fill_to_next</span>(<span class='ident'>last_split</span>);
<span class='ident'>last_split</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>push_split_hole</span>();
<span class='kw'>let</span> <span class='ident'>Patch</span> { <span class='ident'>hole</span>, <span class='ident'>entry</span> } <span class='op'>=</span> <span class='macro'>try</span><span class='macro'>!</span>(<span class='self'>self</span>.<span class='ident'>c_utf8_seq</span>(<span class='kw-2'>&amp;</span><span class='ident'>utf8_seq</span>));
<span class='ident'>holes</span>.<span class='ident'>push</span>(<span class='ident'>hole</span>);
<span class='ident'>last_split</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>fill_split</span>(<span class='ident'>last_split</span>, <span class='prelude-val'>Some</span>(<span class='ident'>entry</span>), <span class='prelude-val'>None</span>);
}
}
}
<span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>utf8_seqs</span> <span class='op'>=</span> <span class='prelude-val'>Some</span>(<span class='ident'>utf8_seqs</span>);
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> {
<span class='ident'>hole</span>: <span class='ident'>Hole</span>::<span class='ident'>Many</span>(<span class='ident'>holes</span>),
<span class='ident'>entry</span>: <span class='ident'>initial_entry</span>.<span class='ident'>unwrap</span>(),
})
}
<span class='kw'>fn</span> <span class='ident'>c_utf8_seq</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>seq</span>: <span class='kw-2'>&amp;</span><span class='ident'>Utf8Sequence</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span> {
<span class='kw'>if</span> <span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>compiled</span>.<span class='ident'>is_reverse</span> {
<span class='self'>self</span>.<span class='ident'>c_utf8_seq_</span>(<span class='ident'>seq</span>)
} <span class='kw'>else</span> {
<span class='self'>self</span>.<span class='ident'>c_utf8_seq_</span>(<span class='ident'>seq</span>.<span class='ident'>into_iter</span>().<span class='ident'>rev</span>())
}
}
<span class='kw'>fn</span> <span class='ident'>c_utf8_seq_</span><span class='op'>&lt;</span><span class='lifetime'>&#39;r</span>, <span class='ident'>I</span><span class='op'>&gt;</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>seq</span>: <span class='ident'>I</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Result</span>
<span class='kw'>where</span> <span class='ident'>I</span>: <span class='ident'>IntoIterator</span><span class='op'>&lt;</span><span class='ident'>Item</span><span class='op'>=</span><span class='kw-2'>&amp;</span><span class='lifetime'>&#39;r</span> <span class='ident'>Utf8Range</span><span class='op'>&gt;</span> {
<span class='comment'>// The initial instruction for each UTF-8 sequence should be the same.</span>
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>from_inst</span> <span class='op'>=</span> ::<span class='ident'>std</span>::<span class='ident'>usize</span>::<span class='ident'>MAX</span>;
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>last_hole</span> <span class='op'>=</span> <span class='ident'>Hole</span>::<span class='prelude-val'>None</span>;
<span class='kw'>for</span> <span class='ident'>byte_range</span> <span class='kw'>in</span> <span class='ident'>seq</span> {
<span class='kw'>let</span> <span class='ident'>key</span> <span class='op'>=</span> <span class='ident'>SuffixCacheKey</span> {
<span class='ident'>from_inst</span>: <span class='ident'>from_inst</span>,
<span class='ident'>start</span>: <span class='ident'>byte_range</span>.<span class='ident'>start</span>,
<span class='ident'>end</span>: <span class='ident'>byte_range</span>.<span class='ident'>end</span>,
};
{
<span class='kw'>let</span> <span class='ident'>pc</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>();
<span class='kw'>if</span> <span class='kw'>let</span> <span class='prelude-val'>Some</span>(<span class='ident'>cached_pc</span>) <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>suffix_cache</span>.<span class='ident'>get</span>(<span class='ident'>key</span>, <span class='ident'>pc</span>) {
<span class='ident'>from_inst</span> <span class='op'>=</span> <span class='ident'>cached_pc</span>;
<span class='kw'>continue</span>;
}
}
<span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>byte_classes</span>.<span class='ident'>set_range</span>(<span class='ident'>byte_range</span>.<span class='ident'>start</span>, <span class='ident'>byte_range</span>.<span class='ident'>end</span>);
<span class='kw'>if</span> <span class='ident'>from_inst</span> <span class='op'>==</span> ::<span class='ident'>std</span>::<span class='ident'>usize</span>::<span class='ident'>MAX</span> {
<span class='ident'>last_hole</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>push_hole</span>(<span class='ident'>InstHole</span>::<span class='ident'>Bytes</span> {
<span class='ident'>start</span>: <span class='ident'>byte_range</span>.<span class='ident'>start</span>,
<span class='ident'>end</span>: <span class='ident'>byte_range</span>.<span class='ident'>end</span>,
});
} <span class='kw'>else</span> {
<span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>push_compiled</span>(<span class='ident'>Inst</span>::<span class='ident'>Bytes</span>(<span class='ident'>InstBytes</span> {
<span class='ident'>goto</span>: <span class='ident'>from_inst</span>,
<span class='ident'>start</span>: <span class='ident'>byte_range</span>.<span class='ident'>start</span>,
<span class='ident'>end</span>: <span class='ident'>byte_range</span>.<span class='ident'>end</span>,
}));
}
<span class='ident'>from_inst</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>c</span>.<span class='ident'>insts</span>.<span class='ident'>len</span>().<span class='ident'>checked_sub</span>(<span class='number'>1</span>).<span class='ident'>unwrap</span>();
<span class='macro'>debug_assert</span><span class='macro'>!</span>(<span class='ident'>from_inst</span> <span class='op'>&lt;</span> ::<span class='ident'>std</span>::<span class='ident'>usize</span>::<span class='ident'>MAX</span>);
}
<span class='macro'>debug_assert</span><span class='macro'>!</span>(<span class='ident'>from_inst</span> <span class='op'>&lt;</span> ::<span class='ident'>std</span>::<span class='ident'>usize</span>::<span class='ident'>MAX</span>);
<span class='prelude-val'>Ok</span>(<span class='ident'>Patch</span> { <span class='ident'>hole</span>: <span class='ident'>last_hole</span>, <span class='ident'>entry</span>: <span class='ident'>from_inst</span> })
}
}
<span class='doccomment'>/// SuffixCache is a simple bounded hash map for caching suffix entries in</span>
<span class='doccomment'>/// UTF-8 automata. For example, consider the Unicode range \u{0}-\u{FFFF}.</span>
<span class='doccomment'>/// The set of byte ranges looks like this:</span>
<span class='doccomment'>///</span>
<span class='doccomment'>/// [0-7F]</span>
<span class='doccomment'>/// [C2-DF][80-BF]</span>
<span class='doccomment'>/// [E0][A0-BF][80-BF]</span>
<span class='doccomment'>/// [E1-EC][80-BF][80-BF]</span>
<span class='doccomment'>/// [ED][80-9F][80-BF]</span>
<span class='doccomment'>/// [EE-EF][80-BF][80-BF]</span>
<span class='doccomment'>///</span>
<span class='doccomment'>/// Each line above translates to one alternate in the compiled regex program.</span>
<span class='doccomment'>/// However, all but one of the alternates end in the same suffix, which is</span>
<span class='doccomment'>/// a waste of an instruction. The suffix cache facilitates reusing them across</span>
<span class='doccomment'>/// alternates.</span>
<span class='doccomment'>///</span>
<span class='doccomment'>/// Note that a HashMap could be trivially used for this, but we don&#39;t need its</span>
<span class='doccomment'>/// overhead. Some small bounded space (LRU style) is more than enough.</span>
<span class='kw'>struct</span> <span class='ident'>SuffixCache</span> {
<span class='ident'>table</span>: <span class='ident'>Vec</span><span class='op'>&lt;</span><span class='ident'>SuffixCacheEntry</span><span class='op'>&gt;</span>,
<span class='comment'>// Every time the cache is cleared, we increment the version number instead</span>
<span class='comment'>// of actually zeroing memory. Since we store a copy of the current version</span>
<span class='comment'>// in every element, all we need to do is make sure to invalidate any stale</span>
<span class='comment'>// entries upon access. This saves quite a bit of time!</span>
<span class='ident'>version</span>: <span class='ident'>usize</span>,
}
<span class='attribute'>#[<span class='ident'>derive</span>(<span class='ident'>Clone</span>, <span class='ident'>Copy</span>, <span class='ident'>Debug</span>, <span class='ident'>Default</span>, <span class='ident'>Eq</span>, <span class='ident'>Hash</span>, <span class='ident'>PartialEq</span>)]</span>
<span class='kw'>struct</span> <span class='ident'>SuffixCacheEntry</span> {
<span class='ident'>key</span>: <span class='ident'>SuffixCacheKey</span>,
<span class='ident'>pc</span>: <span class='ident'>InstPtr</span>,
<span class='ident'>version</span>: <span class='ident'>usize</span>,
}
<span class='attribute'>#[<span class='ident'>derive</span>(<span class='ident'>Clone</span>, <span class='ident'>Copy</span>, <span class='ident'>Debug</span>, <span class='ident'>Default</span>, <span class='ident'>Eq</span>, <span class='ident'>Hash</span>, <span class='ident'>PartialEq</span>)]</span>
<span class='kw'>struct</span> <span class='ident'>SuffixCacheKey</span> {
<span class='ident'>from_inst</span>: <span class='ident'>InstPtr</span>,
<span class='ident'>start</span>: <span class='ident'>u8</span>,
<span class='ident'>end</span>: <span class='ident'>u8</span>,
}
<span class='kw'>impl</span> <span class='ident'>SuffixCache</span> {
<span class='kw'>fn</span> <span class='ident'>new</span>(<span class='ident'>size</span>: <span class='ident'>usize</span>) <span class='op'>-&gt;</span> <span class='kw'>Self</span> {
<span class='ident'>SuffixCache</span> {
<span class='ident'>table</span>: <span class='macro'>vec</span><span class='macro'>!</span>[<span class='ident'>SuffixCacheEntry</span>::<span class='ident'>default</span>(); <span class='ident'>size</span>],
<span class='ident'>version</span>: <span class='number'>0</span>,
}
}
<span class='kw'>fn</span> <span class='ident'>get</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>key</span>: <span class='ident'>SuffixCacheKey</span>, <span class='ident'>pc</span>: <span class='ident'>InstPtr</span>) <span class='op'>-&gt;</span> <span class='prelude-ty'>Option</span><span class='op'>&lt;</span><span class='ident'>InstPtr</span><span class='op'>&gt;</span> {
<span class='kw'>let</span> <span class='ident'>h</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>hash</span>(<span class='kw-2'>&amp;</span><span class='ident'>key</span>);
<span class='kw'>let</span> <span class='ident'>e</span> <span class='op'>=</span> <span class='self'>self</span>.<span class='ident'>table</span>[<span class='ident'>h</span>];
<span class='kw'>if</span> <span class='ident'>e</span>.<span class='ident'>key</span> <span class='op'>==</span> <span class='ident'>key</span> <span class='op'>&amp;&amp;</span> <span class='ident'>e</span>.<span class='ident'>version</span> <span class='op'>==</span> <span class='self'>self</span>.<span class='ident'>version</span> {
<span class='prelude-val'>Some</span>(<span class='ident'>e</span>.<span class='ident'>pc</span>)
} <span class='kw'>else</span> {
<span class='self'>self</span>.<span class='ident'>table</span>[<span class='ident'>h</span>] <span class='op'>=</span> <span class='ident'>SuffixCacheEntry</span> {
<span class='ident'>key</span>: <span class='ident'>key</span>,
<span class='ident'>pc</span>: <span class='ident'>pc</span>,
<span class='ident'>version</span>: <span class='self'>self</span>.<span class='ident'>version</span>,
};
<span class='prelude-val'>None</span>
}
}
<span class='kw'>fn</span> <span class='ident'>clear</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>) {
<span class='self'>self</span>.<span class='ident'>version</span> <span class='op'>+=</span> <span class='number'>1</span>;
}
<span class='kw'>fn</span> <span class='ident'>hash</span>(<span class='kw-2'>&amp;</span><span class='self'>self</span>, <span class='ident'>suffix</span>: <span class='kw-2'>&amp;</span><span class='ident'>SuffixCacheKey</span>) <span class='op'>-&gt;</span> <span class='ident'>usize</span> {
<span class='comment'>// Basic FNV-1a hash as described:</span>
<span class='comment'>// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function</span>
<span class='kw'>const</span> <span class='ident'>FNV_PRIME</span>: <span class='ident'>u64</span> <span class='op'>=</span> <span class='number'>1099511628211</span>;
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>h</span> <span class='op'>=</span> <span class='number'>14695981039346656037</span>;
<span class='ident'>h</span> <span class='op'>=</span> (<span class='ident'>h</span> <span class='op'>^</span> (<span class='ident'>suffix</span>.<span class='ident'>from_inst</span> <span class='kw'>as</span> <span class='ident'>u64</span>)).<span class='ident'>wrapping_mul</span>(<span class='ident'>FNV_PRIME</span>);
<span class='ident'>h</span> <span class='op'>=</span> (<span class='ident'>h</span> <span class='op'>^</span> (<span class='ident'>suffix</span>.<span class='ident'>start</span> <span class='kw'>as</span> <span class='ident'>u64</span>)).<span class='ident'>wrapping_mul</span>(<span class='ident'>FNV_PRIME</span>);
<span class='ident'>h</span> <span class='op'>=</span> (<span class='ident'>h</span> <span class='op'>^</span> (<span class='ident'>suffix</span>.<span class='ident'>end</span> <span class='kw'>as</span> <span class='ident'>u64</span>)).<span class='ident'>wrapping_mul</span>(<span class='ident'>FNV_PRIME</span>);
(<span class='ident'>h</span> <span class='kw'>as</span> <span class='ident'>usize</span>) <span class='op'>%</span> <span class='self'>self</span>.<span class='ident'>table</span>.<span class='ident'>len</span>()
}
}
<span class='kw'>struct</span> <span class='ident'>ByteClassSet</span>([<span class='ident'>bool</span>; <span class='number'>256</span>]);
<span class='kw'>impl</span> <span class='ident'>ByteClassSet</span> {
<span class='kw'>fn</span> <span class='ident'>new</span>() <span class='op'>-&gt;</span> <span class='kw'>Self</span> {
<span class='ident'>ByteClassSet</span>([<span class='boolval'>false</span>; <span class='number'>256</span>])
}
<span class='kw'>fn</span> <span class='ident'>set_range</span>(<span class='kw-2'>&amp;</span><span class='kw-2'>mut</span> <span class='self'>self</span>, <span class='ident'>start</span>: <span class='ident'>u8</span>, <span class='ident'>end</span>: <span class='ident'>u8</span>) {
<span class='macro'>debug_assert</span><span class='macro'>!</span>(<span class='ident'>start</span> <span class='op'>&lt;=</span> <span class='ident'>end</span>);
<span class='kw'>if</span> <span class='ident'>start</span> <span class='op'>&gt;</span> <span class='number'>0</span> {
<span class='self'>self</span>.<span class='number'>0</span>[<span class='ident'>start</span> <span class='kw'>as</span> <span class='ident'>usize</span> <span class='op'>-</span> <span class='number'>1</span>] <span class='op'>=</span> <span class='boolval'>true</span>;
}
<span class='self'>self</span>.<span class='number'>0</span>[<span class='ident'>end</span> <span class='kw'>as</span> <span class='ident'>usize</span>] <span class='op'>=</span> <span class='boolval'>true</span>;
}
<span class='kw'>fn</span> <span class='ident'>byte_classes</span>(<span class='kw-2'>&amp;</span><span class='self'>self</span>) <span class='op'>-&gt;</span> <span class='ident'>Vec</span><span class='op'>&lt;</span><span class='ident'>u8</span><span class='op'>&gt;</span> {
<span class='comment'>// N.B. If you&#39;re debugging the DFA, it&#39;s useful to simply return</span>
<span class='comment'>// `(0..256).collect()`, which effectively removes the byte classes</span>
<span class='comment'>// and makes the transitions easier to read.</span>
<span class='comment'>// return (0..256).collect();</span>
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>byte_classes</span> <span class='op'>=</span> <span class='macro'>vec</span><span class='macro'>!</span>[<span class='number'>0</span>; <span class='number'>256</span>];
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>class</span> <span class='op'>=</span> <span class='number'>0u8</span>;
<span class='kw'>for</span> <span class='ident'>i</span> <span class='kw'>in</span> <span class='number'>0</span>..<span class='number'>256</span> {
<span class='ident'>byte_classes</span>[<span class='ident'>i</span>] <span class='op'>=</span> <span class='ident'>class</span>;
<span class='kw'>if</span> <span class='self'>self</span>.<span class='number'>0</span>[<span class='ident'>i</span>] {
<span class='ident'>class</span> <span class='op'>=</span> <span class='ident'>class</span>.<span class='ident'>checked_add</span>(<span class='number'>1</span>).<span class='ident'>unwrap</span>();
}
}
<span class='ident'>byte_classes</span>
}
}
<span class='kw'>fn</span> <span class='ident'>u32_to_usize</span>(<span class='ident'>n</span>: <span class='ident'>u32</span>) <span class='op'>-&gt;</span> <span class='ident'>usize</span> {
<span class='kw'>if</span> (<span class='ident'>n</span> <span class='kw'>as</span> <span class='ident'>u64</span>) <span class='op'>&gt;</span> (::<span class='ident'>std</span>::<span class='ident'>usize</span>::<span class='ident'>MAX</span> <span class='kw'>as</span> <span class='ident'>u64</span>) {
<span class='macro'>panic</span><span class='macro'>!</span>(<span class='string'>&quot;BUG: {} is too big to be pointer sized&quot;</span>, <span class='ident'>n</span>)
}
<span class='ident'>n</span> <span class='kw'>as</span> <span class='ident'>usize</span>
}
<span class='attribute'>#[<span class='ident'>cfg</span>(<span class='ident'>test</span>)]</span>
<span class='kw'>mod</span> <span class='ident'>tests</span> {
<span class='kw'>use</span> <span class='ident'>super</span>::<span class='ident'>ByteClassSet</span>;
<span class='attribute'>#[<span class='ident'>test</span>]</span>
<span class='kw'>fn</span> <span class='ident'>byte_classes</span>() {
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>set</span> <span class='op'>=</span> <span class='ident'>ByteClassSet</span>::<span class='ident'>new</span>();
<span class='ident'>set</span>.<span class='ident'>set_range</span>(<span class='string'>b&#39;a&#39;</span>, <span class='string'>b&#39;z&#39;</span>);
<span class='kw'>let</span> <span class='ident'>classes</span> <span class='op'>=</span> <span class='ident'>set</span>.<span class='ident'>byte_classes</span>();
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>0</span>], <span class='number'>0</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>1</span>], <span class='number'>0</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>2</span>], <span class='number'>0</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='string'>b&#39;a&#39;</span> <span class='kw'>as</span> <span class='ident'>usize</span> <span class='op'>-</span> <span class='number'>1</span>], <span class='number'>0</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='string'>b&#39;a&#39;</span> <span class='kw'>as</span> <span class='ident'>usize</span>], <span class='number'>1</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='string'>b&#39;m&#39;</span> <span class='kw'>as</span> <span class='ident'>usize</span>], <span class='number'>1</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='string'>b&#39;z&#39;</span> <span class='kw'>as</span> <span class='ident'>usize</span>], <span class='number'>1</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='string'>b&#39;z&#39;</span> <span class='kw'>as</span> <span class='ident'>usize</span> <span class='op'>+</span> <span class='number'>1</span>], <span class='number'>2</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>254</span>], <span class='number'>2</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>255</span>], <span class='number'>2</span>);
<span class='kw'>let</span> <span class='kw-2'>mut</span> <span class='ident'>set</span> <span class='op'>=</span> <span class='ident'>ByteClassSet</span>::<span class='ident'>new</span>();
<span class='ident'>set</span>.<span class='ident'>set_range</span>(<span class='number'>0</span>, <span class='number'>2</span>);
<span class='ident'>set</span>.<span class='ident'>set_range</span>(<span class='number'>4</span>, <span class='number'>6</span>);
<span class='kw'>let</span> <span class='ident'>classes</span> <span class='op'>=</span> <span class='ident'>set</span>.<span class='ident'>byte_classes</span>();
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>0</span>], <span class='number'>0</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>1</span>], <span class='number'>0</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>2</span>], <span class='number'>0</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>3</span>], <span class='number'>1</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>4</span>], <span class='number'>2</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>5</span>], <span class='number'>2</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>6</span>], <span class='number'>2</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>7</span>], <span class='number'>3</span>);
<span class='macro'>assert_eq</span><span class='macro'>!</span>(<span class='ident'>classes</span>[<span class='number'>255</span>], <span class='number'>3</span>);
}
}
</pre>
</section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<aside id="help" class="hidden">
<div>
<h1 class="hidden">Help</h1>
<div class="shortcuts">
<h2>Keyboard Shortcuts</h2>
<dl>
<dt>?</dt>
<dd>Show this help dialog</dd>
<dt>S</dt>
<dd>Focus the search field</dd>
<dt>&larrb;</dt>
<dd>Move up in search results</dd>
<dt>&rarrb;</dt>
<dd>Move down in search results</dd>
<dt>&#9166;</dt>
<dd>Go to active search result</dd>
</dl>
</div>
<div class="infos">
<h2>Search Tricks</h2>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>type</code>, <code>macro</code>,
and <code>const</code>.
</p>
<p>
Search functions by type signature (e.g.
<code>vec -> usize</code> or <code>* -> vec</code>)
</p>
</div>
</div>
</aside>
<script>
window.rootPath = "../../";
window.currentCrate = "regex";
window.playgroundUrl = "";
</script>
<script src="../../jquery.js"></script>
<script src="../../main.js"></script>
<script defer src="../../search-index.js"></script>
</body>
</html>