summaryrefslogtreecommitdiff
path: root/miniany/doc/Writing a C Compiler, Part 2.html
diff options
context:
space:
mode:
Diffstat (limited to 'miniany/doc/Writing a C Compiler, Part 2.html')
-rw-r--r--miniany/doc/Writing a C Compiler, Part 2.html357
1 files changed, 357 insertions, 0 deletions
diff --git a/miniany/doc/Writing a C Compiler, Part 2.html b/miniany/doc/Writing a C Compiler, Part 2.html
new file mode 100644
index 0000000..835b5d5
--- /dev/null
+++ b/miniany/doc/Writing a C Compiler, Part 2.html
@@ -0,0 +1,357 @@
+<!DOCTYPE html>
+<!-- saved from url=(0058)https://norasandler.com/2017/12/05/Write-a-Compiler-2.html -->
+<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <title>Writing a C Compiler, Part 2</title>
+ <meta name="description" content="This is the second post in a series. Read part 1 here.">
+
+ <link rel="stylesheet" href="./Writing a C Compiler, Part 2_files/main.css">
+ <link rel="canonical" href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html">
+ <link rel="alternate" type="application/rss+xml" title="Nora Sandler" href="https://norasandler.com/feed.xml">
+
+</head>
+
+
+ <body>
+
+ <header class="site-header" role="banner">
+
+ <div class="wrapper">
+
+
+ <a class="site-title" href="https://norasandler.com/">Nora Sandler</a>
+
+
+ <nav class="site-nav">
+ <input type="checkbox" id="nav-trigger" class="nav-trigger">
+ <label for="nav-trigger">
+ <span class="menu-icon">
+ <svg viewBox="0 0 18 15" width="18px" height="15px">
+ <path fill="#424242" d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.031C17.335,0,18,0.665,18,1.484L18,1.484z"></path>
+ <path fill="#424242" d="M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0c0-0.82,0.665-1.484,1.484-1.484 h15.031C17.335,6.031,18,6.696,18,7.516L18,7.516z"></path>
+ <path fill="#424242" d="M18,13.516C18,14.335,17.335,15,16.516,15H1.484C0.665,15,0,14.335,0,13.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.031C17.335,12.031,18,12.696,18,13.516L18,13.516z"></path>
+ </svg>
+ </span>
+ </label>
+
+ <div class="trigger">
+
+
+
+
+
+
+
+
+
+ <a class="page-link" href="https://norasandler.com/about/">About</a>
+
+
+
+
+
+
+ <a class="page-link" href="https://norasandler.com/archive/">Archive</a>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <a class="page-link" href="https://github.com/nlsandler">Github</a>
+ <a href="https://norasandler.com/feed.xml"><img id="rss" height="20" width="20" src="./Writing a C Compiler, Part 2_files/rss.png"></a>
+
+ </div>
+ </nav>
+
+ </div>
+</header>
+
+
+ <main class="page-content" aria-label="Content">
+ <div class="wrapper">
+ <article class="post h-entry" itemscope="" itemtype="http://schema.org/BlogPosting">
+
+ <header class="post-header">
+ <h1 class="post-title p-name" itemprop="name headline">Writing a C Compiler, Part 2</h1>
+ <p class="post-meta">
+ <time class="dt-published" datetime="2017-12-05T21:30:00+00:00" itemprop="datePublished">Dec 5, 2017
+ </time></p>
+ </header>
+
+ <div class="post-content e-content" itemprop="articleBody">
+ <p><em>This is the second post in a series. Read part 1 <a href="https://norasandler.com/2017/11/29/Write-a-Compiler.html">here</a>.</em></p>
+
+<p>In the last post, we learned to compile programs that return integers. This week we’ll do math to those integers. Same as last week, you can find the accompanying tests <a href="https://github.com/nlsandler/write_a_c_compiler">here</a>.</p>
+
+<h1 id="week-2-unary-operators">Week 2: Unary Operators</h1>
+
+<p>This week, we’re adding three unary operators<sup id="anchor1"><a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#fn1">1</a></sup> (i.e. operators that only take one value):</p>
+
+<p><strong>Negation (<code class="language-plaintext highlighter-rouge">-</code>)</strong></p>
+
+<p>-5 = 0 - 5. In other words, it’s a regular negative number.</p>
+
+<p><strong>Bitwise complement (<code class="language-plaintext highlighter-rouge">~</code>)</strong></p>
+
+<p>This flips every bit in a number<sup id="anchor2"><a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#fn2">2</a></sup>. For example:</p>
+<ul>
+ <li>4 is written as 100 in binary.</li>
+ <li>The bitwise complement of 100 is 011.</li>
+ <li>011 in decimal is 3.</li>
+ <li>So ~4 = 3.</li>
+</ul>
+
+<p><strong>Logical negation (<code class="language-plaintext highlighter-rouge">!</code>)</strong></p>
+
+<p>The boolean “not” operator. This treats 0 as “false” and everything else as “true”.</p>
+
+<ul>
+ <li>!0 = 1</li>
+ <li>!(anything else) = 0</li>
+</ul>
+
+<p>Last week we created a compiler with three stages: a lexer, a parser, and a code generator. Now we’ll update each stage to handle these new operators.</p>
+
+<h2 id="lexing">Lexing</h2>
+
+<p>We just need to add each of these operators to our list of tokens. Here’s the list of tokens: tokens from last week are at the top, and new tokens are bolded at the bottom.</p>
+
+<ul>
+ <li>Open brace <code class="language-plaintext highlighter-rouge">{</code></li>
+ <li>Close brace <code class="language-plaintext highlighter-rouge">}</code></li>
+ <li>Open parenthesis <code class="language-plaintext highlighter-rouge">\(</code></li>
+ <li>Close parenthesis <code class="language-plaintext highlighter-rouge">\)</code></li>
+ <li>Semicolon <code class="language-plaintext highlighter-rouge">;</code></li>
+ <li>Int keyword <code class="language-plaintext highlighter-rouge">int</code></li>
+ <li>Return keyword <code class="language-plaintext highlighter-rouge">return</code></li>
+ <li>Identifier <code class="language-plaintext highlighter-rouge">[a-zA-Z]\w*</code></li>
+ <li>Integer literal <code class="language-plaintext highlighter-rouge">[0-9]+</code></li>
+ <li><strong>Negation <code class="language-plaintext highlighter-rouge">-</code></strong></li>
+ <li><strong>Bitwise complement <code class="language-plaintext highlighter-rouge">~</code></strong></li>
+ <li><strong>Logical negation <code class="language-plaintext highlighter-rouge">!</code></strong></li>
+</ul>
+
+<p>We can process these new tokens exactly the same way as the other single-character tokens, like braces and parentheses.</p>
+
+<h4 id="-task">☑ Task:</h4>
+<p>Update the <em>lex</em> function to handle the new tokens. It should work for all stage 1 and 2 examples in the test suite, including the invalid ones.</p>
+
+<h2 id="parsing">Parsing</h2>
+
+<p>Last week we defined several AST nodes, including expressions. We only defined one type of expression: constants. This week, we’ll add another type of expression, unary operations. The latest set of definitions is below. Only the definition of <code class="language-plaintext highlighter-rouge">exp</code> has changed.</p>
+
+<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>program = Program(function_declaration)
+function_declaration = Function(string, statement) //string is the function name
+statement = Return(exp)
+exp = UnOp(operator, exp) | Constant(int)
+</code></pre></div></div>
+
+<p>Now, an expression can take one of two forms - it can be either a constant, or a unary operation. A unary operation consists of the operator (e.g. <code class="language-plaintext highlighter-rouge">~</code>), and the operand, which is itself an expression. For example, here’s how we could construct the expression <code class="language-plaintext highlighter-rouge">~3</code>:</p>
+
+<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>c = Const(3)
+exp = UnOp(COMPLEMENT, c)
+</code></pre></div></div>
+
+<p>Our definition of expressions is recursive - expressions can contain other expressions!</p>
+
+<p>This is an expression: <code class="language-plaintext highlighter-rouge">!3</code></p>
+
+<p>So is this: <code class="language-plaintext highlighter-rouge">!~-4</code></p>
+
+<p>So is this: <code class="language-plaintext highlighter-rouge">!!!!!!!-~~-!3</code></p>
+
+<p>We need to update our formal grammar too:</p>
+
+<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;program&gt; ::= &lt;function&gt;
+&lt;function&gt; ::= "int" &lt;id&gt; "(" ")" "{" &lt;statement&gt; "}"
+&lt;statement&gt; ::= "return" &lt;exp&gt; ";"
+&lt;exp&gt; ::= &lt;unary_op&gt; &lt;exp&gt; | &lt;int&gt;
+&lt;unary_op&gt; ::= "!" | "~" | "-"
+</code></pre></div></div>
+
+<p>Because the definition of an expression is recursive, the function to parse an expression should also be recursive.
+Here’s the pseudocode for parsing an expression:</p>
+
+<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>def parse_expression(tokens):
+ tok = tokens.next()
+ if tok.type == "INT":
+ //parse this the same way as before, return a Const node
+ else:
+ op = get_operator(tok) //convert token to unary_op AST element - fail if token isn't "!", "~" or "-"
+ inner_exp = parse_expression(tokens) //HOORAY, RECURSION - this will pop more tokens off the stack
+ return UnOp(op, inner_exp)
+</code></pre></div></div>
+
+<h4 id="-task-1">☑ Task:</h4>
+<p>Update your expression-parsing function to handle unary operations. It should successfully parse all valid stage 1 and 2 examples in the test suite, and fail on all invalid stage 1 and 2 examples.</p>
+
+<h2 id="code-generation">Code Generation</h2>
+
+<p>Negation and bitwise complement are super easy; each of them can be accomplished with a single assembly instruction.</p>
+
+<p><code class="language-plaintext highlighter-rouge">neg</code> negates the value of its operand<sup id="anchor3"><a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#fn3">3</a></sup>. Here’s an example:</p>
+
+<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nf">movl</span> <span class="kc">$</span><span class="mi">3</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span> <span class="c1">;EAX register contains 3</span>
+ <span class="nf">neg</span> <span class="o">%</span><span class="nb">eax</span> <span class="c1">;now EAX register contains -3</span>
+</code></pre></div></div>
+
+<p>Of course, we need to calculate a value before we can negate it, so we need to recursively generate code for the inner expression, then emit the <code class="language-plaintext highlighter-rouge">neg</code> instruction.</p>
+
+<p><code class="language-plaintext highlighter-rouge">not</code> replaces a value with its bitwise complement. We can use it exactly the same way as <code class="language-plaintext highlighter-rouge">neg</code>.</p>
+
+<p>Logical negation is a little more complicated. Remember, <code class="language-plaintext highlighter-rouge">return !exp</code> is equivalent to:</p>
+<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">exp</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
+ <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
+<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
+ <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
+<span class="p">}</span>
+</code></pre></div></div>
+
+<p>Unlike the other operations, which were straightforward bit manipulation, this requires some conditional logic. We can implement it using <code class="language-plaintext highlighter-rouge">cmpl</code><sup id="anchor4"><a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#fn4">4</a></sup>, which compares two values, and <code class="language-plaintext highlighter-rouge">sete</code> (“set if equal”). <code class="language-plaintext highlighter-rouge">sete</code> sets its operand to 1 if the result of the last comparison was equal, and 0 otherwise.</p>
+
+<p>Comparision and conditonal instructions like <code class="language-plaintext highlighter-rouge">cmpl</code> and <code class="language-plaintext highlighter-rouge">sete</code> are a little weird; <code class="language-plaintext highlighter-rouge">cmpl</code> doesn’t explicitly store the result of the comparison, and <code class="language-plaintext highlighter-rouge">sete</code> doesn’t explicitly refer to that result, or to the values being compared. Both of these instructions - and all comparison and conditional instructions - implicitly refer to the <a href="https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture#EFLAGS_Register">FLAGS register</a><sup id="anchor5"><a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#fn5">5</a></sup>. As the name suggests, the contents of this register are interpreted as an array of one-bit flags, rather than a single integer. These flags are automatically set after every arithmetic operation. The only flag we care about right now is the zero flag (ZF), which is set on if the result of an operation is 0, and set off otherwise.</p>
+
+<p><code class="language-plaintext highlighter-rouge">cmpl a, b</code> computes (b - a) and sets FLAGS accordingly. If two values are equal, their difference is 0, so ZF will be set on if and only if the operands to <code class="language-plaintext highlighter-rouge">cmpl</code> are equal. The <code class="language-plaintext highlighter-rouge">sete</code> instruction uses ZF to test for equality; it sets its operand to 1 if ZF is on, and 0 if ZF is off. In fact, <code class="language-plaintext highlighter-rouge">setz</code> (“set if zero”) is another mnemonic for the same instruction.</p>
+
+<p>The last gotcha here is that <code class="language-plaintext highlighter-rouge">sete</code> can only set a <em>byte</em>, not an entire four-byte integer. We’ll have it set the AL register, which is just the least-significant byte of EAX. We just need to zero out EAX first<sup id="anchor6"><a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#fn6">6</a></sup>; since the result of <code class="language-plaintext highlighter-rouge">!</code> is always 0 or 1, we dont want to leave any stray higher bits set.</p>
+
+<p>So that was a long explanation, but you can actually implement <code class="language-plaintext highlighter-rouge">!</code> in just three lines of assembly:</p>
+
+<div class="language-nasm highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="err">&lt;</span><span class="nf">CODE</span> <span class="nv">FOR</span> <span class="nv">exp</span> <span class="nv">GOES</span> <span class="nv">HERE</span><span class="o">&gt;</span>
+ <span class="nf">cmpl</span> <span class="kc">$</span><span class="mi">0</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span> <span class="c1">;set ZF on if exp == 0, set it off otherwise</span>
+ <span class="nf">movl</span> <span class="kc">$</span><span class="mi">0</span><span class="p">,</span> <span class="o">%</span><span class="nb">eax</span> <span class="c1">;zero out EAX (doesn't change FLAGS)</span>
+ <span class="nf">sete</span> <span class="o">%</span><span class="nb">al</span> <span class="c1">;set AL register (the lower byte of EAX) to 1 iff ZF is on</span>
+</code></pre></div></div>
+
+<p>To convince ourselves that this is correct, let’s work through this with the expression <code class="language-plaintext highlighter-rouge">!5</code>:</p>
+
+<ol>
+ <li>First we move 5 into the EAX register.</li>
+ <li>We compare 0 to 5. 5 != 0, so the ZF flag is set to 0.</li>
+ <li>The EAX register is zeroed out, so we can set it in the next step.</li>
+ <li>We conditionaly set AL; because ZF is 0, we set AL to 0. AL refers to the lower bytes of EAX; the upper bytes were also zeroed in step 3, so now EAX contains 0.</li>
+</ol>
+
+<h4 id="-task-2">☑ Task:</h4>
+<p>Update your code-generation pass to emit correct code for <code class="language-plaintext highlighter-rouge">!</code>, <code class="language-plaintext highlighter-rouge">~</code> and <code class="language-plaintext highlighter-rouge">-</code> operations. It should generate correct assembly for all valid stage 1 and stage 2 examples.</p>
+
+<h2 id="up-next">Up Next</h2>
+
+<p><a href="https://norasandler.com/2017/12/15/Write-a-Compiler-3.html">Next week</a> we’ll find out whether 2+2 really does equal 4, by adding some binary operations: addition, subtraction, and more. See you then!</p>
+
+<h2 id="update-10112023">Update 10/11/2023</h2>
+
+<ul>
+ <li>Clarified the definition of “word” in footnote 4, and updated several posts in the series to avoid the term “word”. I previously used “word” to mean a 32-bit integer. Thanks to Denton Spivey for pointing out the confusing terminology.</li>
+</ul>
+
+<p><em>If you have any questions, corrections, or other feedback, you can <a href="mailto:nora@norasandler.com">email me</a> or <a href="https://github.com/nlsandler/write_a_c_compiler/issues">open an issue</a>.</em></p>
+
+<div class="footnote">
+ <p><sup id="fn1">1</sup>
+These are defined on page 89 of the <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf">C11 standard</a>.<a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#anchor1">↩</a></p>
+</div>
+
+<div class="footnote">
+ <p><sup id="fn2">2</sup>
+As <a href="https://news.ycombinator.com/item?id=15864537">remcob correctly pointed out</a> on Hacker News, the bitwise complement of a number really depends on how many bits you’re using to represent it. The example above is correct if we assume all integers are 3 bits. But if an integer is 8 bits, then 4 is 00000100, so ~4 is 11111011, or 251. To make things even MORE complicated, 11111011 is only 251 if you’re dealing with an unsigned integer - if it’s signed, then 11111011 is actually the two’s complement representation of -5.<a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#anchor2">↩</a></p>
+</div>
+
+<div class="footnote">
+ <p><sup id="fn3">3</sup>
+To be really pedantic, <code class="language-plaintext highlighter-rouge">neg</code> calculates the <a href="https://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html">two’s complement</a> of its operand.<a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#anchor3">↩</a></p>
+</div>
+
+<div class="footnote">
+ <p><sup id="fn4">4</sup>
+Some documentation mentions <code class="language-plaintext highlighter-rouge">mov</code> and <code class="language-plaintext highlighter-rouge">cmp</code> instead of <code class="language-plaintext highlighter-rouge">movl</code> and <code class="language-plaintext highlighter-rouge">cmpl</code>; later you’ll see that “l” suffix on a lot of other instructions too. The “l” stands for “longword”, and indicates that the operand is 32 bits. (More assembly suffixes <a href="https://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax#Operation_Suffixes">here</a>.) When we describe a processor as 32- or 64-bit, we’re talking about its <a href="https://en.wikipedia.org/wiki/Word_(computer_architecture)">word size</a>, the main integer operand size it’s designed to work with. But a lot of discussions of assembly code call 16-bit values “words,” 32-bit values “longwords” or “doublewords,” and 64-bit values “quadwords,” regardless of the processor’s word size. This terminology is a relic of the era of 16-bit processors.
+<a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#anchor4">↩</a></p>
+</div>
+
+<div class="footnote">
+ <p><sup id="fn5">5</sup>
+Actually, it’s FLAGS on 16-bit machines, EFLAGS on 32-bit machines, and RFLAGS on 64-bit machines, so your computer almost definitely doesn’t have a FLAGS register. But the flags we care about are all in the lower 16 bits so it doesn’t really matter. <a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#anchor5">↩</a></p>
+</div>
+
+<div class="footnote">
+ <p><sup id="fn6">6</sup>
+<code class="language-plaintext highlighter-rouge">mov $0, %eax</code> is the most obvious way to zero out a register, but it isn’t the quickest. <code class="language-plaintext highlighter-rouge">xor %eax, %eax</code> is better, for reasons you can read about <a href="https://stackoverflow.com/questions/33666617/what-is-the-best-way-to-set-a-register-to-zero-in-x86-assembly-xor-mov-or-and/33668295#33668295">here</a>. There’s a whole slew of ways to zero a register; in your compiler you can use whichever one you want. <a href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html#anchor6">↩</a></p>
+</div>
+
+ </div><a class="u-url" href="https://norasandler.com/2017/12/05/Write-a-Compiler-2.html" hidden=""></a>
+</article>
+
+ </div>
+ </main>
+
+ <footer class="site-footer">
+
+ <div class="wrapper">
+ <div class="footer-col-wrapper">
+ <div class="footer-col footer-col-1">
+ <div class="rc-scout" data-scout-rendered="true"><p class="rc-scout__text"><i class="rc-scout__logo"></i> Want to become a better programmer? <a class="rc-scout__link" href="https://www.recurse.com/scout/click?t=8f520efbc4be09fb83a71920f53a07b7">Join the Recurse Center!</a></p></div><script async="" defer="" src="./Writing a C Compiler, Part 2_files/loader.js"></script>
+ </div>
+ </div>
+ <div class="footer-col-wrapper">
+ <div class="footer-col footer-col-1">
+ © 2023 Nora Sandler.
+ </div>
+ </div>
+ </div>
+
+</footer>
+
+
+
+
+
+<script async="" src="./Writing a C Compiler, Part 2_files/scout-176be16681a03cbddd686f3cc96694d3aab338ea5cb65452f83d989309810528.js"></script><style class="rc-scout__style" type="text/css">.rc-scout {
+ display: block;
+ padding: 0;
+ border: 0;
+ margin: 0;
+}
+.rc-scout__text {
+ display: block;
+ padding: 0;
+ border: 0;
+ margin: 0;
+ height: 100%;
+ font-size: 100%;
+}
+.rc-scout__logo {
+ display: inline-block;
+ padding: 0;
+ border: 0;
+ margin: 0;
+ width: 0.85em;
+ height: 0.85em;
+ background: no-repeat center url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2012%2015%22%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%2212%22%20height%3D%2210%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%221%22%20y%3D%221%22%20width%3D%2210%22%20height%3D%228%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%222%22%20y%3D%222%22%20width%3D%228%22%20height%3D%226%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%222%22%20y%3D%223%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%233dc06c%22%3E%3C%2Frect%3E%3Crect%20x%3D%224%22%20y%3D%223%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%233dc06c%22%3E%3C%2Frect%3E%3Crect%20x%3D%226%22%20y%3D%223%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%233dc06c%22%3E%3C%2Frect%3E%3Crect%20x%3D%223%22%20y%3D%225%22%20width%3D%222%22%20height%3D%221%22%20fill%3D%22%233dc06c%22%3E%3C%2Frect%3E%3Crect%20x%3D%226%22%20y%3D%225%22%20width%3D%222%22%20height%3D%221%22%20fill%3D%22%233dc06c%22%3E%3C%2Frect%3E%3Crect%20x%3D%224%22%20y%3D%229%22%20width%3D%224%22%20height%3D%223%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%221%22%20y%3D%2211%22%20width%3D%2210%22%20height%3D%224%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%220%22%20y%3D%2212%22%20width%3D%2212%22%20height%3D%223%22%20fill%3D%22%23000%22%3E%3C%2Frect%3E%3Crect%20x%3D%222%22%20y%3D%2213%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%223%22%20y%3D%2212%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%224%22%20y%3D%2213%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%225%22%20y%3D%2212%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%226%22%20y%3D%2213%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%227%22%20y%3D%2212%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%228%22%20y%3D%2213%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3Crect%20x%3D%229%22%20y%3D%2212%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22%23fff%22%3E%3C%2Frect%3E%3C%2Fsvg%3E');
+}
+.rc-scout__link:link, .rc-scout__link:visited {
+ color: #3dc06c;
+ text-decoration: underline;
+}
+.rc-scout__link:hover, .rc-scout__link:active {
+ color: #4e8b1d;
+}
+</style></body></html> \ No newline at end of file