1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/core-module/7-rs.html
2019-04-22 15:42:10 +01:00

2288 lines
244 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>7/oaf</title>
<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>
<!--Weave of '7/rs' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">core</a></li><li><a href="index.html#7">Chapter 7: Sentences</a></li><li><b>Rule Subtrees</b></li></ul><p class="purpose">To tidy up |INVOCATION_LIST_NT| nodes into a list of children under the relevant |ROUTINE_NT| node, and so turn each rule definition into a single subtree.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP7">&#167;7. Parsing Routine Structure</a></li><li><a href="#SP11">&#167;11. Basic Structural Syntax</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>Initially, the phrases (<code class="display"><span class="extract">INVOCATION_LIST_NT</span></code>) making up a rule (<code class="display"><span class="extract">ROUTINE_NT</span></code>) are
simply listed after it in the parse tree, but we want them to become its
children: this is the only thing the A-grammar does with rules, which
otherwise wait until later to be dealt with.
</p>
<p class="inwebparagraph">The single routine in this section accomplishes the regrouping: after it
runs, every <code class="display"><span class="extract">INVOCATION_LIST_NT</span></code> is a child of the <code class="display"><span class="extract">ROUTINE_NT</span></code> header to which it
belongs.
</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Certain phrases are "structural": otherwise, if, repeat, while and so
on. These have different expectations in terms of the layout of surrounding
phrases in rule or phrase definitions, and the following structure defines
the relevant behaviour. (The contents are static.)
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">control_structure_phrase</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">subordinate_to</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">indent_subblocks</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">body_empty_except_for_subordinates</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">used_at_stage</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">is_a_loop</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">requires_new_syntax</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">allow_run_on</span><span class="plain">;</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">keyword</span><span class="plain">;</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">control_structure_phrase</span><span class="plain">;</span>
<span class="reserved">control_structure_phrase</span>
<span class="plain">*</span><span class="identifier">switch_CSP</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="plain">*</span><span class="identifier">if_CSP</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="plain">*</span><span class="identifier">repeat_CSP</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="plain">*</span><span class="identifier">while_CSP</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="plain">*</span><span class="identifier">otherwise_CSP</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="plain">*</span><span class="identifier">abbreviated_otherwise_CSP</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="plain">*</span><span class="identifier">otherwise_if_CSP</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="plain">*</span><span class="identifier">default_case_CSP</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="plain">*</span><span class="identifier">case_CSP</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="plain">*</span><span class="identifier">say_CSP</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="plain">*</span><span class="identifier">now_CSP</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">,</span>
<span class="plain">*</span><span class="identifier">instead_CSP</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure control_structure_phrase is private to this section.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>This routine is used whenever new material is added. Whenever it finds a
childless <code class="display"><span class="extract">ROUTINE_NT</span></code> followed by a sequence of <code class="display"><span class="extract">INVOCATION_LIST_NT</span></code> nodes, it
joins these in sequence as children of the <code class="display"><span class="extract">ROUTINE_NT</span></code>. Since it always
acts so as to leave a non-zero number of children, and since it acts only
on childless nodes, it cannot ever act on the same node twice.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::register_recently_lexed_phrases</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; 0) </span><span class="reserved">return</span><span class="plain">; </span> <span class="comment">for then the tree is perhaps broken anyway</span>
<span class="identifier">ParseTree::traverse</span><span class="plain">(</span><span class="functiontext">Sentences::RuleSubtrees::demote_command_nodes</span><span class="plain">);</span>
<span class="identifier">ParseTree::traverse</span><span class="plain">(</span><span class="functiontext">Sentences::RuleSubtrees::detect_loose_command_nodes</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Sentences::RuleSubtrees::register_recently_lexed_phrases is used in 1/mr (<a href="1-mr.html#SP4_9">&#167;4.9</a>), 5/lp (<a href="5-lp.html#SP40">&#167;40</a>, <a href="5-lp.html#SP41">&#167;41</a>), 7/oaf (<a href="7-oaf.html#SP3">&#167;3</a>), 15/ma (<a href="15-ma.html#SP11_4">&#167;11.4</a>).</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>Command nodes are demoted to be children of routine nodes:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::demote_command_nodes</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == </span><span class="constant">ROUTINE_NT</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">end_def</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">end_def</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) &amp;&amp; (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">end_def</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) == </span><span class="constant">INVOCATION_LIST_NT</span><span class="plain">))</span>
<span class="identifier">end_def</span><span class="plain"> = </span><span class="identifier">end_def</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain"> == </span><span class="identifier">end_def</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">ROUTINE_NT</span></code> not followed by any <code class="display"><span class="extract">INVOCATION_LIST_NT</span></code>s</span>
<span class="comment">splice so that <code class="display"><span class="extract">p-&gt;next</span></code> to <code class="display"><span class="extract">end_def</span></code> become the children of <code class="display"><span class="extract">p</span></code>:</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">end_def</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="identifier">end_def</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="functiontext">Sentences::RuleSubtrees::parse_routine_structure</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Sentences::RuleSubtrees::demote_command_nodes is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b>And just in case:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::detect_loose_command_nodes</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == </span><span class="constant">INVOCATION_LIST_NT</span><span class="plain">)</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"loose COMMAND node outside of rule definition"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Sentences::RuleSubtrees::detect_loose_command_nodes is used in <a href="#SP4">&#167;4</a>.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Parsing Routine Structure. </b>There are now two possible syntaxes to express the structural makeup of a
routine. Traditional I7 syntax for blocks is to place them within begin/end
markers: the "begin" occurring at the end of the conditional or loop header,
and the "end if", "end while", etc., as a phrase of its own at the end of
the block. Newer I7 syntax (March 2008) is to use Python-style colons and
indentation. Both are allowed, but not in the same routine.
</p>
<p class="inwebparagraph">This routine opens with the routine's parse tree consisting of a simple
linked list of code-point nodes, one for each phrase. We must work out
which syntax is used, decipher it, and turn the list into a proper tree
structure in a single unified format.
</p>
<p class="inwebparagraph">How much simpler this would all be if we could abolish the old format, but
it's kept for the benefit of partially sighted users, who find tabbed
indentation difficult to manage with screen-readers.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::parse_routine_structure</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">routine_node</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">initial_problem_count</span><span class="plain"> = </span><span class="identifier">problem_count</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">uses_colon_syntax</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">uses_begin_end_syntax</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">mispunctuates_begin_end_syntax</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">requires_colon_syntax</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
&lt;<span class="cwebmacro">(a.1) See which block syntax is used by conditionals and loops</span> <span class="cwebmacronumber">7.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">(a.2) Report problems if the two syntaxes are mixed up with each other</span> <span class="cwebmacronumber">7.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">initial_problem_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">uses_colon_syntax</span><span class="plain">) </span>&lt;<span class="cwebmacro">(b.1) Annotate the parse tree with indentation levels</span> <span class="cwebmacronumber">7.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">(b.2) Annotate the parse tree with control structure usage</span> <span class="cwebmacronumber">7.4</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">(c) Expand comma notation for blocks</span> <span class="cwebmacronumber">7.5</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">initial_problem_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">uses_colon_syntax</span><span class="plain">) </span>&lt;<span class="cwebmacro">(d) Insert end nodes and check the indentation</span> <span class="cwebmacronumber">7.6</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">initial_problem_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
&lt;<span class="cwebmacro">(e) Structure the parse tree to match the use of control structures</span> <span class="cwebmacronumber">7.7</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">initial_problem_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
&lt;<span class="cwebmacro">(f) Police the structure of the parse tree</span> <span class="cwebmacronumber">7.8</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">initial_problem_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
&lt;<span class="cwebmacro">(g) Optimise out the otherwise if nodes</span> <span class="cwebmacronumber">7.9</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">initial_problem_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
&lt;<span class="cwebmacro">(h) Remove any end markers as no longer necessary</span> <span class="cwebmacronumber">7.11</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">initial_problem_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">uses_colon_syntax</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">(i) Remove any begin markers as no longer necessary</span> <span class="cwebmacronumber">7.13</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">(j) Insert code block nodes so that nodes needing to be parsed are childless</span> <span class="cwebmacronumber">7.15</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">(k) Insert instead marker nodes</span> <span class="cwebmacronumber">7.17</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">(l) Break up say phrases</span> <span class="cwebmacronumber">7.19</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Sentences::RuleSubtrees::parse_routine_structure is used in <a href="#SP5">&#167;5</a>, 17/ts (<a href="17-ts.html#SP11_1">&#167;11.1</a>).</p>
<p class="inwebparagraph"><a id="SP7_1"></a><b>&#167;7.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">(a.1) See which block syntax is used by conditionals and loops</span> <span class="cwebmacronumber">7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain"> =</span>
<span class="functiontext">Sentences::RuleSubtrees::detect_control_structure</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">syntax_used</span><span class="plain"> = </span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">colon_block_command_ANNOT</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">syntax_used</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) { </span> <span class="comment">i.e., doesn't end with a colon</span>
<span class="comment">don't count "if x is 1, let y be 2" &mdash; with no block &mdash; as deciding it</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(!(&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">beginning</span><span class="plain">-</span><span class="identifier">block</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)))))</span>
<span class="identifier">syntax_used</span><span class="plain"> = </span><span class="identifier">NOT_APPLICABLE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">syntax_used</span><span class="plain"> != </span><span class="identifier">NOT_APPLICABLE</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">syntax_used</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">uses_colon_syntax</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">uses_colon_syntax</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
&lt;<span class="cwebmacro">Note what looks like a begin-end piece of syntax</span> <span class="cwebmacronumber">7.1.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;requires_new_syntax</span><span class="plain">) &amp;&amp; (</span><span class="identifier">requires_colon_syntax</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">))</span>
<span class="identifier">requires_colon_syntax</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Sentences::RuleSubtrees::detect_end_control_structure</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">))) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">uses_begin_end_syntax</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="identifier">uses_begin_end_syntax</span><span class="plain"> = </span><span class="identifier">p</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="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_1_1"></a><b>&#167;7.1.1. </b>It's possible in oddball cases to mis-punctuate such as to fool us, so:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Note what looks like a begin-end piece of syntax</span> <span class="cwebmacronumber">7.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">uses_begin_end_syntax</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) &amp;&amp; (</span><span class="identifier">mispunctuates_begin_end_syntax</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">beginning</span><span class="plain">-</span><span class="identifier">block</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)))</span>
<span class="identifier">uses_begin_end_syntax</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="reserved">else</span>
<span class="identifier">mispunctuates_begin_end_syntax</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_1">&#167;7.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_2"></a><b>&#167;7.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">(a.2) Report problems if the two syntaxes are mixed up with each other</span> <span class="cwebmacronumber">7.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">uses_colon_syntax</span><span class="plain">) &amp;&amp; (</span><span class="identifier">mispunctuates_begin_end_syntax</span><span class="plain">)) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(2, </span><span class="identifier">mispunctuates_begin_end_syntax</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_BadOldSyntax</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The rule or phrase definition %1 seems to use indentation and "</span>
<span class="string">"colons to group phrases together into 'if', 'repeat' or 'while' "</span>
<span class="string">"blocks. That's fine, but then this phrase seems to be missing "</span>
<span class="string">"some punctuation - %2. Perhaps a colon is missing?"</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">uses_colon_syntax</span><span class="plain">) &amp;&amp; (</span><span class="identifier">uses_begin_end_syntax</span><span class="plain">)) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(2, </span><span class="identifier">uses_colon_syntax</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(3, </span><span class="identifier">uses_begin_end_syntax</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_BothBlockSyntaxes</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The rule or phrase definition %1 seems to use both ways of grouping "</span>
<span class="string">"phrases together into 'if', 'repeat' and 'while' blocks at once. "</span>
<span class="string">"Inform allows two alternative forms, but they cannot be mixed in "</span>
<span class="string">"the same definition. %POne way is to end the 'if', 'repeat' or "</span>
<span class="string">"'while' phrases with a 'begin', and then to match that with an "</span>
<span class="string">"'end if' or similar. ('Otherwise' or 'otherwise if' clauses are "</span>
<span class="string">"phrases like any other, and end with semicolons in this case.) "</span>
<span class="string">"You use this begin/end form here, for instance - %3. %P"</span>
<span class="string">"The other way is to end with a colon ':' and then indent the "</span>
<span class="string">"subsequent phrases underneath, using tabs. (Note that any "</span>
<span class="string">"'otherwise' or 'otherwise if' clauses also have to end with "</span>
<span class="string">"colons in this case.) You use this indented form here - %2."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">requires_colon_syntax</span><span class="plain">) &amp;&amp; (</span><span class="identifier">uses_begin_end_syntax</span><span class="plain">)) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(2, </span><span class="identifier">requires_colon_syntax</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_NotInOldSyntax</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The construction %2, in the rule or phrase definition %1, "</span>
<span class="string">"is only allowed if the rule is written in the 'new' format, "</span>
<span class="string">"that is, with the phrases written one to a line with "</span>
<span class="string">"indentation showing how they are grouped together, and "</span>
<span class="string">"with colons indicating the start of such a group."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_3"></a><b>&#167;7.3. </b>If we're using Pythonesque notation, then the number of tab stops of
indentation of a phrase tells us where it belongs in the structure, so
we mark up the tree with that information.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">(b.1) Annotate the parse tree with indentation levels</span> <span class="cwebmacronumber">7.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">routine_node</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">,</span>
<span class="identifier">Lexer::indentation_level</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">routine_node</span><span class="plain">))));</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</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">Lexer::indentation_level</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)));</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">, </span><span class="identifier">I</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_4"></a><b>&#167;7.4. </b>Note that we are a little cautious about recognising phrases which will
open blocks, such as "repeat...", because of the dangers of false positives;
so we look for the "begin" keyword, or the colon. We're less cautious with
subordinate phrases (such as "otherwise") because we know their wonding
more certainly, and similarly for "end X" phrases.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">(b.2) Annotate the parse tree with control structure usage</span> <span class="cwebmacronumber">7.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain">;</span>
<span class="identifier">csp</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::detect_control_structure</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">colon_block_command_ANNOT</span><span class="plain">)) ||</span>
<span class="plain">(&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">beginning</span><span class="plain">-</span><span class="identifier">block</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">))) ||</span>
<span class="plain">(</span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain">)) {</span>
<span class="identifier">ParseTree::set_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">csp</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">case_CSP</span><span class="plain">) </span>&lt;<span class="cwebmacro">Trim a switch case to just the case value</span> <span class="cwebmacronumber">7.4.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">csp</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::detect_end_control_structure</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain">) </span><span class="identifier">ParseTree::set_end_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">csp</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_4_1"></a><b>&#167;7.4.1. </b>At this point anything at all can be a case value: it won't be parsed
or type-checked until compilation.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Trim a switch case to just the case value</span> <span class="cwebmacronumber">7.4.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="identifier">control</span><span class="plain">-</span><span class="identifier">structure</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt;, 1));</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_4">&#167;7.4</a>.</p>
<p class="inwebparagraph"><a id="SP7_5"></a><b>&#167;7.5. </b>"Comma notation" is when a comma is used in an "if" statement to divide
off only a single consequential phrase, as in
</p>
<blockquote>
<p>if the hat is worn, try dropping the hat;</p>
</blockquote>
<p class="inwebparagraph">Such a line occupies a single node in its routine's parse tree, and we need
to break this up.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">(c) Expand comma notation for blocks</span> <span class="cwebmacronumber">7.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain">;</span>
<span class="identifier">csp</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::detect_control_structure</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">if_CSP</span><span class="plain">) &amp;&amp; (&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">with</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">notation</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">))))</span>
&lt;<span class="cwebmacro">Effect a comma expansion</span> <span class="cwebmacronumber">7.5.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_5_1"></a><b>&#167;7.5.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Effect a comma expansion</span> <span class="cwebmacronumber">7.5.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">BCW</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">with</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">notation</span><span class="plain">&gt;, 1); </span> <span class="comment">text before the comma</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">ACW</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">with</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">notation</span><span class="plain">&gt;, 2); </span> <span class="comment">text after the comma</span>
<span class="comment">First trim and annotate the "if ..." part</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">colon_block_command_ANNOT</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">); </span> <span class="comment">it previously had no colon...</span>
<span class="identifier">ParseTree::set_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">csp</span><span class="plain">); </span> <span class="comment">...and therefore didn't have its CSP set</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">BCW</span><span class="plain">);</span>
<span class="comment">Now make a new node for the "then" part, indenting it one step inward</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">then_node</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">INVOCATION_LIST_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">then_node</span><span class="plain">, </span><span class="constant">results_from_splitting_ANNOT</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">then_node</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">,</span>
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">) + 1);</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">then_node</span><span class="plain">, </span><span class="identifier">ACW</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">last_node_of_if_construction</span><span class="plain"> = </span><span class="identifier">then_node</span><span class="plain">, *</span><span class="identifier">rest_of_routine</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="comment">Attach the "then" node after the "if" node:</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">then_node</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Deal with an immediately following otherwise node, if there is one</span> <span class="cwebmacronumber">7.5.1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">uses_colon_syntax</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">last_node_of_if_construction</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::end_node</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">last_node_of_if_construction</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">rest_of_routine</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">last_node_of_if_construction</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">rest_of_routine</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_5">&#167;7.5</a>.</p>
<p class="inwebparagraph"><a id="SP7_5_1_1"></a><b>&#167;7.5.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Deal with an immediately following otherwise node, if there is one</span> <span class="cwebmacronumber">7.5.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">rest_of_routine</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">uses_colon_syntax</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">) ==</span>
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">rest_of_routine</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">))) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">rest_of_routine</span><span class="plain">) == </span><span class="identifier">otherwise_CSP</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Deal with an immediately following otherwise</span> <span class="cwebmacronumber">7.5.1.1.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Sentences::RuleSubtrees::abbreviated_otherwise</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">rest_of_routine</span><span class="plain">)))</span>
&lt;<span class="cwebmacro">Deal with an abbreviated otherwise node</span> <span class="cwebmacronumber">7.5.1.1.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_5_1">&#167;7.5.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_5_1_1_1"></a><b>&#167;7.5.1.1.1. </b>We string a plain "otherwise" node onto the "if" construction.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Deal with an immediately following otherwise</span> <span class="cwebmacronumber">7.5.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">then_node</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">rest_of_routine</span><span class="plain">;</span>
<span class="identifier">last_node_of_if_construction</span><span class="plain"> = </span><span class="identifier">last_node_of_if_construction</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="identifier">rest_of_routine</span><span class="plain"> = </span><span class="identifier">rest_of_routine</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_5_1_1">&#167;7.5.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_5_1_1_2"></a><b>&#167;7.5.1.1.2. </b>An abbreviated otherwise clause looks like this:
</p>
<blockquote>
<p>otherwise award 4 points;</p>
</blockquote>
<p class="inwebparagraph">and we want to split this, too, into distinct nodes.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Deal with an abbreviated otherwise node</span> <span class="cwebmacronumber">7.5.1.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">otherwise_node</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">CODE_BLOCK_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">otherwise_node</span><span class="plain">, </span><span class="constant">results_from_splitting_ANNOT</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">otherwise_node</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">,</span>
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">));</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">otherwise_node</span><span class="plain">,</span>
<span class="identifier">Wordings::one_word</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">rest_of_routine</span><span class="plain">)))); </span> <span class="comment">extract just the word "otherwise"</span>
<span class="identifier">ParseTree::set_control_structure_used</span><span class="plain">(</span><span class="identifier">otherwise_node</span><span class="plain">, </span><span class="identifier">otherwise_CSP</span><span class="plain">);</span>
<span class="identifier">then_node</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">otherwise_node</span><span class="plain">;</span>
<span class="identifier">otherwise_node</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">rest_of_routine</span><span class="plain">;</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">rest_of_routine</span><span class="plain">,</span>
<span class="identifier">Wordings::trim_first_word</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">rest_of_routine</span><span class="plain">))); </span> <span class="comment">to remove the "otherwise"</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">rest_of_routine</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">,</span>
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">rest_of_routine</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">) + 1);</span>
<span class="identifier">last_node_of_if_construction</span><span class="plain"> = </span><span class="identifier">rest_of_routine</span><span class="plain">;</span>
<span class="identifier">rest_of_routine</span><span class="plain"> = </span><span class="identifier">rest_of_routine</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_5_1_1">&#167;7.5.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_6"></a><b>&#167;7.6. </b>If the old-style syntax is used, there are explicit "end if", "end repeat"
and "end while" nodes in the list already. But if the Pythonesque syntax is
used then we need to create these nodes and insert them into the list; we
do these by reading off the structure from the pattern of indentation. It's
quite a long task, since this pattern may contain errors, which we have to
report more or less helpfully.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">(d) Insert end nodes and check the indentation</span> <span class="cwebmacronumber">7.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">, *</span><span class="identifier">prev</span><span class="plain">, *</span><span class="identifier">run_on_at</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">first_misaligned_phrase</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">first_overindented_phrase</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain">, </span><span class="identifier">indent</span><span class="plain">, </span><span class="identifier">expected_indent</span><span class="plain"> = 1, </span><span class="identifier">indent_misalign</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">indent_overmuch</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">,</span>
<span class="identifier">just_opened_block</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="comment">the blocks open stack holds blocks currently open</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">blstack_opening_phrase</span><span class="plain">[</span><span class="identifier">GROSS_AMOUNT_OF_INDENTATION</span><span class="plain">+1];</span>
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">blstack_construct</span><span class="plain">[</span><span class="identifier">GROSS_AMOUNT_OF_INDENTATION</span><span class="plain">+1];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">blstack_stage</span><span class="plain">[</span><span class="identifier">GROSS_AMOUNT_OF_INDENTATION</span><span class="plain">+1];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">blo_sp</span><span class="plain"> = 0, </span><span class="identifier">suppress_further_problems</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">routine_node</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">) != 0)</span>
&lt;<span class="cwebmacro">Issue problem message for failing to start flush on the left margin</span> <span class="cwebmacronumber">7.6.1</span>&gt;<span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">prev</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">=1; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">prev</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">++) {</span>
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain"> = </span><span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Determine actual indentation of this phrase</span> <span class="cwebmacronumber">7.6.2</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Compare actual indentation to what we expect from structure so far</span> <span class="cwebmacronumber">7.6.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Insert begin marker and increase expected indentation if a block begins here</span> <span class="cwebmacronumber">7.6.4</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">indent</span><span class="plain"> = 1;</span>
&lt;<span class="cwebmacro">Try closing blocks to bring expected indentation down to match</span> <span class="cwebmacronumber">7.6.5</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">indent_overmuch</span><span class="plain">) </span>&lt;<span class="cwebmacro">Issue problem message for an excess of indentation</span> <span class="cwebmacronumber">7.6.7</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">run_on_at</span><span class="plain">) </span>&lt;<span class="cwebmacro">Issue problem message for run-ons within phrase definition</span> <span class="cwebmacronumber">7.6.8</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">indent_misalign</span><span class="plain">) </span>&lt;<span class="cwebmacro">Issue problem message for misaligned indentation</span> <span class="cwebmacronumber">7.6.6</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_1"></a><b>&#167;7.6.1. </b>Controversially:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem message for failing to start flush on the left margin</span> <span class="cwebmacronumber">7.6.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source_eliding_begin</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_NonflushRule</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The phrase or rule definition %1 is written using tab indentations "</span>
<span class="string">"to show how its phrases are to be grouped together. But in that "</span>
<span class="string">"case the opening line needs to be on the left margin, not indented."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="identifier">suppress_further_problems</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6">&#167;7.6</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_2"></a><b>&#167;7.6.2. </b>Here we set <code class="display"><span class="extract">indent</span></code> to the number of tab-stops in from the margin, or to
<code class="display"><span class="extract">expected_indent</span></code> if the text does not appear to be at the start of its own
line in the source (because it runs on from a previous phrase, in
which case we set the <code class="display"><span class="extract">run_on_at</span></code> flag: except for following on from cases
in switches with a non-control-structure, which is allowed, because otherwise
the lines often look silly and short).
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Determine actual indentation of this phrase</span> <span class="cwebmacronumber">7.6.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">indent</span><span class="plain"> = </span><span class="identifier">expected_indent</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">) &gt; 0)</span>
<span class="identifier">indent</span><span class="plain"> = </span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</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">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">))) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">Lexer::break_before</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)))) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">n</span><span class="character">'</span><span class="plain">: </span><span class="identifier">indent</span><span class="plain"> = 0; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'\</span><span class="plain">t</span><span class="character">'</span><span class="plain">: </span><span class="identifier">indent</span><span class="plain"> = 1; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">prev</span><span class="plain">) &amp;&amp; (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">pcsp</span><span class="plain"> = </span><span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">prev</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pcsp</span><span class="plain">) &amp;&amp; (</span><span class="identifier">pcsp</span><span class="plain">-</span><span class="element">&gt;allow_run_on</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">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">results_from_splitting_ANNOT</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">run_on_at</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="identifier">run_on_at</span><span class="plain"> = </span><span class="identifier">p</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">indent</span><span class="plain"> &gt;= </span><span class="identifier">GROSS_AMOUNT_OF_INDENTATION</span><span class="plain">) </span>&lt;<span class="cwebmacro">Record an excess of indentation</span> <span class="cwebmacronumber">7.6.2.1</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6">&#167;7.6</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_3"></a><b>&#167;7.6.3. </b>We now know the <code class="display"><span class="extract">indent</span></code> level of the line as read, and also the
<code class="display"><span class="extract">expected_indent</span></code> given the definition so far. If they agree, fine. If they
don't agree, it isn't necessarily bad news &mdash; if each line's indentation were
a function of the last, there would be no information in it, after all.
Roughly speaking, when <code class="display"><span class="extract">indent</span></code> is greater than we expect, that must be
wrong &mdash; it means indentation has jumped inward as if to open a new block,
but blocks are opened explicitly and not by simply raising the indent.
But when <code class="display"><span class="extract">indent</span></code> is less than we expect, this may simply mean that the
current block(s) has or have been closed, because blocks are indeed closed
implicitly just by moving the indentation back in.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compare actual indentation to what we expect from structure so far</span> <span class="cwebmacronumber">7.6.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">indent</span><span class="plain"> == 0) {</span>
&lt;<span class="cwebmacro">Record a misalignment of indentation</span> <span class="cwebmacronumber">7.6.3.3</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Record a phrase within current block</span> <span class="cwebmacronumber">7.6.3.2</span>&gt;<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">csp</span><span class="plain">) &amp;&amp; (</span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain">)) {</span>
&lt;<span class="cwebmacro">Compare actual indentation to what we expect for an intermediate phrase</span> <span class="cwebmacronumber">7.6.3.1</span>&gt;<span class="plain">;</span>
<span class="identifier">just_opened_block</span><span class="plain"> = </span><span class="identifier">TRUE</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">expected_indent</span><span class="plain"> &lt; </span><span class="identifier">indent</span><span class="plain">) </span>&lt;<span class="cwebmacro">Record a misalignment of indentation</span> <span class="cwebmacronumber">7.6.3.3</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">expected_indent</span><span class="plain"> &gt; </span><span class="identifier">indent</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Try closing blocks to bring expected indentation down to match</span> <span class="cwebmacronumber">7.6.5</span>&gt;<span class="plain">;</span>
<span class="identifier">expected_indent</span><span class="plain"> = </span><span class="identifier">indent</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Record a phrase within current block</span> <span class="cwebmacronumber">7.6.3.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">expected_indent</span><span class="plain"> &lt; 1) </span><span class="identifier">expected_indent</span><span class="plain"> = 1;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6">&#167;7.6</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_3_1"></a><b>&#167;7.6.3.1. </b>This is a small variation used for an intermediate phrase like "otherwise".
These are required to be at the same indentation as the line which opened the
block, rather than being one tab step in from there: in other words they are
not deemed part of the block itself. They can also occur in "stages", which
is a way to enforce one intermediate phrase only being allowed after another
one &mdash; for instance, "otherwise if..." is not allowed after an "otherwise"
within an "if".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Compare actual indentation to what we expect for an intermediate phrase</span> <span class="cwebmacronumber">7.6.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">expected_indent</span><span class="plain">--;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">expected_indent</span><span class="plain"> &lt; </span><span class="identifier">indent</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Issue problem for an intermediate phrase not matching</span> <span class="cwebmacronumber">7.6.3.1.1</span>&gt;<span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
&lt;<span class="cwebmacro">Try closing blocks to bring expected indentation down to match</span> <span class="cwebmacronumber">7.6.5</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">blo_sp</span><span class="plain"> == 0) ||</span>
<span class="plain">(</span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain"> != </span><span class="identifier">blstack_construct</span><span class="plain">[</span><span class="identifier">blo_sp</span><span class="plain">-1])) {</span>
&lt;<span class="cwebmacro">Issue problem for an intermediate phrase not matching</span> <span class="cwebmacronumber">7.6.3.1.1</span>&gt;<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">blstack_stage</span><span class="plain">[</span><span class="identifier">blo_sp</span><span class="plain">-1] &gt; </span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;used_at_stage</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue problem for an intermediate phrase out of sequence</span> <span class="cwebmacronumber">7.6.3.1.2</span>&gt;<span class="plain">;</span>
<span class="identifier">blstack_stage</span><span class="plain">[</span><span class="identifier">blo_sp</span><span class="plain">-1] = </span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;used_at_stage</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">expected_indent</span><span class="plain">++;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6_3">&#167;7.6.3</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_4"></a><b>&#167;7.6.4. </b>In colon syntax, blocks are explicitly opened; they are only implicitly
closed. Here is the opening:
</p>
<p class="inwebparagraph">If <code class="display"><span class="extract">p</span></code> is a node representing a phrase beginning a block, and we're in the
colon syntax, then it is followed by a word which is the colon: thus if <code class="display"><span class="extract">p</span></code>
reads "if x is 2" then the word following the "2" will be ":".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Insert begin marker and increase expected indentation if a block begins here</span> <span class="cwebmacronumber">7.6.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">csp</span><span class="plain">) &amp;&amp; (</span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) &amp;&amp; (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">colon_block_command_ANNOT</span><span class="plain">))) {</span>
<span class="identifier">expected_indent</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;indent_subblocks</span><span class="plain">) </span><span class="identifier">expected_indent</span><span class="plain">++;</span>
<span class="identifier">blstack_construct</span><span class="plain">[</span><span class="identifier">blo_sp</span><span class="plain">] = </span><span class="identifier">csp</span><span class="plain">;</span>
<span class="identifier">blstack_stage</span><span class="plain">[</span><span class="identifier">blo_sp</span><span class="plain">] = 0;</span>
<span class="identifier">blstack_opening_phrase</span><span class="plain">[</span><span class="identifier">blo_sp</span><span class="plain">++] = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="identifier">just_opened_block</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6">&#167;7.6</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_5"></a><b>&#167;7.6.5. </b>Now for the closing of colon-syntax blocks. We know that blocks must be
being closed if the indentation has jumped backwards: but it may be that many
blocks are being closed at once. (It may also be that the indentation has
gone awry.)
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Try closing blocks to bring expected indentation down to match</span> <span class="cwebmacronumber">7.6.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">just_opened_block</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">blo_sp</span><span class="plain"> &gt; 0) &amp;&amp;</span>
<span class="plain">(!(</span><span class="identifier">blstack_construct</span><span class="plain">[</span><span class="identifier">blo_sp</span><span class="plain">-1]-</span><span class="element">&gt;body_empty_except_for_subordinates</span><span class="plain">)) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Issue problem for an empty block</span> <span class="cwebmacronumber">7.6.5.2</span>&gt;<span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">indent</span><span class="plain"> &lt; </span><span class="identifier">expected_indent</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">opening</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">blo_sp</span><span class="plain"> == 0) {</span>
&lt;<span class="cwebmacro">Record a misalignment of indentation</span> <span class="cwebmacronumber">7.6.3.3</span>&gt;<span class="plain">;</span>
<span class="identifier">indent</span><span class="plain"> = </span><span class="identifier">expected_indent</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">blstack_construct</span><span class="plain">[</span><span class="identifier">blo_sp</span><span class="plain">-1]-</span><span class="element">&gt;body_empty_except_for_subordinates</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">expected_indent</span><span class="plain"> - </span><span class="identifier">indent</span><span class="plain"> == 1)) {</span>
<span class="identifier">indent</span><span class="plain"> = </span><span class="identifier">expected_indent</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">expected_indent</span><span class="plain">--;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">blstack_construct</span><span class="plain">[</span><span class="identifier">blo_sp</span><span class="plain">-1]-</span><span class="element">&gt;indent_subblocks</span><span class="plain">) </span><span class="identifier">expected_indent</span><span class="plain">--;</span>
<span class="identifier">opening</span><span class="plain"> = </span><span class="identifier">blstack_opening_phrase</span><span class="plain">[--</span><span class="identifier">blo_sp</span><span class="plain">];</span>
&lt;<span class="cwebmacro">Insert end marker to match the opening of the block phrase</span> <span class="cwebmacronumber">7.6.5.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6">&#167;7.6</a>, <a href="#SP7_6_3">&#167;7.6.3</a>, <a href="#SP7_6_3_1">&#167;7.6.3.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_3_2"></a><b>&#167;7.6.3.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Record a phrase within current block</span> <span class="cwebmacronumber">7.6.3.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">blo_sp</span><span class="plain"> &gt; 0) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">blstack_stage</span><span class="plain">[</span><span class="identifier">blo_sp</span><span class="plain">-1] == 0) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">blstack_construct</span><span class="plain">[</span><span class="identifier">blo_sp</span><span class="plain">-1]-</span><span class="element">&gt;body_empty_except_for_subordinates</span><span class="plain">)) {</span>
&lt;<span class="cwebmacro">Issue problem for non-case in a switch</span> <span class="cwebmacronumber">7.6.3.2.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">just_opened_block</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6_3">&#167;7.6.3</a> (twice).</p>
<p class="inwebparagraph"><a id="SP7_6_5_1"></a><b>&#167;7.6.5.1. </b>An end marker is a phrase like "end if" which matches the "if... begin"
above it: here we insert such a marker at a place where the source text
indentation implicitly requires it.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Insert end marker to match the opening of the block phrase</span> <span class="cwebmacronumber">7.6.5.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">implicit_end</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::end_node</span><span class="plain">(</span><span class="identifier">opening</span><span class="plain">);</span>
<span class="identifier">implicit_end</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">prev</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">; </span><span class="identifier">prev</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">implicit_end</span><span class="plain">;</span>
<span class="identifier">prev</span><span class="plain"> = </span><span class="identifier">implicit_end</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6_5">&#167;7.6.5</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_3_3"></a><b>&#167;7.6.3.3. </b>Here we throw what amounts to an exception...
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Record a misalignment of indentation</span> <span class="cwebmacronumber">7.6.3.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">indent_misalign</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first_misaligned_phrase</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">first_misaligned_phrase</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6_3">&#167;7.6.3</a> (twice), <a href="#SP7_6_5">&#167;7.6.5</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_6"></a><b>&#167;7.6.6. </b>...and catch it with something of a catch-all message:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem message for misaligned indentation</span> <span class="cwebmacronumber">7.6.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">suppress_further_problems</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">routine_node</span><span class="plain">);</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source_eliding_begin</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source_eliding_begin</span><span class="plain">(2, </span><span class="identifier">first_misaligned_phrase</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_MisalignedIndentation</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The phrase or rule definition %1 is written using the 'colon "</span>
<span class="string">"and indentation' syntax for its 'if's, 'repeat's and 'while's, "</span>
<span class="string">"where blocks of phrases grouped together are indented one "</span>
<span class="string">"tab step inward from the 'if ...:' or similar phrase to which "</span>
<span class="string">"they belong. But the tabs here seem to be misaligned, and I can't "</span>
<span class="string">"determine the structure. The first phrase going awry in the "</span>
<span class="string">"definition seems to be %2, in case that helps. %PThis sometimes "</span>
<span class="string">"happens even when the code looks about right, to the eye, if rows "</span>
<span class="string">"of spaces have been used to indent phrases instead of tabs."</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::diagnose_further</span><span class="plain">();</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6">&#167;7.6</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_2_1"></a><b>&#167;7.6.2.1. </b>And another...
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Record an excess of indentation</span> <span class="cwebmacronumber">7.6.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">indent_overmuch</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first_overindented_phrase</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">first_overindented_phrase</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6_2">&#167;7.6.2</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_7"></a><b>&#167;7.6.7. </b>...caught here:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem message for an excess of indentation</span> <span class="cwebmacronumber">7.6.7</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">suppress_further_problems</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source_eliding_begin</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source_eliding_begin</span><span class="plain">(2, </span><span class="identifier">first_overindented_phrase</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TooMuchIndentation</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The phrase or rule definition %1 is written using tab indentations "</span>
<span class="string">"to show how its phrases are to be grouped together. But the level "</span>
<span class="string">"of indentation goes far too deep, reaching more than 25 tab stops "</span>
<span class="string">"from the left margin."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6">&#167;7.6</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_8"></a><b>&#167;7.6.8. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem message for run-ons within phrase definition</span> <span class="cwebmacronumber">7.6.8</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">suppress_further_problems</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source_eliding_begin</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source_eliding_begin</span><span class="plain">(2, </span><span class="identifier">run_on_at</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_RunOnsInTabbedRoutine</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The phrase or rule definition %1 is written using the 'colon "</span>
<span class="string">"and indentation' syntax for its 'if's, 'repeat's and 'while's, "</span>
<span class="string">"but that's only allowed if each phrase in the definition "</span>
<span class="string">"occurs on its own line. So phrases like %2, which follow "</span>
<span class="string">"directly on from the previous phrase, aren't allowed."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6">&#167;7.6</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_5_2"></a><b>&#167;7.6.5.2. </b>It's a moot point whether the following should be incorrect syntax, but it
far more often happens as an accident than anything else, and it's hard to
think of a sensible use.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem for an empty block</span> <span class="cwebmacronumber">7.6.5.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">suppress_further_problems</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">routine_node</span><span class="plain">);</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source_eliding_begin</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source_eliding_begin</span><span class="plain">(2, </span><span class="identifier">prev</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source_eliding_begin</span><span class="plain">(3, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EmptyIndentedBlock</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The phrase or rule definition %1 is written using the 'colon "</span>
<span class="string">"and indentation' syntax for its 'if's, 'repeat's and 'while's, "</span>
<span class="string">"where blocks of phrases grouped together are indented one "</span>
<span class="string">"tab step inward from the 'if ...:' or similar phrase to which "</span>
<span class="string">"they belong. But the phrase %2, which ought to begin a block, "</span>
<span class="string">"is immediately followed by %3 at the same or a lower indentation, "</span>
<span class="string">"so the block seems to be empty - this must mean there has been "</span>
<span class="string">"a mistake in indenting the phrases."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6_5">&#167;7.6.5</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_3_2_1"></a><b>&#167;7.6.3.2.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem for non-case in a switch</span> <span class="cwebmacronumber">7.6.3.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">suppress_further_problems</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">;</span>
<span class="identifier">Problems::quote_source_eliding_begin</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source_eliding_begin</span><span class="plain">(2, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_NonCaseInIf</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In the phrase or rule definition %1, the phrase %2 came as a "</span>
<span class="string">"surprise since it was not a case in an 'if X is...' but was "</span>
<span class="string">"instead some other miscellaneous instruction."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6_3_2">&#167;7.6.3.2</a>.</p>
<p class="inwebparagraph"><a id="SP7_6_3_1_1"></a><b>&#167;7.6.3.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem for an intermediate phrase not matching</span> <span class="cwebmacronumber">7.6.3.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">indent_misalign</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">suppress_further_problems</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain"> == </span><span class="identifier">if_CSP</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">routine_node</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_MisalignedOtherwise</span><span class="plain">),</span>
<span class="string">"this doesn't match a corresponding 'if'"</span><span class="plain">,</span>
<span class="string">"as it must. An 'otherwise' must be vertically underneath the "</span>
<span class="string">"'if' to which it corresponds, at the same indentation, and "</span>
<span class="string">"if the 'otherwise' uses a colon to begin a block then the "</span>
<span class="string">"'if' must do the same."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain"> == </span><span class="identifier">switch_CSP</span><span class="plain">)</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_MisalignedCase</span><span class="plain">),</span>
<span class="string">"this seems to be misplaced since it is not a case within an "</span>
<span class="string">"'if X is...'"</span><span class="plain">,</span>
<span class="string">"as it must be. Each case must be placed one tab stop in from "</span>
<span class="string">"the 'if X is...' to which it belongs, and the instructions "</span>
<span class="string">"for what to do in that case should be one tab stop further in "</span>
<span class="string">"still."</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6_3_1">&#167;7.6.3.1</a> (twice).</p>
<p class="inwebparagraph"><a id="SP7_6_3_1_2"></a><b>&#167;7.6.3.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem for an intermediate phrase out of sequence</span> <span class="cwebmacronumber">7.6.3.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">indent_misalign</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">suppress_further_problems</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">default_case_CSP</span><span class="plain">) || (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">case_CSP</span><span class="plain">))</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_DefaultCaseNotLast</span><span class="plain">),</span>
<span class="string">"'otherwise' must be the last clause if an 'if ... is:'"</span><span class="plain">,</span>
<span class="string">"and in particular it has to come after all the '-- V:' "</span>
<span class="string">"case values supplied."</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_MisarrangedOtherwise</span><span class="plain">),</span>
<span class="string">"this seems to be misplaced since it is out of sequence within its 'if'"</span><span class="plain">,</span>
<span class="string">"with an 'otherwise if...' coming after the more general 'otherwise' "</span>
<span class="string">"rather than before. (Note that an 'otherwise' or 'otherwise if' must "</span>
<span class="string">"be vertically underneath the 'if' to which it corresponds, at the "</span>
<span class="string">"same indentation."</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_6_3_1">&#167;7.6.3.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_7"></a><b>&#167;7.7. </b>And after all that work, the routine's parse tree still consists only of a
linked list of nodes; but at least it now contains the same pattern of nodes
whichever syntax is used. We finally make a meaningful tree out of it.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">(e) Structure the parse tree to match the use of control structures</span> <span class="cwebmacronumber">7.7</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">routine_list</span><span class="plain"> = </span><span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">top_level</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">CODE_BLOCK_NT</span><span class="plain">);</span>
<span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">top_level</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">attach_owners</span><span class="plain">[</span><span class="constant">MAX_BLOCK_NESTING</span><span class="plain">+1];</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">attach_points</span><span class="plain">[</span><span class="constant">MAX_BLOCK_NESTING</span><span class="plain">+1];</span>
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">attach_csps</span><span class="plain">[</span><span class="constant">MAX_BLOCK_NESTING</span><span class="plain">+1];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">attach_point_sp</span><span class="plain"> = 0;</span>
<span class="comment">push the top level code block onto the stack</span>
<span class="identifier">attach_owners</span><span class="plain">[</span><span class="identifier">attach_point_sp</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">attach_csps</span><span class="plain">[</span><span class="identifier">attach_point_sp</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">attach_points</span><span class="plain">[</span><span class="identifier">attach_point_sp</span><span class="plain">++] = </span><span class="identifier">top_level</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">overflow_point</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">if any overflow is found</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">routine_list</span><span class="plain">, *</span><span class="identifier">pn_prev</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn_prev</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="comment">unstring this node from the old list</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn_prev</span><span class="plain">) </span><span class="identifier">pn_prev</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Attach the node to the routine's growing parse tree</span> <span class="cwebmacronumber">7.7.1</span>&gt;<span class="character">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">overflow_point</span><span class="plain">) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">overflow_point</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_BlockNestingTooDeep</span><span class="plain">),</span>
<span class="string">"compound phrases have gone too deep"</span><span class="plain">,</span>
<span class="string">"perhaps because many have begun but not been properly ended?"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_7_1"></a><b>&#167;7.7.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Attach the node to the routine's growing parse tree</span> <span class="cwebmacronumber">7.7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">go_up</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">go_down</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain"> = </span><span class="identifier">ParseTree::get_end_control_structure_used</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain">) </span><span class="identifier">go_up</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">csp</span><span class="plain"> = </span><span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain">) {</span>
<span class="identifier">go_down</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Sentences::RuleSubtrees::opens_block</span><span class="plain">(</span><span class="identifier">csp</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">go_up</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">ParseTree::set_type</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="constant">CODE_BLOCK_NT</span><span class="plain">);</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">go_up</span><span class="plain">) </span>&lt;<span class="cwebmacro">Move the attachment point up in the tree</span> <span class="cwebmacronumber">7.7.1.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Attach this latest node</span> <span class="cwebmacronumber">7.7.1.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">go_down</span><span class="plain">) </span>&lt;<span class="cwebmacro">Move the attachment point down in the tree</span> <span class="cwebmacronumber">7.7.1.3</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_7">&#167;7.7</a>.</p>
<p class="inwebparagraph"><a id="SP7_7_1_1"></a><b>&#167;7.7.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Move the attachment point up in the tree</span> <span class="cwebmacronumber">7.7.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">superior_csp</span><span class="plain"> = </span><span class="identifier">attach_csps</span><span class="plain">[</span><span class="identifier">attach_point_sp</span><span class="plain">-1];</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">superior_csp</span><span class="plain">) &amp;&amp; (</span><span class="identifier">superior_csp</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain">)) </span>&lt;<span class="cwebmacro">Pop the CSP stack</span> <span class="cwebmacronumber">7.7.1.1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">go_down</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span>&lt;<span class="cwebmacro">Pop the CSP stack</span> <span class="cwebmacronumber">7.7.1.1.1</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_7_1">&#167;7.7.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_7_1_2"></a><b>&#167;7.7.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Attach this latest node</span> <span class="cwebmacronumber">7.7.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain"> = </span><span class="identifier">attach_points</span><span class="plain">[</span><span class="identifier">attach_point_sp</span><span class="plain">-1];</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">go_up</span><span class="plain">) &amp;&amp; (</span><span class="identifier">go_down</span><span class="plain">) &amp;&amp; (</span><span class="identifier">attach_owners</span><span class="plain">[</span><span class="identifier">attach_point_sp</span><span class="plain">-1]))</span>
<span class="identifier">to</span><span class="plain"> = </span><span class="identifier">attach_owners</span><span class="plain">[</span><span class="identifier">attach_point_sp</span><span class="plain">-1];</span>
<span class="identifier">ParseTree::graft</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_7_1">&#167;7.7.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_7_1_3"></a><b>&#167;7.7.1.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Move the attachment point down in the tree</span> <span class="cwebmacronumber">7.7.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">next_attach_point</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">go_up</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">CODE_BLOCK_NT</span><span class="plain">);</span>
<span class="identifier">next_attach_point</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Push the CSP stack</span> <span class="cwebmacronumber">7.7.1.3.1</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_7_1">&#167;7.7.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_7_1_1_1"></a><b>&#167;7.7.1.1.1. </b>It's an error to let this underflow, but we'll catch that problem later.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Pop the CSP stack</span> <span class="cwebmacronumber">7.7.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">attach_point_sp</span><span class="plain"> != 1) </span><span class="identifier">attach_point_sp</span><span class="plain">--;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_7_1_1">&#167;7.7.1.1</a> (twice).</p>
<p class="inwebparagraph"><a id="SP7_7_1_3_1"></a><b>&#167;7.7.1.3.1. </b>An overflow, however, we must catch right here.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Push the CSP stack</span> <span class="cwebmacronumber">7.7.1.3.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">attach_point_sp</span><span class="plain"> &lt;= </span><span class="constant">MAX_BLOCK_NESTING</span><span class="plain">) {</span>
<span class="identifier">attach_owners</span><span class="plain">[</span><span class="identifier">attach_point_sp</span><span class="plain">] = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="identifier">attach_csps</span><span class="plain">[</span><span class="identifier">attach_point_sp</span><span class="plain">] = </span><span class="identifier">csp</span><span class="plain">;</span>
<span class="identifier">attach_points</span><span class="plain">[</span><span class="identifier">attach_point_sp</span><span class="plain">++] = </span><span class="identifier">next_attach_point</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">overflow_point</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">overflow_point</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_7_1_3">&#167;7.7.1.3</a>.</p>
<p class="inwebparagraph"><a id="SP7_8"></a><b>&#167;7.8. </b>We now have a neatly structured tree, so from here on anything we do will
need a recursive procedure.
</p>
<p class="inwebparagraph">Firstly, the tree is certainly neat, but it can still contain all kinds
of nonsense: "if" blocks with multiple "otherwise"s, for example. This is
where we look for such mistakes.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">(f) Police the structure of the parse tree</span> <span class="cwebmacronumber">7.8</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain"> = </span><span class="identifier">problem_count</span><span class="plain">;</span>
<span class="functiontext">Sentences::RuleSubtrees::police_code_block</span><span class="plain">(</span><span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">n</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Local parse tree: $T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">routine_node</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>Which recursively uses the following:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::police_code_block</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">block</span><span class="plain">, </span><span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">context</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">block</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, *</span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">prior</span><span class="plain"> =</span>
<span class="plain">(</span><span class="identifier">prev_p</span><span class="plain">)?</span><span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">prev_p</span><span class="plain">):</span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain"> = </span><span class="identifier">ParseTree::get_end_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">csp</span><span class="plain">) &amp;&amp; (</span><span class="identifier">csp</span><span class="plain"> != </span><span class="identifier">prior</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prior</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span>&lt;<span class="cwebmacro">Issue problem for end without begin</span> <span class="cwebmacronumber">8.1</span>&gt;
<span class="reserved">else</span><span class="plain"> </span>&lt;<span class="cwebmacro">Issue problem for wrong sort of end</span> <span class="cwebmacronumber">8.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">csp</span><span class="plain"> = </span><span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Sentences::RuleSubtrees::opens_block</span><span class="plain">(</span><span class="identifier">csp</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">ParseTree::get_end_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) == </span><span class="identifier">NULL</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Issue problem for begin without end</span> <span class="cwebmacronumber">8.3</span>&gt;<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">context</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Choose a problem for a loose clause</span> <span class="cwebmacronumber">8.4</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">context</span><span class="plain"> != </span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Choose a problem for the wrong clause</span> <span class="cwebmacronumber">8.5</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">otherwise_CSP</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Choose a problem for otherwise not occurring last</span> <span class="cwebmacronumber">8.6</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">default_case_CSP</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Issue a problem for the default case not occurring last</span> <span class="cwebmacronumber">8.7</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) </span><span class="functiontext">Sentences::RuleSubtrees::police_code_block</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">csp</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Sentences::RuleSubtrees::police_code_block is used in <a href="#SP7_8">&#167;7.8</a>.</p>
<p class="inwebparagraph"><a id="SP8_1"></a><b>&#167;8.1. </b>These used to be much-seen problem messages, until Inform moved to Pythonesque
structure-by-indentation. Nowadays "end if", "end while" and such are
automatically inserted into the stream of commands, always in the right place,
and always passing these checks. But the problem messages are kept for the sake
of old-format source text, and for refuseniks.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem for end without begin</span> <span class="cwebmacronumber">8.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::Issue::sentence_problem_with_note</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EndWithoutBegin</span><span class="plain">),</span>
<span class="string">"this is an 'end' with no matching 'begin'"</span><span class="plain">,</span>
<span class="string">"which should not happen: every phrase like 'if ... begin;' "</span>
<span class="string">"should eventually be followed by its bookend 'end if'. "</span>
<span class="string">"It makes no sense to have an 'end ...' on its own."</span><span class="plain">,</span>
<span class="string">"Perhaps the problem is actually that you opened several "</span>
<span class="string">"such begin... end 'blocks' and accidentally closed them "</span>
<span class="string">"once too many? This is very easily done."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_2"></a><b>&#167;8.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem for wrong sort of end</span> <span class="cwebmacronumber">8.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wide_text</span><span class="plain">(2, </span><span class="identifier">prior</span><span class="plain">-</span><span class="element">&gt;keyword</span><span class="plain">);</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(3, </span><span class="identifier">prev_p</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_WrongEnd</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but the end I was expecting next was 'end %2', "</span>
<span class="string">"finishing the block you began with %3."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_3"></a><b>&#167;8.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem for begin without end</span> <span class="cwebmacronumber">8.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_BeginWithoutEnd</span><span class="plain">),</span>
<span class="string">"the definition of the phrase ended with no matching 'end' for "</span>
<span class="string">"this 'begin'"</span><span class="plain">,</span>
<span class="string">"bearing in mind that every begin must have a matching end, and "</span>
<span class="string">"that the one most recently begun must be the one first to end. For "</span>
<span class="string">"instance, 'if ... begin' must have a matching 'end if'."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_4"></a><b>&#167;8.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Choose a problem for a loose clause</span> <span class="cwebmacronumber">8.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">otherwise_CSP</span><span class="plain">)</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_OtherwiseWithoutIf</span><span class="plain">),</span>
<span class="string">"this is an 'else' or 'otherwise' with no matching 'if' (or 'unless')"</span><span class="plain">,</span>
<span class="string">"which must be wrong."</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">csp</span><span class="plain"> == </span><span class="identifier">otherwise_if_CSP</span><span class="plain">)</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_OtherwiseIfMisplaced</span><span class="plain">),</span>
<span class="string">"the 'otherwise if' clause here seems not to be occurring inside "</span>
<span class="string">"a large 'if'"</span><span class="plain">,</span>
<span class="string">"and seems to be freestanding instead. (Though 'otherwise ...' can "</span>
<span class="string">"usually be used after simple one-line 'if's to provide an alternative "</span>
<span class="string">"course of action, 'otherwise if...' is a different matter, and is "</span>
<span class="string">"used to divide up larger-scale instructions.)"</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">),</span>
<span class="string">"this clause can't occur outside of a control phrase"</span><span class="plain">,</span>
<span class="string">"which suggests that the structure of this routine is wrong."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_5"></a><b>&#167;8.5. </b><code class="display">
&lt;<span class="cwebmacrodefn">Choose a problem for the wrong clause</span> <span class="cwebmacronumber">8.5</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">otherwise_CSP</span><span class="plain">) || (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">otherwise_if_CSP</span><span class="plain">)) {</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wide_text</span><span class="plain">(2, </span><span class="identifier">context</span><span class="plain">-</span><span class="element">&gt;keyword</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_OtherwiseInNonIf</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"The %1 here did not make sense inside a "</span>
<span class="string">"'%2' structure: it's provided for 'if' (or 'unless')."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">} </span><span class="reserved">else</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">),</span>
<span class="string">"this clause is wrong for the phrase containing it"</span><span class="plain">,</span>
<span class="string">"which suggests that the structure of this routine is wrong."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_6"></a><b>&#167;8.6. </b><code class="display">
&lt;<span class="cwebmacrodefn">Choose a problem for otherwise not occurring last</span> <span class="cwebmacronumber">8.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">doubled</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">oi</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p2</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">; </span><span class="identifier">p2</span><span class="plain">; </span><span class="identifier">p2</span><span class="plain"> = </span><span class="identifier">p2</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">p2</span><span class="plain">) == </span><span class="identifier">otherwise_CSP</span><span class="plain">) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">p2</span><span class="plain">;</span>
<span class="identifier">doubled</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">p2</span><span class="plain">) == </span><span class="identifier">otherwise_if_CSP</span><span class="plain">)</span>
<span class="identifier">oi</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">doubled</span><span class="plain">)</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_DoubleOtherwise</span><span class="plain">),</span>
<span class="string">"that makes two unconditional 'otherwise' or 'else' clauses "</span>
<span class="string">"for this 'if'"</span><span class="plain">,</span>
<span class="string">"which is forbidden since 'otherwise' is meant to be a single "</span>
<span class="string">"(optional) catch-all clause at the end."</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">oi</span><span class="plain">)</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_OtherwiseIfAfterOtherwise</span><span class="plain">),</span>
<span class="string">"this seems to be misplaced since it is out of sequence within its 'if'"</span><span class="plain">,</span>
<span class="string">"with an 'otherwise if...' coming after the more general 'otherwise' "</span>
<span class="string">"rather than before. (If there's an 'otherwise' clause, it has to be "</span>
<span class="string">"the last clause of the 'if'.)"</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">),</span>
<span class="string">"'otherwise' must be the last clause"</span><span class="plain">,</span>
<span class="string">"but it seems not to be."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_7"></a><b>&#167;8.7. </b>This shouldn't happen because the switch construct requires Python syntax
and the structure of that was checked at indentation time, but just in case.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue a problem for the default case not occurring last</span> <span class="cwebmacronumber">8.7</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">),</span>
<span class="string">"'otherwise' must be the last clause"</span><span class="plain">,</span>
<span class="string">"which must be wrong."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP7_9"></a><b>&#167;7.9. </b>The tree is now known to be correctly structured, and there are no possible
problem messages left to issue. It's therefore safe to begin rearranging it.
We'll first eliminate one whole construction: "otherwise if whatever: ..."
can now become "otherwise: if whatever: ...".
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">(g) Optimise out the otherwise if nodes</span> <span class="cwebmacronumber">7.9</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">n</span><span class="plain"> = </span><span class="identifier">problem_count</span><span class="plain">;</span>
<span class="functiontext">Sentences::RuleSubtrees::purge_otherwise_if</span><span class="plain">(</span><span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">n</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Local parse tree: $T\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">routine_node</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_10"></a><b>&#167;7.10. </b>We made a similar manoeuvre above, but for one-line "otherwise do something"
phrases following one-line "if", not for the wider case of "otherwise if". We
didn't handle this back then because to do so would have made it impossible
to issue good problem messages for failures to use "otherwise if" correctly.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::purge_otherwise_if</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">block</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">block</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, *</span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">) == </span><span class="identifier">otherwise_if_CSP</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">former_contents</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">former_successors</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="comment">put an otherwise node in the position previously occupied by p</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">otherwise_node</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">CODE_BLOCK_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_control_structure_used</span><span class="plain">(</span><span class="identifier">otherwise_node</span><span class="plain">, </span><span class="identifier">otherwise_CSP</span><span class="plain">);</span>
<span class="comment">extract just the word "otherwise"</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">otherwise_node</span><span class="plain">, </span><span class="identifier">Wordings::one_word</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">))));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prev_p</span><span class="plain">) </span><span class="identifier">prev_p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">otherwise_node</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">block</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">otherwise_node</span><span class="plain">;</span>
<span class="comment">move p to below the otherwise node</span>
<span class="identifier">otherwise_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="identifier">ParseTree::set_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">INVOCATION_LIST_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">if_CSP</span><span class="plain">);</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">Wordings::trim_first_word</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)));</span>
<span class="comment">put the code previously under p under a new code block node under p</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">CODE_BLOCK_NT</span><span class="plain">);</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">former_contents</span><span class="plain">;</span>
<span class="comment">any further "otherwise if" or "otherwise" nodes after p follow</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">former_successors</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) </span><span class="functiontext">Sentences::RuleSubtrees::purge_otherwise_if</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Sentences::RuleSubtrees::purge_otherwise_if is used in <a href="#SP7_9">&#167;7.9</a>.</p>
<p class="inwebparagraph"><a id="SP7_11"></a><b>&#167;7.11. </b>End nodes are now redundant: maybe they got here as explicit "end if" phrases
in the source text, or maybe they were auto-inserted by the indentation reader,
but now that the structure is known to be correct they serve no further purpose.
We remove them.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">(h) Remove any end markers as no longer necessary</span> <span class="cwebmacronumber">7.11</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Sentences::RuleSubtrees::purge_end_markers</span><span class="plain">(</span><span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_12"></a><b>&#167;7.12. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::purge_end_markers</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">block</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">block</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, *</span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_end_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prev_p</span><span class="plain">) </span><span class="identifier">prev_p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">block</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) </span><span class="functiontext">Sentences::RuleSubtrees::purge_end_markers</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Sentences::RuleSubtrees::purge_end_markers is used in <a href="#SP7_11">&#167;7.11</a>.</p>
<p class="inwebparagraph"><a id="SP7_13"></a><b>&#167;7.13. </b>The "begin" keyword at the end of control constructs in the old-style syntax
can now be removed, too.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">(i) Remove any begin markers as no longer necessary</span> <span class="cwebmacronumber">7.13</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Sentences::RuleSubtrees::purge_begin_markers</span><span class="plain">(</span><span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_14"></a><b>&#167;7.14. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::purge_begin_markers</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">block</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">block</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, *</span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">))</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">beginning</span><span class="plain">-</span><span class="identifier">block</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)))</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">beginning</span><span class="plain">-</span><span class="identifier">block</span><span class="plain">&gt;, 1));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) </span><span class="functiontext">Sentences::RuleSubtrees::purge_begin_markers</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Sentences::RuleSubtrees::purge_begin_markers is used in <a href="#SP7_13">&#167;7.13</a>.</p>
<p class="inwebparagraph"><a id="SP7_15"></a><b>&#167;7.15. </b>This all makes a nice tree, but it has the defect that the statements heading
block-opening phrases (the ifs, whiles, repeats) have child nodes (the blocks
of code consequent on them). We want them to be leaves for now, so that we
can append statement-parsing data underneath them later. So we insert blank
code block nodes to mark these phrases, and transfer the control structure
annotations to them.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">(j) Insert code block nodes so that nodes needing to be parsed are childless</span> <span class="cwebmacronumber">7.15</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Sentences::RuleSubtrees::insert_cb_nodes</span><span class="plain">(</span><span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_16"></a><b>&#167;7.16. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::insert_cb_nodes</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">block</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">block</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, *</span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Sentences::RuleSubtrees::opens_block</span><span class="plain">(</span><span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">))) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">blank_cb_node</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">CODE_BLOCK_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_control_structure_used</span><span class="plain">(</span><span class="identifier">blank_cb_node</span><span class="plain">,</span>
<span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="identifier">ParseTree::set_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">blank_cb_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="identifier">blank_cb_node</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">;</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prev_p</span><span class="plain">) </span><span class="identifier">prev_p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">blank_cb_node</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">block</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">blank_cb_node</span><span class="plain">;</span>
<span class="identifier">p</span><span class="plain"> = </span><span class="identifier">blank_cb_node</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) </span><span class="functiontext">Sentences::RuleSubtrees::insert_cb_nodes</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Sentences::RuleSubtrees::insert_cb_nodes is used in <a href="#SP7_15">&#167;7.15</a>.</p>
<p class="inwebparagraph"><a id="SP7_17"></a><b>&#167;7.17. </b>Now:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">(k) Insert instead marker nodes</span> <span class="cwebmacronumber">7.17</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Sentences::RuleSubtrees::read_instead_markers</span><span class="plain">(</span><span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_18"></a><b>&#167;7.18. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::read_instead_markers</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">block</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">block</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, *</span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">instead</span><span class="plain">-</span><span class="identifier">keyword</span><span class="plain">&gt;(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">))) {</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="identifier">instead</span><span class="plain">-</span><span class="identifier">keyword</span><span class="plain">&gt;, 1));</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">instead_node</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">CODE_BLOCK_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_control_structure_used</span><span class="plain">(</span><span class="identifier">instead_node</span><span class="plain">, </span><span class="identifier">instead_CSP</span><span class="plain">);</span>
<span class="identifier">instead_node</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">instead_node</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) </span><span class="functiontext">Sentences::RuleSubtrees::read_instead_markers</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Sentences::RuleSubtrees::read_instead_markers is used in <a href="#SP7_17">&#167;7.17</a>.</p>
<p class="inwebparagraph"><a id="SP7_19"></a><b>&#167;7.19. </b>Now:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">(l) Break up say phrases</span> <span class="cwebmacronumber">7.19</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Sentences::RuleSubtrees::break_up_says</span><span class="plain">(</span><span class="identifier">routine_node</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::break_up_says</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">block</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">block</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">, *</span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">prev_p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">sf</span><span class="plain"> = </span><span class="constant">NO_SIGF</span><span class="plain">;</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="constant">from_text_substitution_ANNOT</span><span class="plain">)) </span><span class="identifier">sf</span><span class="plain"> = </span><span class="constant">SAY_SIGF</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">other</span><span class="plain">-</span><span class="identifier">significant</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="identifier">sf</span><span class="plain"> = &lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt;; </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="identifier">other</span><span class="plain">-</span><span class="identifier">significant</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt;, 1);</span>
<span class="plain">}</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">sf</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">SAY_SIGF</span><span class="plain">: {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">blank_cb_node</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">CODE_BLOCK_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_control_structure_used</span><span class="plain">(</span><span class="identifier">blank_cb_node</span><span class="plain">, </span><span class="identifier">say_CSP</span><span class="plain">);</span>
<span class="identifier">blank_cb_node</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">blank_cb_node</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">));</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prev_p</span><span class="plain">) </span><span class="identifier">prev_p</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">blank_cb_node</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">block</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">blank_cb_node</span><span class="plain">;</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">;</span>
<span class="functiontext">Sentences::RuleSubtrees::unroll_says</span><span class="plain">(</span><span class="identifier">blank_cb_node</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, 0);</span>
<span class="identifier">p</span><span class="plain"> = </span><span class="identifier">blank_cb_node</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="constant">NOW_SIGF</span><span class="plain">: {</span>
<span class="identifier">ParseTree::set_control_structure_used</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">now_CSP</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">cond_node</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">CONDITION_CONTEXT_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">cond_node</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain"> = </span><span class="identifier">cond_node</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">p</span><span class="plain">-</span><span class="element">&gt;down</span><span class="plain">) </span><span class="functiontext">Sentences::RuleSubtrees::break_up_says</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::unroll_says</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">cb_node</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">depth</span><span class="plain">) {</span>
<span class="reserved">while</span><span class="plain"> (&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">with</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">notation</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">AW</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">with</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">notation</span><span class="plain">&gt;, 1);</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">BW</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">with</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">notation</span><span class="plain">&gt;, 2);</span>
<span class="identifier">W</span><span class="plain"> = </span><span class="identifier">AW</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Bite off a say term</span> <span class="cwebmacronumber">9.1</span>&gt;<span class="plain">;</span>
<span class="identifier">W</span><span class="plain"> = </span><span class="identifier">BW</span><span class="plain">;</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Bite off a say term</span> <span class="cwebmacronumber">9.1</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Sentences::RuleSubtrees::break_up_says is used in <a href="#SP7_19">&#167;7.19</a>.</p>
<p class="endnote">The function Sentences::RuleSubtrees::unroll_says is used in <a href="#SP9_1">&#167;9.1</a>.</p>
<p class="inwebparagraph"><a id="SP9_1"></a><b>&#167;9.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Bite off a say term</span> <span class="cwebmacronumber">9.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Wordings::length</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">) &gt; 1) || (</span><span class="identifier">Wide::cmp</span><span class="plain">(</span><span class="identifier">Lexer::word_text</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)), </span><span class="identifier">L</span><span class="string">"\</span><span class="plain">"</span><span class="string">\</span><span class="plain">"</span><span class="string">"</span><span class="plain">) != 0)) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Wordings::length</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">) == 1) &amp;&amp; (</span><span class="identifier">Vocabulary::test_flags</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">), </span><span class="identifier">TEXTWITHSUBS_MC</span><span class="plain">)) &amp;&amp; (</span><span class="identifier">depth</span><span class="plain"> == 0)) {</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">));</span>
&lt;<span class="cwebmacro">Check that substitution does not contain suspicious punctuation</span> <span class="cwebmacronumber">9.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">A</span><span class="plain"> = </span><span class="identifier">Feeds::feed_text_expanding_strings</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">verify</span><span class="plain">-</span><span class="identifier">expanded</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">substitution</span><span class="plain">&gt;(</span><span class="identifier">A</span><span class="plain">))</span>
<span class="functiontext">Sentences::RuleSubtrees::unroll_says</span><span class="plain">(</span><span class="identifier">cb_node</span><span class="plain">, </span><span class="identifier">A</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">+1);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">say_term_node</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">INVOCATION_LIST_SAY_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">say_term_node</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">ParseTree::graft</span><span class="plain">(</span><span class="identifier">say_term_node</span><span class="plain">, </span><span class="identifier">cb_node</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="#SP9">&#167;9</a> (twice).</p>
<p class="inwebparagraph"><a id="SP9_1_1"></a><b>&#167;9.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Check that substitution does not contain suspicious punctuation</span> <span class="cwebmacronumber">9.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain">, </span><span class="identifier">sqb</span><span class="plain"> = 0;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain">=0; </span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">]; </span><span class="identifier">k</span><span class="plain">++) {</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">]) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">'['</span><span class="plain">: </span><span class="identifier">sqb</span><span class="plain">++; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sqb</span><span class="plain"> &gt; 1) </span>&lt;<span class="cwebmacro">Issue problem message for nested substitution</span> <span class="cwebmacronumber">9.1.1.2</span>&gt;<span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">']'</span><span class="plain">: </span><span class="identifier">sqb</span><span class="plain">--; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sqb</span><span class="plain"> &lt; 0) </span>&lt;<span class="cwebmacro">Issue problem message for unopened substitution</span> <span class="cwebmacronumber">9.1.1.4</span>&gt;<span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">':'</span><span class="plain">: </span><span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">k</span><span class="plain">&gt;0) &amp;&amp; (</span><span class="identifier">Characters::isdigit</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">-1])) &amp;&amp; (</span><span class="identifier">Characters::isdigit</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</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="character">';'</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sqb</span><span class="plain"> &gt; 0) </span>&lt;<span class="cwebmacro">Issue PM_TSWithPunctuation problem</span> <span class="cwebmacronumber">9.1.1.6</span>&gt;<span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="character">','</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sqb</span><span class="plain"> &gt; 0) </span>&lt;<span class="cwebmacro">Issue problem message for comma in a substitution</span> <span class="cwebmacronumber">9.1.1.1</span>&gt;<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">sqb</span><span class="plain"> != 0) </span>&lt;<span class="cwebmacro">Issue problem message for unclosed substitution</span> <span class="cwebmacronumber">9.1.1.3</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9_1">&#167;9.1</a>.</p>
<p class="inwebparagraph"><a id="SP9_1_1_1"></a><b>&#167;9.1.1.1. </b>And the more specialised:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem message for comma in a substitution</span> <span class="cwebmacronumber">9.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TSWithComma</span><span class="plain">),</span>
<span class="string">"a substitution contains a comma ','"</span><span class="plain">,</span>
<span class="string">"which is against the rules, because 'say' is a special phrase in "</span>
<span class="string">"which the comma divides items in a list of things to say, and so it "</span>
<span class="string">"loses its ordinary meanings. Because of this, no text substitution "</span>
<span class="string">"can contain a comma. "</span>
<span class="string">"(If you're trying to use a value produced by a phrase with a phrase "</span>
<span class="string">"option - say 'the best route from A to B, using even locked doors' - "</span>
<span class="string">"you'll need to put this in a 'let' variable first and then say that, "</span>
<span class="string">"or else define a better text substitution to do the job for you.)"</span><span class="plain">);</span>
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9_1_1">&#167;9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP9_1_1_2"></a><b>&#167;9.1.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem message for nested substitution</span> <span class="cwebmacronumber">9.1.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">+1] == </span><span class="character">'u'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">+2] == </span><span class="character">'n'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">+3] == </span><span class="character">'i'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">+4] == </span><span class="character">'c'</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">+5] == </span><span class="character">'o'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">+6] == </span><span class="character">'d'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">+7] == </span><span class="character">'e'</span><span class="plain">) &amp;&amp; (</span><span class="identifier">p</span><span class="plain">[</span><span class="identifier">k</span><span class="plain">+8] == </span><span class="character">' '</span><span class="plain">)) {</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_NestedUSubstitution</span><span class="plain">),</span>
<span class="string">"the text here contains one substitution '[...]' inside another"</span><span class="plain">,</span>
<span class="string">"which is not allowed. Actually, it looks as if you might have got "</span>
<span class="string">"into this by typing an exotic character as part of the name of a "</span>
<span class="string">"text substitution - those get rewritten automatically as '[unicode N]' "</span>
<span class="string">"for the appropriate Unicode character code number N. Either way - "</span>
<span class="string">"this isn't allowed."</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_NestedSubstitution</span><span class="plain">),</span>
<span class="string">"the text here contains one substitution '[...]' inside another"</span><span class="plain">,</span>
<span class="string">"which is not allowed. (If you just wanted a literal open and closed "</span>
<span class="string">"square bracket, use '[bracket]' and '[close bracket]'.)"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9_1_1">&#167;9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP9_1_1_3"></a><b>&#167;9.1.1.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem message for unclosed substitution</span> <span class="cwebmacronumber">9.1.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_UnclosedSubstitution</span><span class="plain">),</span>
<span class="string">"the text here uses an open square bracket '[', which opens a substitution "</span>
<span class="string">"in the text, but doesn't close it again"</span><span class="plain">,</span>
<span class="string">"so that the result is malformed. (If you just wanted a literal open "</span>
<span class="string">"square bracket, use '[bracket]'.)"</span><span class="plain">);</span>
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9_1_1">&#167;9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP9_1_1_4"></a><b>&#167;9.1.1.4. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue problem message for unopened substitution</span> <span class="cwebmacronumber">9.1.1.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_UnopenedSubstitution</span><span class="plain">),</span>
<span class="string">"the text here uses a close square bracket ']', which closes a substitution "</span>
<span class="string">"in the text, but never actually opened it"</span><span class="plain">,</span>
<span class="string">"with a matching '['. (If you just wanted a literal close square bracket, "</span>
<span class="string">"use '[close bracket]'.)"</span><span class="plain">);</span>
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9_1_1">&#167;9.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP9_1_1_5"></a><b>&#167;9.1.1.5. </b>Something devious happens when production (b) of &lt;s-say-phrase&gt; is matched.
Double-quoted text is literal if it contains no square brackets, but is
expanded if it includes text substitutions in squares. When (b) matches,
Inform expands a text such as
</p>
<blockquote>
<p>"Look, [the noun] said."</p>
</blockquote>
<p class="inwebparagraph">into:
</p>
<blockquote>
<p>"Look, ", the noun, " said."</p>
</blockquote>
<p class="inwebparagraph">and then re-parses the result with the following nonterminal; note that we
make sure commas are used correctly before handing back to &lt;s-say-phrase&gt;
to parse the list.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">verify</span><span class="plain">-</span><span class="identifier">expanded</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">substitution</span><span class="plain">&gt; ::=</span>
<span class="plain">*** . *** | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_TSWithPunctuation problem</span> <span class="cwebmacronumber">9.1.1.6</span>&gt;<span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FAIL_NONTERMINAL</span>
<span class="plain">, *** | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_EmptySubstitution problem</span> <span class="cwebmacronumber">9.1.1.5.1</span>&gt;<span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FAIL_NONTERMINAL</span>
<span class="plain">*** , | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_EmptySubstitution problem</span> <span class="cwebmacronumber">9.1.1.5.1</span>&gt;<span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FAIL_NONTERMINAL</span>
<span class="plain">*** , , *** | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_EmptySubstitution problem</span> <span class="cwebmacronumber">9.1.1.5.1</span>&gt;<span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FAIL_NONTERMINAL</span>
<span class="plain">...</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP9_1_1_6"></a><b>&#167;9.1.1.6. </b>So now just the problem messages:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_TSWithPunctuation problem</span> <span class="cwebmacronumber">9.1.1.6</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TSWithPunctuation</span><span class="plain">),</span>
<span class="string">"a substitution contains a '.', ':' or ';'"</span><span class="plain">,</span>
<span class="string">"which suggests that a close square bracket ']' may have gone astray."</span><span class="plain">);</span>
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9_1_1">&#167;9.1.1</a>, <a href="#SP9_1_1_5">&#167;9.1.1.5</a>.</p>
<p class="inwebparagraph"><a id="SP9_1_1_5_1"></a><b>&#167;9.1.1.5.1. </b>And:
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_EmptySubstitution problem</span> <span class="cwebmacronumber">9.1.1.5.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_EmptySubstitution</span><span class="plain">),</span>
<span class="string">"the text here contains an empty substitution '[]'"</span><span class="plain">,</span>
<span class="string">"which is not allowed. To say nothing - well, say nothing."</span><span class="plain">);</span>
<span class="identifier">it_is_not_worth_adding</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP9_1_1_5">&#167;9.1.1.5</a> (three times).</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>That just leaves one utility routine, for manufacturing end nodes which
match a given begin node.
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">Sentences::RuleSubtrees::end_node</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">opening</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">implicit_end</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="constant">INVOCATION_LIST_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_end_control_structure_used</span><span class="plain">(</span><span class="identifier">implicit_end</span><span class="plain">,</span>
<span class="identifier">ParseTree::get_control_structure_used</span><span class="plain">(</span><span class="identifier">opening</span><span class="plain">));</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">implicit_end</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">,</span>
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">opening</span><span class="plain">, </span><span class="constant">indentation_level_ANNOT</span><span class="plain">));</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">implicit_end</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Sentences::RuleSubtrees::end_node is used in <a href="#SP7_5_1">&#167;7.5.1</a>, <a href="#SP7_6_5_1">&#167;7.6.5.1</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. Basic Structural Syntax. </b>The following routine is an attempt to contain information about the
basic structural phrases in one place, so that if future loop constructs
are added, they can fairly simply be put here.
</p>
<pre class="display">
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="functiontext">Sentences::RuleSubtrees::csp_new</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">control_structure_phrase</span><span class="plain">);</span>
<span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;indent_subblocks</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;body_empty_except_for_subordinates</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;used_at_stage</span><span class="plain"> = -1;</span>
<span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;requires_new_syntax</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;allow_run_on</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;keyword</span><span class="plain"> = </span><span class="identifier">L</span><span class="string">"&lt;none&gt;"</span><span class="plain">;</span>
<span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;is_a_loop</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">csp</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::create_standard_csps</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">switch_CSP</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::csp_new</span><span class="plain">();</span>
<span class="identifier">switch_CSP</span><span class="plain">-</span><span class="element">&gt;body_empty_except_for_subordinates</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">switch_CSP</span><span class="plain">-</span><span class="element">&gt;indent_subblocks</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">switch_CSP</span><span class="plain">-</span><span class="element">&gt;requires_new_syntax</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">switch_CSP</span><span class="plain">-</span><span class="element">&gt;keyword</span><span class="plain"> = </span><span class="identifier">L</span><span class="string">"if"</span><span class="plain">;</span>
<span class="identifier">if_CSP</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::csp_new</span><span class="plain">();</span>
<span class="identifier">if_CSP</span><span class="plain">-</span><span class="element">&gt;keyword</span><span class="plain"> = </span><span class="identifier">L</span><span class="string">"if"</span><span class="plain">;</span>
<span class="identifier">repeat_CSP</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::csp_new</span><span class="plain">();</span>
<span class="identifier">repeat_CSP</span><span class="plain">-</span><span class="element">&gt;keyword</span><span class="plain"> = </span><span class="identifier">L</span><span class="string">"repeat"</span><span class="plain">;</span>
<span class="identifier">repeat_CSP</span><span class="plain">-</span><span class="element">&gt;is_a_loop</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">while_CSP</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::csp_new</span><span class="plain">();</span>
<span class="identifier">while_CSP</span><span class="plain">-</span><span class="element">&gt;keyword</span><span class="plain"> = </span><span class="identifier">L</span><span class="string">"while"</span><span class="plain">;</span>
<span class="identifier">while_CSP</span><span class="plain">-</span><span class="element">&gt;is_a_loop</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">otherwise_CSP</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::csp_new</span><span class="plain">();</span>
<span class="identifier">otherwise_CSP</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain"> = </span><span class="identifier">if_CSP</span><span class="plain">;</span>
<span class="identifier">otherwise_CSP</span><span class="plain">-</span><span class="element">&gt;used_at_stage</span><span class="plain"> = 1;</span>
<span class="identifier">abbreviated_otherwise_CSP</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::csp_new</span><span class="plain">();</span>
<span class="identifier">abbreviated_otherwise_CSP</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain"> = </span><span class="identifier">if_CSP</span><span class="plain">;</span>
<span class="identifier">abbreviated_otherwise_CSP</span><span class="plain">-</span><span class="element">&gt;used_at_stage</span><span class="plain"> = 1;</span>
<span class="identifier">otherwise_if_CSP</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::csp_new</span><span class="plain">();</span>
<span class="identifier">otherwise_if_CSP</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain"> = </span><span class="identifier">if_CSP</span><span class="plain">;</span>
<span class="identifier">otherwise_if_CSP</span><span class="plain">-</span><span class="element">&gt;used_at_stage</span><span class="plain"> = 0;</span>
<span class="identifier">case_CSP</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::csp_new</span><span class="plain">();</span>
<span class="identifier">case_CSP</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain"> = </span><span class="identifier">switch_CSP</span><span class="plain">;</span>
<span class="identifier">case_CSP</span><span class="plain">-</span><span class="element">&gt;used_at_stage</span><span class="plain"> = 1;</span>
<span class="identifier">case_CSP</span><span class="plain">-</span><span class="element">&gt;requires_new_syntax</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">case_CSP</span><span class="plain">-</span><span class="element">&gt;allow_run_on</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">default_case_CSP</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::csp_new</span><span class="plain">();</span>
<span class="identifier">default_case_CSP</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain"> = </span><span class="identifier">switch_CSP</span><span class="plain">;</span>
<span class="identifier">default_case_CSP</span><span class="plain">-</span><span class="element">&gt;used_at_stage</span><span class="plain"> = 2;</span>
<span class="identifier">default_case_CSP</span><span class="plain">-</span><span class="element">&gt;requires_new_syntax</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">default_case_CSP</span><span class="plain">-</span><span class="element">&gt;allow_run_on</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">say_CSP</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::csp_new</span><span class="plain">();</span>
<span class="identifier">now_CSP</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::csp_new</span><span class="plain">();</span>
<span class="identifier">instead_CSP</span><span class="plain"> = </span><span class="functiontext">Sentences::RuleSubtrees::csp_new</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::log_control_structure</span><span class="plain">(</span><span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">if_CSP</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"IF"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">repeat_CSP</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"RPT"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">while_CSP</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"WHI"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">switch_CSP</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"SWI"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">otherwise_CSP</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"O"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">abbreviated_otherwise_CSP</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"AO"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">otherwise_if_CSP</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"OIF"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">case_CSP</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"CAS"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">default_case_CSP</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"DEF"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">say_CSP</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"SAY"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">now_CSP</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"NOW"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">instead_CSP</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"INS"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"---"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::comma_possible</span><span class="plain">(</span><span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">if_CSP</span><span class="plain">) || (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">switch_CSP</span><span class="plain">) || (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">otherwise_if_CSP</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::is_a_loop</span><span class="plain">(</span><span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;is_a_loop</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::opens_block</span><span class="plain">(</span><span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">csp</span><span class="plain">) &amp;&amp; (</span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;subordinate_to</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) &amp;&amp; (</span><span class="identifier">csp</span><span class="plain"> != </span><span class="identifier">say_CSP</span><span class="plain">) &amp;&amp; (</span><span class="identifier">csp</span><span class="plain"> != </span><span class="identifier">now_CSP</span><span class="plain">) &amp;&amp; (</span><span class="identifier">csp</span><span class="plain"> != </span><span class="identifier">instead_CSP</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::permits_break</span><span class="plain">(</span><span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">repeat_CSP</span><span class="plain">) || (</span><span class="identifier">csp</span><span class="plain"> == </span><span class="identifier">while_CSP</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="functiontext">Sentences::RuleSubtrees::incipit</span><span class="plain">(</span><span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="identifier">csp</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">csp</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">csp</span><span class="plain">-</span><span class="element">&gt;keyword</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">L</span><span class="string">"&lt;none&gt;"</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="functiontext">Sentences::RuleSubtrees::detect_control_structure</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">control</span><span class="plain">-</span><span class="identifier">structure</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (&lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt; == </span><span class="identifier">abbreviated_otherwise_CSP</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Sentences::RuleSubtrees::abbreviated_otherwise</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">control</span><span class="plain">-</span><span class="identifier">structure</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (&lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt; == </span><span class="identifier">abbreviated_otherwise_CSP</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">control_structure_phrase</span><span class="plain"> *</span><span class="functiontext">Sentences::RuleSubtrees::detect_end_control_structure</span><span class="plain">(</span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">end</span><span class="plain">-</span><span class="identifier">control</span><span class="plain">-</span><span class="identifier">structure</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Sentences::RuleSubtrees::csp_new appears nowhere else.</p>
<p class="endnote">The function Sentences::RuleSubtrees::create_standard_csps is used in 1/mr (<a href="1-mr.html#SP4_8">&#167;4.8</a>).</p>
<p class="endnote">The function Sentences::RuleSubtrees::log_control_structure is used in 7/ptu (<a href="7-ptu.html#SP17_2">&#167;17.2</a>).</p>
<p class="endnote">The function Sentences::RuleSubtrees::comma_possible is used in 22/dptd (<a href="22-dptd.html#SP8_2">&#167;8.2</a>).</p>
<p class="endnote">The function Sentences::RuleSubtrees::is_a_loop is used in 24/pb (<a href="24-pb.html#SP15">&#167;15</a>).</p>
<p class="endnote">The function Sentences::RuleSubtrees::opens_block is used in <a href="#SP7_7_1">&#167;7.7.1</a>, <a href="#SP8">&#167;8</a>, <a href="#SP7_16">&#167;7.16</a>, 25/cp (<a href="25-cp.html#SP5">&#167;5</a>, <a href="25-cp.html#SP5_4">&#167;5.4</a>).</p>
<p class="endnote">The function Sentences::RuleSubtrees::permits_break is used in 24/pb (<a href="24-pb.html#SP17">&#167;17</a>).</p>
<p class="endnote">The function Sentences::RuleSubtrees::incipit is used in 24/pb (<a href="24-pb.html#SP16">&#167;16</a>).</p>
<p class="endnote">The function Sentences::RuleSubtrees::detect_control_structure is used in <a href="#SP7_1">&#167;7.1</a>, <a href="#SP7_4">&#167;7.4</a>, <a href="#SP7_5">&#167;7.5</a>.</p>
<p class="endnote">The function Sentences::RuleSubtrees::abbreviated_otherwise is used in <a href="#SP7_5_1_1">&#167;7.5.1.1</a>.</p>
<p class="endnote">The function Sentences::RuleSubtrees::detect_end_control_structure is used in <a href="#SP7_1">&#167;7.1</a>, <a href="#SP7_4">&#167;7.4</a>.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>Control structures such as "if" act as a sort of super-punctuation inside
rule and phrase definitions, and in particular they affect the actual
punctuation of the sentences there (consider the rules about colons versus
semicolons). So, though it's still early in Inform's run, we need to seek
them out.
</p>
<p class="inwebparagraph">Here we parse the text of a command phrase which, if any, of the control
structures it might be. Note that &lt;s-command&gt; has a grammar partially
overlapping with this, and they need to match.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">NO_SIGF</span><span class="plain"> 0</span>
<span class="definitionkeyword">define</span> <span class="constant">SAY_SIGF</span><span class="plain"> 1</span>
<span class="definitionkeyword">define</span> <span class="constant">NOW_SIGF</span><span class="plain"> 2</span>
</pre>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">control</span><span class="plain">-</span><span class="identifier">structure</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt; ::=</span>
<span class="reserved">if</span><span class="plain"> ... </span><span class="identifier">is</span><span class="plain"> </span><span class="identifier">begin</span><span class="plain"> | ==&gt; 0; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">switch_CSP</span>
<span class="reserved">if</span><span class="plain"> ... </span><span class="identifier">is</span><span class="plain"> | ==&gt; 0; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">switch_CSP</span>
<span class="reserved">if</span><span class="plain">/</span><span class="identifier">unless</span><span class="plain"> ... | ==&gt; 0; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">if_CSP</span>
<span class="identifier">repeat</span><span class="plain"> ... | ==&gt; 0; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">repeat_CSP</span>
<span class="reserved">while</span><span class="plain"> ... | ==&gt; 0; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">while_CSP</span>
<span class="reserved">else</span><span class="plain">/</span><span class="identifier">otherwise</span><span class="plain"> | ==&gt; 0; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">otherwise_CSP</span>
<span class="reserved">else</span><span class="plain">/</span><span class="identifier">otherwise</span><span class="plain"> </span><span class="reserved">if</span><span class="plain">/</span><span class="identifier">unless</span><span class="plain"> ... | ==&gt; 0; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">otherwise_if_CSP</span>
<span class="reserved">else</span><span class="plain">/</span><span class="identifier">otherwise</span><span class="plain"> ... | ==&gt; 0; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">abbreviated_otherwise_CSP</span>
<span class="plain">-- </span><span class="identifier">otherwise</span><span class="plain"> | ==&gt; 0; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">default_case_CSP</span>
<span class="plain">-- ... ==&gt; 0; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">case_CSP</span>
<span class="plain">&lt;</span><span class="identifier">end</span><span class="plain">-</span><span class="identifier">control</span><span class="plain">-</span><span class="identifier">structure</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt; ::=</span>
<span class="identifier">end</span><span class="plain"> </span><span class="reserved">if</span><span class="plain">/</span><span class="identifier">unless</span><span class="plain"> | ==&gt; 0; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">if_CSP</span>
<span class="identifier">end</span><span class="plain"> </span><span class="reserved">while</span><span class="plain"> | ==&gt; 0; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">while_CSP</span>
<span class="identifier">end</span><span class="plain"> </span><span class="identifier">repeat</span><span class="plain"> ==&gt; 0; *</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">repeat_CSP</span>
<span class="plain">&lt;</span><span class="identifier">other</span><span class="plain">-</span><span class="identifier">significant</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt; ::=</span>
<span class="identifier">say</span><span class="plain"> ... | ==&gt; </span><span class="constant">SAY_SIGF</span>
<span class="identifier">now</span><span class="plain"> ... ==&gt; </span><span class="constant">NOW_SIGF</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>This is used to see if an "if" is being used with the comma notation:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">with</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">notation</span><span class="plain">&gt; ::=</span>
<span class="plain">...... , ......</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. </b>This is used to see if an "if" is being used with the comma notation:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">instead</span><span class="plain">-</span><span class="identifier">keyword</span><span class="plain">&gt; ::=</span>
<span class="identifier">instead</span><span class="plain"> ... |</span>
<span class="plain">... </span><span class="identifier">instead</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. </b>Finally, this is used to see if a control structure opens a block:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">beginning</span><span class="plain">-</span><span class="identifier">block</span><span class="plain">&gt; ::=</span>
<span class="plain">... </span><span class="identifier">begin</span>
</pre>
<p class="inwebparagraph"></p>
<hr class="tocbar">
<ul class="toc"><li><a href="7-oaf.html">Back to 'Of and From'</a></li><li><i>(This section ends Chapter 7: Sentences.)</i></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>