inweb-bootstrap/docs/inweb/4-tp.html
2020-04-07 23:04:32 +01:00

582 lines
106 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>4/as</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../inweb/index.html">inweb</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../foundation-module/index.html">foundation-module</a></li>
<li><a href="../foundation-test/index.html">foundation-test</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '4/tp' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="index.html">inweb</a></li><li><a href="index.html#4">Chapter 4: Languages</a></li><li><b>The Painter</b></li></ul><p class="purpose">A simple syntax-colouring engine.</p>
<ul class="toc"><li><a href="#SP7">&#167;7. Painting a file</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. </b>This is a very simple syntax colouring algorithm. The work is done by the
function <code class="display"><span class="extract">Painter::syntax_colour</span></code>, which can in principle be applied to texts
of any length. But it's usually convenient to run it on a long file one line
at a time, so that it is called repeatedly. The variable <code class="display"><span class="extract">colouring_state</span></code>
remembers where we were at the end of the previous line, so that we can pick
up again later at the start of the next.
</p>
<p class="inwebparagraph">Because of that, we need to call the following before we begin a run of calls
to <code class="display"><span class="extract">Painter::syntax_colour</span></code>:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">painter_count</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Painter::reset_syntax_colouring</span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain">) {</span>
<span class="identifier">colouring_state</span><span class="plain"> = </span><span class="constant">PLAIN_COLOUR</span><span class="plain">;</span>
<span class="identifier">painter_count</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Painter::reset_syntax_colouring is used in <a href="#SP7">&#167;7</a>, 4/as (<a href="4-as.html#SP6">&#167;6</a>).</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>As we begin, the text to colour is in <code class="display"><span class="extract">matter</span></code>, while <code class="display"><span class="extract">colouring</span></code> is an
equal-length text where each character represents the colour of its
corresponding character in <code class="display"><span class="extract">matter</span></code>. For example, we might start as:
</p>
<pre class="display">
<span class="plain">int x = 55;</span>
<span class="plain">ppppppppppp</span>
</pre>
<p class="inwebparagraph">with every character having <code class="display"><span class="extract">PLAIN_COLOUR</span></code>, but end up with:
</p>
<pre class="display">
<span class="plain">int x = 55;</span>
<span class="reserved">rrr</span><span class="plain">p</span><span class="identifier">i</span><span class="plain">ppp</span><span class="constant">nn</span><span class="plain">p</span>
</pre>
<p class="inwebparagraph">We get to that by using a language's rules on literals, and then executing
its colouring program.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Painter::syntax_colour</span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain">,</span>
<span class="reserved">hash_table</span><span class="plain"> *</span><span class="identifier">HT</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">matter</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">colouring</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">with_comments</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">from</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">to</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">) - </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">with_comments</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">part_before_comment</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">part_within_comment</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">LanguageMethods::parse_comment</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">,</span>
<span class="identifier">matter</span><span class="plain">, </span><span class="identifier">part_before_comment</span><span class="plain">, </span><span class="identifier">part_within_comment</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">part_before_comment</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">N</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="functiontext">Str::put_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="constant">COMMENT_COLOUR</span><span class="plain">);</span>
<span class="identifier">from</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">to</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">part_before_comment</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">part_before_comment</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">part_within_comment</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">Painter::syntax_colour_inner</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Painter::syntax_colour_inner</span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain">,</span>
<span class="reserved">hash_table</span><span class="plain"> *</span><span class="identifier">HT</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">matter</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">colouring</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">to</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Spot identifiers, literal text and character constants</span> <span class="cwebmacronumber">2.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Spot literal numerical constants</span> <span class="cwebmacronumber">2.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Now run the colouring program</span> <span class="cwebmacronumber">2.4</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Painter::syntax_colour is used in <a href="#SP7">&#167;7</a>, 4/as (<a href="4-as.html#SP6">&#167;6</a>).</p>
<p class="endnote">The function Painter::syntax_colour_inner appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP2_1"></a><b>&#167;2.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Spot identifiers, literal text and character constants</span> <span class="cwebmacronumber">2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">squote</span><span class="plain"> = </span><span class="functiontext">Str::get_first_char</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">character_literal</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">squote_escape</span><span class="plain"> = </span><span class="functiontext">Str::get_first_char</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">character_literal_escape</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">dquote</span><span class="plain"> = </span><span class="functiontext">Str::get_first_char</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">string_literal</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">dquote_escape</span><span class="plain"> = </span><span class="functiontext">Str::get_first_char</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">string_literal_escape</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain"> &lt;= </span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">skip</span><span class="plain"> = </span><span class="constant">NOT_A_COLOUR</span><span class="plain">, </span><span class="identifier">one_off</span><span class="plain"> = -1, </span><span class="identifier">will_be</span><span class="plain"> = -1;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">colouring_state</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">PLAIN_COLOUR:</span><span class="plain"> {</span>
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="identifier">dquote</span><span class="plain">) {</span>
<span class="identifier">colouring_state</span><span class="plain"> = </span><span class="constant">STRING_COLOUR</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="identifier">squote</span><span class="plain">) {</span>
<span class="identifier">colouring_state</span><span class="plain"> = </span><span class="constant">CHAR_LITERAL_COLOUR</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Painter::identifier_at</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">))</span>
<span class="identifier">one_off</span><span class="plain"> = </span><span class="constant">IDENTIFIER_COLOUR</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CHAR_LITERAL_COLOUR:</span><span class="plain"> {</span>
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="identifier">squote</span><span class="plain">) </span><span class="identifier">will_be</span><span class="plain"> = </span><span class="constant">PLAIN_COLOUR</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="identifier">squote_escape</span><span class="plain">) </span><span class="identifier">skip</span><span class="plain"> = </span><span class="constant">CHAR_LITERAL_COLOUR</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">STRING_COLOUR:</span><span class="plain"> {</span>
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="identifier">dquote</span><span class="plain">) </span><span class="identifier">will_be</span><span class="plain"> = </span><span class="constant">PLAIN_COLOUR</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="identifier">dquote_escape</span><span class="plain">) </span><span class="identifier">skip</span><span class="plain"> = </span><span class="constant">STRING_COLOUR</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">one_off</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) </span><span class="functiontext">Str::put_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, (</span><span class="reserved">char</span><span class="plain">) </span><span class="identifier">one_off</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Str::put_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, (</span><span class="reserved">char</span><span class="plain">) </span><span class="identifier">colouring_state</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">will_be</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">colouring_state</span><span class="plain"> = (</span><span class="reserved">char</span><span class="plain">) </span><span class="identifier">will_be</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">skip</span><span class="plain"> != </span><span class="constant">NOT_A_COLOUR</span><span class="plain">) &amp;&amp; (</span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">to</span><span class="plain">)) {</span>
<span class="identifier">i</span><span class="plain">++; </span><span class="functiontext">Str::put_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">skip</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2">&#167;2</a>.</p>
<p class="inwebparagraph"><a id="SP2_2"></a><b>&#167;2.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Spot literal numerical constants</span> <span class="cwebmacronumber">2.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">base</span><span class="plain"> = -1, </span><span class="identifier">dec_possible</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain"> &lt;= </span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="constant">PLAIN_COLOUR</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="constant">IDENTIFIER_COLOUR</span><span class="plain">)) {</span>
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ACMESupport::text_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">binary_literal_prefix</span><span class="plain">)) {</span>
<span class="identifier">base</span><span class="plain"> = </span><span class="constant">2</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">binary_literal_prefix</span><span class="plain">); </span><span class="identifier">j</span><span class="plain">++)</span>
<span class="functiontext">Str::put_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">j</span><span class="plain">, (</span><span class="reserved">char</span><span class="plain">) </span><span class="constant">CONSTANT_COLOUR</span><span class="plain">);</span>
<span class="identifier">dec_possible</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ACMESupport::text_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">octal_literal_prefix</span><span class="plain">)) {</span>
<span class="identifier">base</span><span class="plain"> = </span><span class="constant">8</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">octal_literal_prefix</span><span class="plain">); </span><span class="identifier">j</span><span class="plain">++)</span>
<span class="functiontext">Str::put_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">j</span><span class="plain">, (</span><span class="reserved">char</span><span class="plain">) </span><span class="constant">CONSTANT_COLOUR</span><span class="plain">);</span>
<span class="identifier">dec_possible</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ACMESupport::text_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">hexadecimal_literal_prefix</span><span class="plain">)) {</span>
<span class="identifier">base</span><span class="plain"> = </span><span class="constant">16</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">hexadecimal_literal_prefix</span><span class="plain">); </span><span class="identifier">j</span><span class="plain">++)</span>
<span class="functiontext">Str::put_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">j</span><span class="plain">, (</span><span class="reserved">char</span><span class="plain">) </span><span class="constant">CONSTANT_COLOUR</span><span class="plain">);</span>
<span class="identifier">dec_possible</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">ACMESupport::text_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">negative_literal_prefix</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">dec_possible</span><span class="plain">) &amp;&amp; (</span><span class="identifier">base</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)) {</span>
<span class="identifier">base</span><span class="plain"> = </span><span class="constant">10</span><span class="plain">;</span>
<span class="functiontext">Str::put_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, (</span><span class="reserved">char</span><span class="plain">) </span><span class="constant">CONSTANT_COLOUR</span><span class="plain">);</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pass</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">base</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> -1:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">dec_possible</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Characters::isdigit</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">))) {</span>
<span class="identifier">base</span><span class="plain"> = </span><span class="constant">10</span><span class="plain">; </span><span class="identifier">pass</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">2</span><span class="plain">: </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'0'</span><span class="plain">) || (</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'1'</span><span class="plain">)) </span><span class="identifier">pass</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">10</span><span class="plain">: </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Characters::isdigit</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">)) </span><span class="identifier">pass</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">16</span><span class="plain">: </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Characters::isdigit</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">)) </span><span class="identifier">pass</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">d</span><span class="plain"> = </span><span class="functiontext">Characters::tolower</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">d</span><span class="plain"> == </span><span class="character">'a'</span><span class="plain">) || (</span><span class="identifier">d</span><span class="plain"> == </span><span class="character">'b'</span><span class="plain">) || (</span><span class="identifier">d</span><span class="plain"> == </span><span class="character">'c'</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">d</span><span class="plain"> == </span><span class="character">'d'</span><span class="plain">) || (</span><span class="identifier">d</span><span class="plain"> == </span><span class="character">'e'</span><span class="plain">) || (</span><span class="identifier">d</span><span class="plain"> == </span><span class="character">'f'</span><span class="plain">)) </span><span class="identifier">pass</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pass</span><span class="plain">) {</span>
<span class="functiontext">Str::put_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, (</span><span class="reserved">char</span><span class="plain">) </span><span class="constant">CONSTANT_COLOUR</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Characters::is_whitespace</span><span class="plain">(</span><span class="identifier">c</span><span class="plain">)) </span><span class="identifier">dec_possible</span><span class="plain"> = </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">dec_possible</span><span class="plain"> = </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">base</span><span class="plain"> = -1;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2">&#167;2</a>.</p>
<p class="inwebparagraph"><a id="SP2_3"></a><b>&#167;2.3. </b>For the moment, we always adopt the C rules on identifiers: they have to
begin with an underscore or letter, then continue with underscores or
alphanumeric characters, except that if the language allows it then they
can contain a <code class="display"><span class="extract">::</span></code> namespace divider.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Painter::identifier_at</span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain">,</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">matter</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">colouring</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">) {</span>
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">i</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">-1) == </span><span class="constant">IDENTIFIER_COLOUR</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'_'</span><span class="plain">) ||</span>
<span class="plain">((</span><span class="identifier">c</span><span class="plain"> &gt;= </span><span class="character">'A'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">c</span><span class="plain"> &lt;= </span><span class="character">'Z'</span><span class="plain">)) ||</span>
<span class="plain">((</span><span class="identifier">c</span><span class="plain"> &gt;= </span><span class="character">'a'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">c</span><span class="plain"> &lt;= </span><span class="character">'z'</span><span class="plain">)) ||</span>
<span class="plain">((</span><span class="identifier">c</span><span class="plain"> &gt;= </span><span class="character">'0'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">c</span><span class="plain"> &lt;= </span><span class="character">'9'</span><span class="plain">))) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">':'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">supports_namespaces</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">wchar_t</span><span class="plain"> </span><span class="identifier">d</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">d</span><span class="plain"> = </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">d</span><span class="plain"> &gt;= </span><span class="character">'0'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">d</span><span class="plain"> &lt;= </span><span class="character">'9'</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> == </span><span class="character">'_'</span><span class="plain">) ||</span>
<span class="plain">((</span><span class="identifier">c</span><span class="plain"> &gt;= </span><span class="character">'A'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">c</span><span class="plain"> &lt;= </span><span class="character">'Z'</span><span class="plain">)) ||</span>
<span class="plain">((</span><span class="identifier">c</span><span class="plain"> &gt;= </span><span class="character">'a'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">c</span><span class="plain"> &lt;= </span><span class="character">'z'</span><span class="plain">))) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Painter::identifier_at is used in <a href="#SP2_1">&#167;2.1</a>.</p>
<p class="inwebparagraph"><a id="SP2_4"></a><b>&#167;2.4. </b>With those preliminaries out of the way, the language's colouring program
takes over.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Now run the colouring program</span> <span class="cwebmacronumber">2.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">program</span><span class="plain">)</span>
<span class="functiontext">Painter::execute</span><span class="plain">(</span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">program</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">, </span><span class="identifier">painter_count</span><span class="plain">++);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP2">&#167;2</a>.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>The run-type for a block determines what the rules in it apply to: the
whole snippet of text, or each character on its own, or each run of characters
of a given sort. Note that we work width-first, as it were: we complete each
rule across the whole snippet before moving on to the next.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Painter::execute</span><span class="plain">(</span><span class="reserved">hash_table</span><span class="plain"> *</span><span class="identifier">HT</span><span class="plain">, </span><span class="reserved">colouring_language_block</span><span class="plain"> *</span><span class="identifier">block</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">matter</span><span class="plain">,</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">colouring</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">to</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">block</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no block"</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">colouring_at_start</span><span class="plain">);</span>
<span class="functiontext">Str::copy</span><span class="plain">(</span><span class="identifier">colouring_at_start</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">);</span>
<span class="reserved">colouring_rule</span><span class="plain"> *</span><span class="identifier">rule</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">rule</span><span class="plain">, </span><span class="reserved">colouring_rule</span><span class="plain">, </span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">rules</span><span class="plain">) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">run</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">WHOLE_LINE_CRULE_RUN:</span>
<span class="functiontext">Painter::execute_rule</span><span class="plain">(</span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">,</span>
<span class="plain">(</span><span class="identifier">N</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">)?1:</span><span class="identifier">N</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CHARACTERS_CRULE_RUN:</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="functiontext">Painter::execute_rule</span><span class="plain">(</span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">-</span><span class="identifier">from</span><span class="plain">+1);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">CHARACTERS_IN_CRULE_RUN:</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">count</span><span class="plain">=1, </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">=0; </span><span class="identifier">j</span><span class="plain">&lt;</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">char_set</span><span class="plain">); </span><span class="identifier">j</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) == </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">char_set</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">) ) {</span>
<span class="functiontext">Painter::execute_rule</span><span class="plain">(</span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">count</span><span class="plain">++);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">INSTANCES_CRULE_RUN:</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain"> = </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">run_instance</span><span class="plain">) - </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">count</span><span class="plain">=1, </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">to</span><span class="plain"> - </span><span class="identifier">L</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ACMESupport::text_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">run_instance</span><span class="plain">)) {</span>
<span class="functiontext">Painter::execute_rule</span><span class="plain">(</span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">L</span><span class="plain">, </span><span class="identifier">count</span><span class="plain">++);</span>
<span class="identifier">i</span><span class="plain"> += </span><span class="identifier">L</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">MATCHES_CRULE_RUN:</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">count</span><span class="plain">=1, </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">L</span><span class="plain"> = </span><span class="functiontext">Regexp::match_from</span><span class="plain">(&amp;(</span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">mr</span><span class="plain">), </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">match_regexp_text</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="functiontext">Painter::execute_rule</span><span class="plain">(</span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">+</span><span class="identifier">L</span><span class="plain">-1, </span><span class="identifier">count</span><span class="plain">++);</span>
<span class="identifier">i</span><span class="plain"> += </span><span class="identifier">L</span><span class="plain">-1;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">BRACKETS_CRULE_RUN:</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">MAX_BRACKETED_SUBEXPRESSIONS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])</span>
<span class="functiontext">Str::clear</span><span class="plain">(</span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;(</span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">mr</span><span class="plain">), </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">match_regexp_text</span><span class="plain">))</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">count</span><span class="plain">=1, </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="constant">MAX_BRACKETED_SUBEXPRESSIONS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="identifier">mr</span><span class="plain">.</span><span class="element">exp_at</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] &gt;= </span><span class="constant">0</span><span class="plain">)</span>
<span class="functiontext">Painter::execute_rule</span><span class="plain">(</span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">,</span>
<span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">mr</span><span class="plain">.</span><span class="identifier">exp_at</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">],</span>
<span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">mr</span><span class="plain">.</span><span class="identifier">exp_at</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] + </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">mr</span><span class="plain">.</span><span class="element">exp</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">])-1,</span>
<span class="identifier">count</span><span class="plain">++);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">default:</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ident_from</span><span class="plain"> = -1, </span><span class="identifier">count</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">col</span><span class="plain"> = </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">colouring_at_start</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">col</span><span class="plain"> == </span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">run</span><span class="plain">) ||</span>
<span class="plain">((</span><span class="identifier">block</span><span class="plain">-&gt;</span><span class="element">run</span><span class="plain"> == </span><span class="constant">UNQUOTED_COLOUR</span><span class="plain">) &amp;&amp;</span>
<span class="plain">((</span><span class="identifier">col</span><span class="plain"> != </span><span class="constant">STRING_COLOUR</span><span class="plain">) &amp;&amp; (</span><span class="identifier">col</span><span class="plain"> != </span><span class="constant">CHAR_LITERAL_COLOUR</span><span class="plain">)))) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ident_from</span><span class="plain"> == -1) </span><span class="identifier">ident_from</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ident_from</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">)</span>
<span class="functiontext">Painter::execute_rule</span><span class="plain">(</span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">ident_from</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">-1, </span><span class="identifier">count</span><span class="plain">++);</span>
<span class="identifier">ident_from</span><span class="plain"> = -1;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ident_from</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">)</span>
<span class="functiontext">Painter::execute_rule</span><span class="plain">(</span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">ident_from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">, </span><span class="identifier">count</span><span class="plain">++);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">colouring_at_start</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Painter::execute is used in <a href="#SP2_4">&#167;2.4</a>, <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>Rules have the form: if X, then Y.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Painter::execute_rule</span><span class="plain">(</span><span class="reserved">hash_table</span><span class="plain"> *</span><span class="identifier">HT</span><span class="plain">, </span><span class="reserved">colouring_rule</span><span class="plain"> *</span><span class="identifier">rule</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">matter</span><span class="plain">,</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">colouring</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">to</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Painter::satisfies</span><span class="plain">(</span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">) == </span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">sense</span><span class="plain">)</span>
<span class="functiontext">Painter::follow</span><span class="plain">(</span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Painter::execute_rule is used in <a href="#SP3">&#167;3</a>.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>Here we test the "if X":
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">UNSPACED_RULE_PREFIX</span><span class="plain"> </span><span class="constant">2</span><span class="plain"> </span><span class="comment">for <code class="display"><span class="extract">prefix P</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">SPACED_RULE_PREFIX</span><span class="plain"> </span><span class="constant">3</span><span class="plain"> </span><span class="comment">for <code class="display"><span class="extract">spaced prefix P</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">OPTIONALLY_SPACED_RULE_PREFIX</span><span class="plain"> </span><span class="constant">4</span><span class="plain"> </span><span class="comment">for <code class="display"><span class="extract">optionally spaced prefix P</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">UNSPACED_RULE_SUFFIX</span><span class="plain"> </span><span class="constant">5</span><span class="plain"> </span><span class="comment">for <code class="display"><span class="extract">suffix P</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">SPACED_RULE_SUFFIX</span><span class="plain"> </span><span class="constant">6</span><span class="plain"> </span><span class="comment">for <code class="display"><span class="extract">spaced suffix P</span></code></span>
<span class="definitionkeyword">define</span> <span class="constant">OPTIONALLY_SPACED_RULE_SUFFIX</span><span class="plain"> </span><span class="constant">7</span><span class="plain"> </span><span class="comment">for <code class="display"><span class="extract">optionally spaced suffix P</span></code></span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Painter::satisfies</span><span class="plain">(</span><span class="reserved">hash_table</span><span class="plain"> *</span><span class="identifier">HT</span><span class="plain">, </span><span class="reserved">colouring_rule</span><span class="plain"> *</span><span class="identifier">rule</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">matter</span><span class="plain">,</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">colouring</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">to</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="identifier">number</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="identifier">number_of</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="identifier">number</span><span class="plain"> != ((</span><span class="identifier">N</span><span class="plain">-1)%(</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">number_of</span><span class="plain">)) + </span><span class="constant">1</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="identifier">number</span><span class="plain"> != </span><span class="identifier">N</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_regexp_text</span><span class="plain">[0]) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">&lt;=</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++) </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">j</span><span class="plain">));</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rv</span><span class="plain"> = </span><span class="functiontext">Regexp::match</span><span class="plain">(&amp;(</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">mr</span><span class="plain">), </span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_regexp_text</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rv</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_text</span><span class="plain">) &gt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="identifier">match_prefix</span><span class="plain"> == </span><span class="constant">UNSPACED_RULE_PREFIX</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_prefix</span><span class="plain"> == </span><span class="constant">SPACED_RULE_PREFIX</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_prefix</span><span class="plain"> == </span><span class="constant">OPTIONALLY_SPACED_RULE_PREFIX</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pos</span><span class="plain"> = </span><span class="identifier">from</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="identifier">match_prefix</span><span class="plain"> != </span><span class="constant">UNSPACED_RULE_PREFIX</span><span class="plain">) {</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">pos</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">Characters::is_whitespace</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">-1))) </span><span class="identifier">pos</span><span class="plain">--;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="identifier">match_prefix</span><span class="plain"> == </span><span class="constant">SPACED_RULE_PREFIX</span><span class="plain">) &amp;&amp; (</span><span class="identifier">pos</span><span class="plain"> == </span><span class="identifier">from</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ACMESupport::text_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">,</span>
<span class="identifier">pos</span><span class="plain">-</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_text</span><span class="plain">), </span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_text</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">fix_position</span><span class="plain"> = </span><span class="identifier">pos</span><span class="plain">-</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_text</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_prefix</span><span class="plain"> == </span><span class="constant">UNSPACED_RULE_SUFFIX</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_prefix</span><span class="plain"> == </span><span class="constant">SPACED_RULE_SUFFIX</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_prefix</span><span class="plain"> == </span><span class="constant">OPTIONALLY_SPACED_RULE_SUFFIX</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pos</span><span class="plain"> = </span><span class="identifier">to</span><span class="plain"> + </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="identifier">match_prefix</span><span class="plain"> != </span><span class="constant">UNSPACED_RULE_SUFFIX</span><span class="plain">) {</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">pos</span><span class="plain"> &lt; </span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_text</span><span class="plain">)) &amp;&amp; (</span><span class="functiontext">Characters::is_whitespace</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">))) </span><span class="identifier">pos</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="identifier">match_prefix</span><span class="plain"> == </span><span class="constant">SPACED_RULE_SUFFIX</span><span class="plain">) &amp;&amp; (</span><span class="identifier">pos</span><span class="plain"> == </span><span class="identifier">from</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ACMESupport::text_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_text</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">fix_position</span><span class="plain"> = </span><span class="identifier">pos</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_text</span><span class="plain">) != </span><span class="identifier">to</span><span class="plain">-</span><span class="identifier">from</span><span class="plain">+1)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) != </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_text</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">-</span><span class="identifier">from</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_keyword_of_colour</span><span class="plain"> != </span><span class="constant">NOT_A_COLOUR</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">);</span>
<span class="functiontext">Str::substr</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">, </span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">), </span><span class="functiontext">Str::at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">+1));</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">rw</span><span class="plain"> = </span><span class="functiontext">Analyser::is_reserved_word</span><span class="plain">(</span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">id</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_keyword_of_colour</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rw</span><span class="plain"> == </span><span class="constant">FALSE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_colour</span><span class="plain"> != </span><span class="constant">NOT_A_COLOUR</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">) != </span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_colour</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Painter::satisfies is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>And here we carry out the "then Y":
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Painter::follow</span><span class="plain">(</span><span class="reserved">hash_table</span><span class="plain"> *</span><span class="identifier">HT</span><span class="plain">, </span><span class="reserved">colouring_rule</span><span class="plain"> *</span><span class="identifier">rule</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">matter</span><span class="plain">,</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">colouring</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">to</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="identifier">execute_block</span><span class="plain">)</span>
<span class="functiontext">Painter::execute</span><span class="plain">(</span><span class="identifier">HT</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">execute_block</span><span class="plain">, </span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">debug</span><span class="plain">) </span>&lt;<span class="cwebmacro">Print some debugging text</span> <span class="cwebmacronumber">6.1</span>&gt;
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="identifier">set_to_colour</span><span class="plain"> != </span><span class="constant">NOT_A_COLOUR</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="functiontext">Str::put_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">set_to_colour</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="identifier">set_prefix_to_colour</span><span class="plain"> != </span><span class="constant">NOT_A_COLOUR</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">fix_position</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">fix_position</span><span class="plain">+</span><span class="functiontext">Str::len</span><span class="plain">(</span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">match_text</span><span class="plain">); </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="functiontext">Str::put_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">rule</span><span class="plain">-&gt;</span><span class="element">set_prefix_to_colour</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Painter::follow is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP6_1"></a><b>&#167;6.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Print some debugging text</span> <span class="cwebmacronumber">6.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"[%d, %d] text: "</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">matter</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">));</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"\n[%d, %d] cols: "</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">&lt;=</span><span class="identifier">to</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="constant">STDOUT</span><span class="plain">, </span><span class="functiontext">Str::get_at</span><span class="plain">(</span><span class="identifier">colouring</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">));</span>
<span class="identifier">PRINT</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP6">&#167;6</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Painting a file. </b></p>
<pre class="display">
<span class="reserved">linked_list</span><span class="plain"> *</span><span class="functiontext">Painter::lines</span><span class="plain">(</span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">) {</span>
<span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain">);</span>
<span class="functiontext">TextFiles::read</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">, </span><span class="constant">FALSE</span><span class="plain">, </span><span class="string">"unable to read file of textual extract"</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">,</span>
<span class="plain">&amp;</span><span class="functiontext">Painter::text_file_helper</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain"> = -1, </span><span class="identifier">c</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">) {</span>
<span class="identifier">c</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::is_whitespace</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">) == </span><span class="constant">FALSE</span><span class="plain">)</span>
<span class="identifier">n</span><span class="plain"> = </span><span class="identifier">c</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">n</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">R</span><span class="plain"> = </span><span class="identifier">NEW_LINKED_LIST</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain">);</span>
<span class="identifier">c</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (++</span><span class="identifier">c</span><span class="plain"> &lt;= </span><span class="identifier">n</span><span class="plain">)</span>
<span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain">, </span><span class="identifier">R</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">R</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">L</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Painter::text_file_helper</span><span class="plain">(</span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">text</span><span class="plain">, </span><span class="reserved">text_file_position</span><span class="plain"> *</span><span class="identifier">tfp</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">state</span><span class="plain">) {</span>
<span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain"> = (</span><span class="reserved">linked_list</span><span class="plain"> *) </span><span class="identifier">state</span><span class="plain">;</span>
<span class="identifier">ADD_TO_LINKED_LIST</span><span class="plain">(</span><span class="functiontext">Str::duplicate</span><span class="plain">(</span><span class="identifier">text</span><span class="plain">), </span><span class="reserved">text_stream</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Painter::colour_file</span><span class="plain">(</span><span class="reserved">programming_language</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain">, </span><span class="reserved">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">coloured</span><span class="plain">) {</span>
<span class="reserved">linked_list</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain"> = </span><span class="functiontext">Painter::lines</span><span class="plain">(</span><span class="identifier">F</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain">) </span><span class="functiontext">Painter::reset_syntax_colouring</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="reserved">text_stream</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER_LINKED_LIST</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">text_stream</span><span class="plain">, </span><span class="identifier">L</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain">++ &gt; </span><span class="constant">1</span><span class="plain">) { </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">, </span><span class="character">'\n'</span><span class="plain">); </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">coloured</span><span class="plain">, </span><span class="constant">NEWLINE_COLOUR</span><span class="plain">); }</span>
<span class="functiontext">Str::trim_white_space_at_end</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">ST</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">SC</span><span class="plain">);</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">) == </span><span class="character">'\t'</span><span class="plain">)</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">ST</span><span class="plain">, </span><span class="string">" "</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">ST</span><span class="plain">, </span><span class="functiontext">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain">) {</span>
<span class="functiontext">Painter::syntax_colour</span><span class="plain">(</span><span class="identifier">pl</span><span class="plain">, (</span><span class="identifier">pl</span><span class="plain">)?(&amp;(</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="element">built_in_keywords</span><span class="plain">)):</span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">ST</span><span class="plain">, </span><span class="identifier">SC</span><span class="plain">, </span><span class="constant">TRUE</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">ST</span><span class="plain">)</span>
<span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">SC</span><span class="plain">, </span><span class="constant">PLAIN_COLOUR</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">, </span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">ST</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">coloured</span><span class="plain">, </span><span class="string">"%S"</span><span class="plain">, </span><span class="identifier">SC</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) { </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">, </span><span class="character">'\n'</span><span class="plain">); </span><span class="identifier">PUT_TO</span><span class="plain">(</span><span class="identifier">coloured</span><span class="plain">, </span><span class="constant">NEWLINE_COLOUR</span><span class="plain">); }</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Painter::lines is used in 2/tp (<a href="2-tp.html#SP1_1_6_7_2">&#167;1.1.6.7.2</a>).</p>
<p class="endnote">The function Painter::text_file_helper appears nowhere else.</p>
<p class="endnote">The function Painter::colour_file is used in 1/pc (<a href="1-pc.html#SP7_3">&#167;7.3</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="4-as.html">Back to 'ACME Support'</a></li><li><a href="4-cl.html">Continue with 'C-Like Languages'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>