1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 10:04:21 +03:00
inform7/docs/syntax-module/2-pt.html
2020-05-03 16:34:53 +01:00

1571 lines
328 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Parse Tree</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
MathJax = {
tex: {
inlineMath: '$', '$'], ['\\(', '\\)'
},
svg: {
fontCache: 'global'
}
};
</script>
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body class="commentary-font">
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-assets/Inform.png" height=72">
</a></h1>
<ul><li><a href="../compiler.html">compiler tools</a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul><h2>Compiler Webs</h2><ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul><h2>Inbuild Modules</h2><ul>
<li><a href="../supervisor-module/index.html">supervisor</a></li>
</ul><h2>Inform7 Modules</h2><ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../problems-module/index.html">problems</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul><h2>Inter Modules</h2><ul>
<li><a href="../bytecode-module/index.html">bytecode</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul><h2>Shared Modules</h2><ul>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="index.html"><span class="selectedlink">syntax</span></a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../html-module/index.html">html</a></li>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Parse Tree' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../compiler.html">Shared Modules</a></li><li><a href="index.html">syntax</a></li><li><a href="index.html#2">Chapter 2: The Parse Tree</a></li><li><b>Parse Tree</b></li></ul></div>
<p class="purpose">To parse trees which decompose the meaning of excerpts of text, and which allow annotations to be made at each node.</p>
<ul class="toc"><li><a href="2-pt.html#SP1">&#167;1. Trees store meanings</a></li><li><a href="2-pt.html#SP4">&#167;4. Structural vs specifications</a></li><li><a href="2-pt.html#SP5">&#167;5. Node types</a></li><li><a href="2-pt.html#SP7">&#167;7. The structure</a></li><li><a href="2-pt.html#SP8">&#167;8. Where we currently are in the text</a></li><li><a href="2-pt.html#SP12">&#167;12. Node metadata</a></li><li><a href="2-pt.html#SP16">&#167;16. The metadata table</a></li><li><a href="2-pt.html#SP20">&#167;20. Logging node types</a></li><li><a href="2-pt.html#SP21">&#167;21. Creation</a></li><li><a href="2-pt.html#SP24">&#167;24. Annotations</a></li><li><a href="2-pt.html#SP33">&#167;33. Copying parse nodes</a></li><li><a href="2-pt.html#SP36">&#167;36. Child count</a></li><li><a href="2-pt.html#SP37">&#167;37. Detection of subnodes</a></li><li><a href="2-pt.html#SP38">&#167;38. The word range beneath a given node</a></li><li><a href="2-pt.html#SP45">&#167;45. Logging the parse tree</a></li><li><a href="2-pt.html#SP50">&#167;50. General traversals</a></li><li><a href="2-pt.html#SP52">&#167;52. Verify integrity</a></li><li><a href="2-pt.html#SP54">&#167;54. Verify structure</a></li><li><a href="2-pt.html#SP56">&#167;56. Parentage rules</a></li><li><a href="2-pt.html#SP58">&#167;58. Annotation rules</a></li><li><a href="2-pt.html#SP60">&#167;60. Ambiguity subtrees</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1"></a><b>&#167;1. Trees store meanings. </b>Most algorithms for parsing natural language involve the construction of
trees, in which the original words appear as leaves at the top of the tree,
while the grammatical functions they serve appear as the branches and trunk:
thus the word "orange", as an adjective, might be growing from a branch
which represents a noun clause ("the orange envelope"), growing in turn from
a trunk which in turn might represent a assertion sentence:
</p>
<blockquote>
<p>The card is in the orange envelope.</p>
</blockquote>
<p class="commentary">Inform goes further than this. The result of parsing any piece of text is
always a tree, so that a common data structure is used for every meaning
which is stored inside Inform.
</p>
<p class="commentary">The tree is stored as a collection of "parse nodes", with <span class="extract"><span class="extract-syntax">next</span></span> and
<span class="extract"><span class="extract-syntax">down</span></span> links between them to represent siblings and children.
</p>
<p class="commentary">Some text is ambiguous. Because of that, the tree needs to be capable of
representing multiple interpretations of the same wording. So nodes also
have a <span class="extract"><span class="extract-syntax">next_alternative</span></span> link, which &mdash; if used &mdash; forks the tree into
different possible readings.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">MAX_ATTACHMENT_STACK_SIZE</span><span class="plain-syntax"> </span><span class="constant-syntax">100</span><span class="plain-syntax"> </span><span class="comment-syntax"> must be at least the number of heading levels plus 3</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">root_node</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">attachment_sp</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">attachment_stack_parent</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_ATTACHMENT_STACK_SIZE</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">one_off_attachment_point</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">MEMORY_MANAGEMENT</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="function-syntax">ParseTree::new_tree</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP21" class="function-link"><span class="function-syntax">ParseTree::new</span></a><span class="plain-syntax">(</span><span class="constant-syntax">ROOT_NT</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">attachment_sp</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">one_off_attachment_point</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP2" class="function-link"><span class="function-syntax">ParseTree::push_attachment_point</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">T</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<ul class="endnotetexts"><li>The structure parse_node_tree is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP2"></a><b>&#167;2. </b>It turns out to be convenient to have a mechanism for inserting sentences,
the main large-scale structural nodes, into the tree. These come in a
stream in the source text, but can attach at different levels in the tree,
since each sentence needs to be a child of the relevant heading node
under which it falls. We therefore keep a stack of open headings:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::push_attachment_point</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">ParseTree::push_attachment_point</span></span>:<br/><a href="2-pt.html#SP1">&#167;1</a>, <a href="2-pt.html#SP44">&#167;44</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">l</span><span class="plain-syntax"> = </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">attachment_sp</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">attachment_sp</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">MAX_ATTACHMENT_STACK_SIZE</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"attachment stack overflow"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">attachment_stack_parent</span><span class="plain-syntax">[</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">attachment_sp</span><span class="plain-syntax">++] = </span><span class="identifier-syntax">to</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">l</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::pop_attachment_point</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">l</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">attachment_sp</span><span class="plain-syntax"> = </span><span class="identifier-syntax">l</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3"></a><b>&#167;3. </b>In addition, we can temporarily override this system:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::set_attachment_point_one_off</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">one_off_attachment_point</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4"></a><b>&#167;4. Structural vs specifications. </b>Each node has a "node type". About half of the node types are called
"structural", with the remainder being "specifications". Structural nodes
represent the large-scale structure of the source text: from headings down to
code points in routines. The shape of the above assertion sentence, for
example, is made up of structural nodes.
</p>
<p class="commentary">Specification nodes represent data rather than structure. For example, in
</p>
<blockquote>
<p>The tally is a number that varies. The tally is 124.</p>
</blockquote>
<p class="commentary">the value "124" is stored as a single specification node, of node type
<span class="extract"><span class="extract-syntax">CONSTANT_NT</span></span>. But more elaborate possibilities exist:
</p>
<blockquote>
<p>tally is 124 and the player is in the Library</p>
</blockquote>
<p class="commentary">is stored as a tree of three specification nodes:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> LOGICAL_AND_NT</span>
<span class="plain-syntax"> TEST_PROPOSITION_NT "tally is 124"</span>
<span class="plain-syntax"> TEST_PROPOSITION_NT "the player is in the Library"</span>
</pre>
<p class="commentary">The tree is heavily annotated, so that nodes can carry more meaning than
just their type alone. For example, the <span class="extract"><span class="extract-syntax">CONSTANT_NT</span></span> node for "124"
is annotated with the kind <span class="extract"><span class="extract-syntax">K_number</span></span>, showing what kind of constant it
represents. The <span class="extract"><span class="extract-syntax">TEST_PROPOSITION_NT</span></span> nodes are annotated with
logical propositions. There's a huge variety of different annotations
used in different contexts, most of them relevant only for certain node
types. Some of these point to structures which in turn point back to
the tree: for example, the proposition "tally is 124" is stored as
a <span class="extract"><span class="extract-syntax">pcalc_prop</span></span> structure which indirectly contains the values "tally"
and "124", which are both represented as parse nodes.
</p>
<p class="commentary firstcommentary"><a id="SP5"></a><b>&#167;5. Node types. </b>The basic meaning of a node is represented by its "node type". Though
they are only used fleetingly, and never remain in either the structural
tree or as stored values, every valid meaning code (i.e., every <span class="extract"><span class="extract-syntax">*_MC</span></span>
constant) is also a valid node type. Since meaning codes are integers
with a single bit set, and we need up to 31 of them, we enumerate
node types as values with bit 32 set. That being so, node types have
to be stored unsigned, and for portability we define:
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="comment-syntax"> (not a typedef only because it makes trouble for inweb)</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6"></a><b>&#167;6. </b>We now run through the enumeration, in a sequence which must exactly match
that in the table of metadata below.
</p>
<p class="commentary">Structural node types are enumerated first:
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">BASE_OF_ENUMERATED_NTS</span><span class="plain-syntax"> </span><span class="constant-syntax">0x80000000</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">INVALID_NT</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="constant-syntax">0x80000000</span><span class="plain-syntax"> </span><span class="comment-syntax"> No node with this node type should ever exist</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">ROOT_NT</span><span class="plain-syntax"> </span><span class="comment-syntax"> Only one such node exists: the tree root</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">INCLUSION_NT</span><span class="plain-syntax"> </span><span class="comment-syntax"> Holds a block of source material</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">HEADING_NT</span><span class="plain-syntax"> </span><span class="comment-syntax"> "Chapter VIII: Never Turn Your Back On A Shreve"</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">INCLUDE_NT</span><span class="plain-syntax"> </span><span class="comment-syntax"> "Include School Rules by Argus Filch"</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">BEGINHERE_NT</span><span class="plain-syntax"> </span><span class="comment-syntax"> "The Standard Rules begin here"</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">ENDHERE_NT</span><span class="plain-syntax"> </span><span class="comment-syntax"> "The Standard Rules end here"</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">SENTENCE_NT</span><span class="plain-syntax"> </span><span class="comment-syntax"> "The Garden is a room"</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">AMBIGUITY_NT</span><span class="plain-syntax"> </span><span class="comment-syntax"> Marks an ambiguous set of readings in the tree</span>
</pre>
<p class="commentary firstcommentary"><a id="SP7"></a><b>&#167;7. The structure. </b>Finally, then, the data structure.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">text_parsed</span><span class="plain-syntax">; </span><span class="comment-syntax"> the text being interpreted by this node</span>
<span class="plain-syntax"> </span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">node_type</span><span class="plain-syntax">; </span><span class="comment-syntax"> what the node basically represents</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">annotations</span><span class="plain-syntax">; </span><span class="comment-syntax"> linked list of miscellaneous annotations</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">down</span><span class="plain-syntax">; </span><span class="comment-syntax"> pointers within the current interpretation</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">next</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">score</span><span class="plain-syntax">; </span><span class="comment-syntax"> used to choose most likely interpretation</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax">; </span><span class="comment-syntax"> fork to alternative interpretation</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">log_time</span><span class="plain-syntax">; </span><span class="comment-syntax"> used purely as a defensive measure when writing debugging log</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">MEMORY_MANAGEMENT</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure parse_node is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP8"></a><b>&#167;8. Where we currently are in the text. </b>Inform makes many traverses through the big parse tree, often modifying as it
goes, and keeps track of its position so that it can make any problem messages
correctly refer to the location of the faulty text in the original source
files.
</p>
<p class="commentary">During such traverses, <span class="extract"><span class="extract-syntax">current_sentence</span></span> is always the subtree being looked
at: it is always a child of the tree root, and is usually a <span class="extract"><span class="extract-syntax">SENTENCE_NT</span></span>
node, hence the name.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9"></a><b>&#167;9. </b>The parse tree annotations are miscellaneous, and many are needed only
at a few unusual nodes. Rather than have the structure grow large, we
store annotations in the following:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">kind_of_annotation</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">annotation_integer</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">general_pointer</span><span class="plain-syntax"> </span><span class="identifier-syntax">annotation_pointer</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">next_annotation</span><span class="plain-syntax">;</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure parse_node_annotation is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP10"></a><b>&#167;10. </b></p>
<pre class="definitions code-font"><span class="definition-keyword">enum</span> <span class="constant-syntax">heading_level_ANNOT</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax"> </span><span class="comment-syntax"> int: for HEADING nodes, a hierarchical level, 0 (highest) to 9 (lowest)</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">language_element_ANNOT</span><span class="plain-syntax"> </span><span class="comment-syntax"> </span><span class="extract"><span class="extract-syntax">int</span></span><span class="comment-syntax">: this node is not really a sentence, but a language definition Use</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">sentence_unparsed_ANNOT</span><span class="plain-syntax"> </span><span class="comment-syntax"> int: set if verbs haven't been sought yet here</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">suppress_heading_dependencies_ANNOT</span><span class="plain-syntax"> </span><span class="comment-syntax"> int: ignore extension dependencies on this heading node</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">implied_heading_ANNOT</span><span class="plain-syntax"> </span><span class="comment-syntax"> int: set only for the heading of implied inclusions</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">MAX_ANNOT_NUMBER</span><span class="plain-syntax"> (</span><span class="identifier-syntax">NO_DEFINED_ANNOT_VALUES</span><span class="plain-syntax">+1)</span>
</pre>
<p class="commentary firstcommentary"><a id="SP11"></a><b>&#167;11. </b>Access routines will be needed for some of these, and the following
constructs them:
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="identifier-syntax">DECLARE_ANNOTATION_FUNCTIONS</span><span class="plain-syntax">(</span><span class="identifier-syntax">annotation_name</span><span class="plain-syntax">, </span><span class="identifier-syntax">pointer_type</span><span class="plain-syntax">)</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="identifier-syntax">ParseTree::set_</span><span class="plain-syntax">##</span><span class="identifier-syntax">annotation_name</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">pointer_type</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">);</span>
<span class="identifier-syntax">pointer_type</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ParseTree::get_</span><span class="plain-syntax">##</span><span class="identifier-syntax">annotation_name</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">);</span>
</pre>
<p class="commentary firstcommentary"><a id="SP12"></a><b>&#167;12. Node metadata. </b>With such a profusion of node types, we need a systematic way to organise
information about them.
</p>
<p class="commentary">The following structure is used only for a row in a table of what we
might call metadata about node types: information on where each node type
can appear, and what restrictions apply to its use. We also store textual
names for the node types here, as this is convenient for logging.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">identity</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">node_type_name</span><span class="plain-syntax">; </span><span class="comment-syntax"> text of name of type, such as </span><span class="extract"><span class="extract-syntax">"INVOCATION_LIST_NT"</span></span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">min_children</span><span class="plain-syntax">; </span><span class="comment-syntax"> minimum legal number of child nodes</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">max_children</span><span class="plain-syntax">; </span><span class="comment-syntax"> maximum legal number of child nodes</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">category</span><span class="plain-syntax">; </span><span class="comment-syntax"> one of the </span><span class="extract"><span class="extract-syntax">*_NCAT</span></span><span class="comment-syntax"> values below</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">node_flags</span><span class="plain-syntax">; </span><span class="comment-syntax"> bitmap of node flags</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure parse_tree_node_type is private to this section.</li></ul>
<p class="commentary firstcommentary"><a id="SP13"></a><b>&#167;13. </b>The categories are:
</p>
<pre class="definitions code-font"><span class="definition-keyword">enum</span> <span class="constant-syntax">INVALID_NCAT</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">L1_NCAT</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">L2_NCAT</span>
</pre>
<p class="commentary firstcommentary"><a id="SP14"></a><b>&#167;14. </b>The bitmap of node flags begins with:
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">DONT_VISIT_NFLAG</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00000001</span><span class="plain-syntax"> </span><span class="comment-syntax"> not visited in traverses</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">TABBED_CONTENT_NFLAG</span><span class="plain-syntax"> </span><span class="constant-syntax">0x00000002</span><span class="plain-syntax"> </span><span class="comment-syntax"> contains tab-delimited lists</span>
</pre>
<p class="commentary firstcommentary"><a id="SP15"></a><b>&#167;15. </b>Various modules conventionally use this global setting to toggle debugging
log output:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">trace_sentences</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP16"></a><b>&#167;16. The metadata table. </b>Note that the sequence here must exactly match the enumeration above.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">INFTY</span><span class="plain-syntax"> </span><span class="constant-syntax">1000000000</span><span class="plain-syntax"> </span><span class="comment-syntax"> if ever a node has more than a billion children, we are in trouble anyway</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax"> </span><span class="identifier-syntax">parse_tree_node_types</span><span class="plain-syntax">[</span><span class="identifier-syntax">NO_DEFINED_NT_VALUES</span><span class="plain-syntax">];</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::md</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">ParseTree::md</span></span>:<br/><a href="2-pt.html#SP17">&#167;17</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax"> </span><span class="identifier-syntax">ptnt</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::valid_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">ptnt</span><span class="plain-syntax">.</span><span class="element-syntax">identity</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"set bad metadata"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">parse_tree_node_types</span><span class="plain-syntax">[</span><span class="identifier-syntax">ptnt</span><span class="plain-syntax">.</span><span class="element-syntax">identity</span><span class="plain-syntax"> - </span><span class="constant-syntax">BASE_OF_ENUMERATED_NTS</span><span class="plain-syntax">] = </span><span class="identifier-syntax">ptnt</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP17"></a><b>&#167;17. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::metadata_setup</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">ParseTree::metadata_setup</span></span>:<br/>Syntax Module - <a href="1-sm.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP16" class="function-link"><span class="function-syntax">ParseTree::md</span></a><span class="plain-syntax">((</span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax">) { </span><span class="constant-syntax">INVALID_NT</span><span class="plain-syntax">, </span><span class="string-syntax">"(INVALID_NT)"</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">INFTY</span><span class="plain-syntax">, </span><span class="constant-syntax">INVALID_NCAT</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax"> });</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP16" class="function-link"><span class="function-syntax">ParseTree::md</span></a><span class="plain-syntax">((</span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax">) { </span><span class="constant-syntax">ROOT_NT</span><span class="plain-syntax">, </span><span class="string-syntax">"ROOT_NT"</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">INFTY</span><span class="plain-syntax">, </span><span class="constant-syntax">L1_NCAT</span><span class="plain-syntax">, </span><span class="constant-syntax">DONT_VISIT_NFLAG</span><span class="plain-syntax"> });</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP16" class="function-link"><span class="function-syntax">ParseTree::md</span></a><span class="plain-syntax">((</span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax">) { </span><span class="constant-syntax">INCLUSION_NT</span><span class="plain-syntax">, </span><span class="string-syntax">"INCLUSION_NT"</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">INFTY</span><span class="plain-syntax">, </span><span class="constant-syntax">L1_NCAT</span><span class="plain-syntax">, </span><span class="constant-syntax">DONT_VISIT_NFLAG</span><span class="plain-syntax"> });</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP16" class="function-link"><span class="function-syntax">ParseTree::md</span></a><span class="plain-syntax">((</span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax">) { </span><span class="constant-syntax">HEADING_NT</span><span class="plain-syntax">, </span><span class="string-syntax">"HEADING_NT"</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">INFTY</span><span class="plain-syntax">, </span><span class="constant-syntax">L1_NCAT</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax"> });</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP16" class="function-link"><span class="function-syntax">ParseTree::md</span></a><span class="plain-syntax">((</span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax">) { </span><span class="constant-syntax">INCLUDE_NT</span><span class="plain-syntax">, </span><span class="string-syntax">"INCLUDE_NT"</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">L2_NCAT</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax"> });</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP16" class="function-link"><span class="function-syntax">ParseTree::md</span></a><span class="plain-syntax">((</span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax">) { </span><span class="constant-syntax">BEGINHERE_NT</span><span class="plain-syntax">, </span><span class="string-syntax">"BEGINHERE_NT"</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">L2_NCAT</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax"> });</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP16" class="function-link"><span class="function-syntax">ParseTree::md</span></a><span class="plain-syntax">((</span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax">) { </span><span class="constant-syntax">ENDHERE_NT</span><span class="plain-syntax">, </span><span class="string-syntax">"ENDHERE_NT"</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">L2_NCAT</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax"> });</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP16" class="function-link"><span class="function-syntax">ParseTree::md</span></a><span class="plain-syntax">((</span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax">) { </span><span class="constant-syntax">SENTENCE_NT</span><span class="plain-syntax">, </span><span class="string-syntax">"SENTENCE_NT"</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">INFTY</span><span class="plain-syntax">, </span><span class="constant-syntax">L2_NCAT</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax"> });</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP16" class="function-link"><span class="function-syntax">ParseTree::md</span></a><span class="plain-syntax">((</span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax">) { </span><span class="constant-syntax">AMBIGUITY_NT</span><span class="plain-syntax">, </span><span class="string-syntax">"AMBIGUITY_NT"</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">INFTY</span><span class="plain-syntax">, </span><span class="constant-syntax">L1_NCAT</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax"> });</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">UNKNOWN_NT</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP16" class="function-link"><span class="function-syntax">ParseTree::md</span></a><span class="plain-syntax">((</span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax">) { </span><span class="identifier-syntax">UNKNOWN_NT</span><span class="plain-syntax">, </span><span class="string-syntax">"UNKNOWN_NT"</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">INFTY</span><span class="plain-syntax">, </span><span class="identifier-syntax">L3_NCAT</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax"> });</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">PARSE_TREE_METADATA_SETUP</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PARSE_TREE_METADATA_SETUP</span><span class="plain-syntax">();</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP18"></a><b>&#167;18. </b>We can only retrieve metadata on enumerated node types, not on meaning
codes such as <span class="extract"><span class="extract-syntax">RULE_MC</span></span>, for which the following will return <span class="extract"><span class="extract-syntax">NULL</span></span>.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax"> *</span><span class="function-syntax">ParseTree::node_metadata</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">ParseTree::node_metadata</span></span>:<br/><a href="2-pt.html#SP19">&#167;19</a>, <a href="2-pt.html#SP20">&#167;20</a>, <a href="2-pt.html#SP55">&#167;55</a>, <a href="2-pt.html#SP55_3">&#167;55.3</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">t</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">BASE_OF_ENUMERATED_NTS</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">t</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">BASE_OF_ENUMERATED_NTS</span><span class="plain-syntax">+</span><span class="identifier-syntax">NO_DEFINED_NT_VALUES</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax"> *</span><span class="identifier-syntax">metadata</span><span class="plain-syntax"> = &amp;(</span><span class="identifier-syntax">parse_tree_node_types</span><span class="plain-syntax">[</span><span class="identifier-syntax">t</span><span class="plain-syntax"> - </span><span class="constant-syntax">BASE_OF_ENUMERATED_NTS</span><span class="plain-syntax">]);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">metadata</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">identity</span><span class="plain-syntax"> != </span><span class="identifier-syntax">t</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">STDERR</span><span class="plain-syntax">, </span><span class="string-syntax">"unable to locate node type %08x\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"node type metadata lookup incorrect"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">metadata</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP19"></a><b>&#167;19. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::valid_type</span><button class="popup" onclick="togglePopup('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <span class="code-font"><span class="function-syntax">ParseTree::valid_type</span></span>:<br/><a href="2-pt.html#SP16">&#167;16</a>, <a href="2-pt.html#SP53">&#167;53</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">t</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">BASE_OF_ENUMERATED_NTS</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">t</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">BASE_OF_ENUMERATED_NTS</span><span class="plain-syntax">+</span><span class="identifier-syntax">NO_DEFINED_NT_VALUES</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::cat</span><button class="popup" onclick="togglePopup('usagePopup6')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup6">Usage of <span class="code-font"><span class="function-syntax">ParseTree::cat</span></span>:<br/><a href="2-pt.html#SP58">&#167;58</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax"> *</span><span class="identifier-syntax">metadata</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP18" class="function-link"><span class="function-syntax">ParseTree::node_metadata</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">metadata</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">category</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">INVALID_NCAT</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::top_level</span><button class="popup" onclick="togglePopup('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <span class="code-font"><span class="function-syntax">ParseTree::top_level</span></span>:<br/><a href="2-pt.html#SP50">&#167;50</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax"> *</span><span class="identifier-syntax">metadata</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP18" class="function-link"><span class="function-syntax">ParseTree::node_metadata</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">metadata</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">category</span><span class="plain-syntax"> == </span><span class="constant-syntax">L1_NCAT</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::visitable</span><button class="popup" onclick="togglePopup('usagePopup8')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup8">Usage of <span class="code-font"><span class="function-syntax">ParseTree::visitable</span></span>:<br/><a href="2-pt.html#SP50">&#167;50</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::test_flag</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="constant-syntax">DONT_VISIT_NFLAG</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::test_flag</span><button class="popup" onclick="togglePopup('usagePopup9')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup9">Usage of <span class="code-font"><span class="function-syntax">ParseTree::test_flag</span></span>:<br/>Sentences - <a href="2-snt.html#SP5_2">&#167;5.2</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">f</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax"> *</span><span class="identifier-syntax">metadata</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP18" class="function-link"><span class="function-syntax">ParseTree::node_metadata</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">metadata</span><span class="plain-syntax">) &amp;&amp; ((</span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_flags</span><span class="plain-syntax">) &amp; </span><span class="identifier-syntax">f</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP20"></a><b>&#167;20. Logging node types. </b>And also making node names available to the machinery for producing internal
errors when incorrect node types are encountered, though we hope this will
never be used.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::log_type</span><button class="popup" onclick="togglePopup('usagePopup10')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup10">Usage of <span class="code-font"><span class="function-syntax">ParseTree::log_type</span></span>:<br/><a href="2-pt.html#SP47">&#167;47</a><br/>Syntax Module - <a href="1-sm.html#SP3_5">&#167;3.5</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">it</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax"> = (</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax">) </span><span class="identifier-syntax">it</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax"> *</span><span class="identifier-syntax">metadata</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP18" class="function-link"><span class="function-syntax">ParseTree::node_metadata</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">metadata</span><span class="plain-syntax">) </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"%s"</span><span class="plain-syntax">, </span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">UseExcerptMeanings::log_meaning_code</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"?%08x_NT"</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="function-syntax">ParseTree::get_type_name</span><span class="plain-syntax">(</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax"> *</span><span class="identifier-syntax">metadata</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP18" class="function-link"><span class="function-syntax">ParseTree::node_metadata</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">metadata</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="string-syntax">"?"</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type_name</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP21"></a><b>&#167;21. Creation. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="function-syntax">ParseTree::new</span><button class="popup" onclick="togglePopup('usagePopup11')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup11">Usage of <span class="code-font"><span class="function-syntax">ParseTree::new</span></span>:<br/><a href="2-pt.html#SP1">&#167;1</a>, <a href="2-pt.html#SP22">&#167;22</a>, <a href="2-pt.html#SP33">&#167;33</a>, <a href="2-pt.html#SP35">&#167;35</a><br/>Sentences - <a href="2-snt.html#SP6_1">&#167;6.1</a>, <a href="2-snt.html#SP6_6">&#167;6.6</a>, <a href="2-snt.html#SP6_9_4">&#167;6.9.4</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax"> = </span><span class="identifier-syntax">t</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP23" class="function-link"><span class="function-syntax">ParseTree::set_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">EMPTY_WORDING</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">log_time</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP26" class="function-link"><span class="function-syntax">ParseTree::set_score</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP22"></a><b>&#167;22. </b>The following constructor routines fill out the fields in useful ways.
Here's one if a word range is to be attached:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="function-syntax">ParseTree::new_with_words</span><button class="popup" onclick="togglePopup('usagePopup12')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup12">Usage of <span class="code-font"><span class="function-syntax">ParseTree::new_with_words</span></span>:<br/><a href="2-pt.html#SP60">&#167;60</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">code_number</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP21" class="function-link"><span class="function-syntax">ParseTree::new</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">code_number</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP23" class="function-link"><span class="function-syntax">ParseTree::set_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP23"></a><b>&#167;23. </b>The attached text.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::get_text</span><button class="popup" onclick="togglePopup('usagePopup13')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup13">Usage of <span class="code-font"><span class="function-syntax">ParseTree::get_text</span></span>:<br/><a href="2-pt.html#SP38">&#167;38</a>, <a href="2-pt.html#SP39">&#167;39</a>, <a href="2-pt.html#SP46">&#167;46</a>, <a href="2-pt.html#SP47">&#167;47</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pn</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">EMPTY_WORDING</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">text_parsed</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::set_text</span><button class="popup" onclick="togglePopup('usagePopup14')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup14">Usage of <span class="code-font"><span class="function-syntax">ParseTree::set_text</span></span>:<br/><a href="2-pt.html#SP21">&#167;21</a>, <a href="2-pt.html#SP22">&#167;22</a><br/>Sentences - <a href="2-snt.html#SP6_1">&#167;6.1</a>, <a href="2-snt.html#SP6_6">&#167;6.6</a>, <a href="2-snt.html#SP6_9_4">&#167;6.9.4</a>, <a href="2-snt.html#SP6_9_7">&#167;6.9.7</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pn</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to set words for null node"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">text_parsed</span><span class="plain-syntax"> = </span><span class="identifier-syntax">W</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP24"></a><b>&#167;24. Annotations. </b>It's easily overlooked that the single most useful piece of information
at each node is its node type, accessed as follows:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::get_type</span><button class="popup" onclick="togglePopup('usagePopup15')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup15">Usage of <span class="code-font"><span class="function-syntax">ParseTree::get_type</span></span>:<br/><a href="2-pt.html#SP44">&#167;44</a>, <a href="2-pt.html#SP44_1">&#167;44.1</a>, <a href="2-pt.html#SP53">&#167;53</a>, <a href="2-pt.html#SP55">&#167;55</a>, <a href="2-pt.html#SP55_3">&#167;55.3</a>, <a href="2-pt.html#SP60">&#167;60</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pn</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">INVALID_NT</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::is</span><button class="popup" onclick="togglePopup('usagePopup16')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup16">Usage of <span class="code-font"><span class="function-syntax">ParseTree::is</span></span>:<br/><a href="2-pt.html#SP50">&#167;50</a>, <a href="2-pt.html#SP55_1_1">&#167;55.1.1</a>, <a href="2-pt.html#SP60">&#167;60</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">pn</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax"> == </span><span class="identifier-syntax">t</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP25"></a><b>&#167;25. </b>When setting, we have to preserve the invariant, so we clear away any
annotations no longer relevant to the node's new identity.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::set_type</span><button class="popup" onclick="togglePopup('usagePopup17')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup17">Usage of <span class="code-font"><span class="function-syntax">ParseTree::set_type</span></span>:<br/>Sentences - <a href="2-snt.html#SP6_9">&#167;6.9</a>, <a href="2-snt.html#SP6_9_5">&#167;6.9.5</a>, <a href="2-snt.html#SP6_9_6">&#167;6.9.6</a>, <a href="2-snt.html#SP6_9_7">&#167;6.9.7</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">IMMUTABLE_NODE</span>
<span class="plain-syntax"> </span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">IMMUTABLE_NODE</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"$P changed to $N\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">nt</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"immutable type changed"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax"> = </span><span class="identifier-syntax">nt</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax"> (!(</span><a href="2-pt.html#SP59" class="function-link"><span class="function-syntax">ParseTree::annotation_allowed</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_of_annotation</span><span class="plain-syntax">))))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pna</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax"> (!(</span><a href="2-pt.html#SP59" class="function-link"><span class="function-syntax">ParseTree::annotation_allowed</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_of_annotation</span><span class="plain-syntax">))))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::set_type_and_clear_annotations</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax"> = </span><span class="identifier-syntax">nt</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP26"></a><b>&#167;26. </b>The integer score, used in choosing best matches:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::get_score</span><button class="popup" onclick="togglePopup('usagePopup18')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup18">Usage of <span class="code-font"><span class="function-syntax">ParseTree::get_score</span></span>:<br/><a href="2-pt.html#SP46">&#167;46</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">) { </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">score</span><span class="plain-syntax">; }</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::set_score</span><button class="popup" onclick="togglePopup('usagePopup19')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup19">Usage of <span class="code-font"><span class="function-syntax">ParseTree::set_score</span></span>:<br/><a href="2-pt.html#SP21">&#167;21</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">s</span><span class="plain-syntax">) { </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">score</span><span class="plain-syntax"> = </span><span class="identifier-syntax">s</span><span class="plain-syntax">; }</span>
</pre>
<p class="commentary firstcommentary"><a id="SP27"></a><b>&#167;27. </b>Beyond that, we have to attach something. A blank annotation is like a
blank luggage ticket, waiting to be filled out and attached to some suitcase:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="function-syntax">ParseTree::pna_new</span><button class="popup" onclick="togglePopup('usagePopup20')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup20">Usage of <span class="code-font"><span class="function-syntax">ParseTree::pna_new</span></span>:<br/><a href="2-pt.html#SP30">&#167;30</a>, <a href="2-pt.html#SP31">&#167;31</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">koa</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pna</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_of_annotation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">koa</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotation_integer</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotation_pointer</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL_GENERAL_POINTER</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pna</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP28"></a><b>&#167;28. </b>Annotations are identified by an enumerated range of constants (KOA here
stands for "kind of annotation"). Each node is permitted an arbitrary
selection of these, storing them as a linked list: it will always be short
(worst case about 5), so there is no need for a more efficient algorithm
to search this list.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::has_annotation</span><button class="popup" onclick="togglePopup('usagePopup21')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup21">Usage of <span class="code-font"><span class="function-syntax">ParseTree::has_annotation</span></span>:<br/><a href="2-pt.html#SP32">&#167;32</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PN</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">koa</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pna</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PN</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">PN</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_of_annotation</span><span class="plain-syntax"> == </span><span class="identifier-syntax">koa</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP29"></a><b>&#167;29. </b>Reading annotations is similar. We need two variant forms: one for reading
integer-valued annotations (which is most of them, as it happens) and the
other for reading pointers to structures.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::int_annotation</span><button class="popup" onclick="togglePopup('usagePopup22')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup22">Usage of <span class="code-font"><span class="function-syntax">ParseTree::int_annotation</span></span>:<br/><a href="2-pt.html#SP44_1">&#167;44.1</a>, <a href="2-pt.html#SP47">&#167;47</a>, <a href="2-pt.html#SP50">&#167;50</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PN</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">koa</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pna</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PN</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">PN</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_of_annotation</span><span class="plain-syntax"> == </span><span class="identifier-syntax">koa</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotation_integer</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="identifier-syntax">general_pointer</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::pn_pointer_annotation</span><button class="popup" onclick="togglePopup('usagePopup23')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup23">Usage of <span class="code-font"><span class="function-syntax">ParseTree::pn_pointer_annotation</span></span>:<br/><a href="2-pt.html#SP32">&#167;32</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PN</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">koa</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pna</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PN</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">PN</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_of_annotation</span><span class="plain-syntax"> == </span><span class="identifier-syntax">koa</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotation_pointer</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL_GENERAL_POINTER</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP30"></a><b>&#167;30. </b>Integer-valued annotations are set with the following routine. Note that
any second or subsequent annotation with the same KOA as an existing one
overwrites it.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::annotate_int</span><button class="popup" onclick="togglePopup('usagePopup24')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup24">Usage of <span class="code-font"><span class="function-syntax">ParseTree::annotate_int</span></span>:<br/>Sentences - <a href="2-snt.html#SP6_1">&#167;6.1</a>, <a href="2-snt.html#SP6_6">&#167;6.6</a>, <a href="2-snt.html#SP6_9">&#167;6.9</a>, <a href="2-snt.html#SP6_9_4">&#167;6.9.4</a>, <a href="2-snt.html#SP6_9_5">&#167;6.9.5</a>, <a href="2-snt.html#SP6_9_8">&#167;6.9.8</a>, <a href="2-snt.html#SP6_9_9">&#167;6.9.9</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PN</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">koa</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">v</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">newpna</span><span class="plain-syntax">, *</span><span class="identifier-syntax">pna</span><span class="plain-syntax">, *</span><span class="identifier-syntax">final</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PN</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"annotated null PN"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">PN</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_of_annotation</span><span class="plain-syntax"> == </span><span class="identifier-syntax">koa</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> an annotation with this KOA exists already: overwrite it</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotation_integer</span><span class="plain-syntax"> = </span><span class="identifier-syntax">v</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">final</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pna</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> no annotation with this KOA exists: create a new one and add to end of node's list</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">newpna</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP27" class="function-link"><span class="function-syntax">ParseTree::pna_new</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">koa</span><span class="plain-syntax">); </span><span class="identifier-syntax">newpna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotation_integer</span><span class="plain-syntax"> = </span><span class="identifier-syntax">v</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">final</span><span class="plain-syntax">) </span><span class="identifier-syntax">final</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">newpna</span><span class="plain-syntax">; </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">PN</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax"> = </span><span class="identifier-syntax">newpna</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP31"></a><b>&#167;31. </b>Again, almost identical code handles the case of pointer-valued annotations:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::pn_annotate_pointer</span><button class="popup" onclick="togglePopup('usagePopup25')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup25">Usage of <span class="code-font"><span class="function-syntax">ParseTree::pn_annotate_pointer</span></span>:<br/><a href="2-pt.html#SP32">&#167;32</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PN</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">koa</span><span class="plain-syntax">, </span><span class="identifier-syntax">general_pointer</span><span class="plain-syntax"> </span><span class="identifier-syntax">data</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PN</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"annotated null PN"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">newpna</span><span class="plain-syntax">, *</span><span class="identifier-syntax">pna</span><span class="plain-syntax">, *</span><span class="identifier-syntax">final</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">PN</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_of_annotation</span><span class="plain-syntax"> == </span><span class="identifier-syntax">koa</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> an annotation with this KOA exists already: overwrite it</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotation_pointer</span><span class="plain-syntax"> = </span><span class="identifier-syntax">data</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">final</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pna</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> no annotation with this KOA exists: create a new one and add to end of node's list</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">newpna</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP27" class="function-link"><span class="function-syntax">ParseTree::pna_new</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">koa</span><span class="plain-syntax">); </span><span class="identifier-syntax">newpna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotation_pointer</span><span class="plain-syntax"> = </span><span class="identifier-syntax">data</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">final</span><span class="plain-syntax">) </span><span class="identifier-syntax">final</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">newpna</span><span class="plain-syntax">; </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">PN</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax"> = </span><span class="identifier-syntax">newpna</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP32"></a><b>&#167;32. </b>It turns out to be convenient to access annotations with standard-form
get and set functions, for pointers, to avoid difficulties with null
pointers (which would throw run-time errors as being invalid if the store
and retrieve routines were allowed to work on them). It's also less verbose.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="identifier-syntax">MAKE_ANNOTATION_FUNCTIONS</span><span class="plain-syntax">(</span><span class="identifier-syntax">annotation_name</span><span class="plain-syntax">, </span><span class="identifier-syntax">pointer_type</span><span class="plain-syntax">)</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="identifier-syntax">ParseTree::set_</span><span class="plain-syntax">##</span><span class="identifier-syntax">annotation_name</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">pointer_type</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP31" class="function-link"><span class="function-syntax">ParseTree::pn_annotate_pointer</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">annotation_name</span><span class="plain-syntax">##</span><span class="identifier-syntax">_ANNOT</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">STORE_POINTER_</span><span class="plain-syntax">##</span><span class="identifier-syntax">pointer_type</span><span class="plain-syntax">(</span><span class="identifier-syntax">bp</span><span class="plain-syntax">));</span>
<span class="plain-syntax">}</span>
<span class="identifier-syntax">pointer_type</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ParseTree::get_</span><span class="plain-syntax">##</span><span class="identifier-syntax">annotation_name</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pointer_type</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP28" class="function-link"><span class="function-syntax">ParseTree::has_annotation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">annotation_name</span><span class="plain-syntax">##</span><span class="identifier-syntax">_ANNOT</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">RETRIEVE_POINTER_</span><span class="plain-syntax">##</span><span class="identifier-syntax">pointer_type</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP29" class="function-link"><span class="function-syntax">ParseTree::pn_pointer_annotation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">annotation_name</span><span class="plain-syntax">##</span><span class="identifier-syntax">_ANNOT</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">pt</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP33"></a><b>&#167;33. Copying parse nodes. </b>If we want to duplicate a parse node, we cannot do so with a shallow bit copy:
the node points to a list of its annotations, and the duplicated node would
therefore point to the same list. If, subsequently, one of the two nodes
were annotated further, then the other would change in synchrony, which
would be the source of mysterious bugs. We therefore need to perform a
deep copy which duplicates not only the node, but also its annotation list.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::copy</span><button class="popup" onclick="togglePopup('usagePopup26')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup26">Usage of <span class="code-font"><span class="function-syntax">ParseTree::copy</span></span>:<br/><a href="2-pt.html#SP34">&#167;34</a>, <a href="2-pt.html#SP35">&#167;35</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">from</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">COPY</span><span class="plain-syntax">(</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pna</span><span class="plain-syntax">, *</span><span class="identifier-syntax">latest</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pna_copy</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> *</span><span class="identifier-syntax">pna_copy</span><span class="plain-syntax"> = *</span><span class="identifier-syntax">pna</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">PARSE_TREE_COPIER</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PARSE_TREE_COPIER</span><span class="plain-syntax">(</span><span class="identifier-syntax">pna_copy</span><span class="plain-syntax">, </span><span class="identifier-syntax">pna</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pna_copy</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pna_copy</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">latest</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pna_copy</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">latest</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pna_copy</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="function-syntax">ParseTree::duplicate</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">dup</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP21" class="function-link"><span class="function-syntax">ParseTree::new</span></a><span class="plain-syntax">(</span><span class="constant-syntax">INVALID_NT</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP33" class="function-link"><span class="function-syntax">ParseTree::copy</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">dup</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">dup</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP34"></a><b>&#167;34. </b>This variation preserves links out.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::copy_in_place</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">from</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">next_link</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">alt_link</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">down_link</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP33" class="function-link"><span class="function-syntax">ParseTree::copy</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax"> = </span><span class="identifier-syntax">next_link</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax"> = </span><span class="identifier-syntax">alt_link</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax"> = </span><span class="identifier-syntax">down_link</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP35"></a><b>&#167;35. </b>And to deep-copy a whole subtree:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::copy_subtree</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">level</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">from</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">to</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Null deep copy"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP33" class="function-link"><span class="function-syntax">ParseTree::copy</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">to</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP21" class="function-link"><span class="function-syntax">ParseTree::new</span></a><span class="plain-syntax">(</span><span class="constant-syntax">INVALID_NT</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP35" class="function-link"><span class="function-syntax">ParseTree::copy_subtree</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">level</span><span class="plain-syntax">+1);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">level</span><span class="plain-syntax">&gt;0) &amp;&amp; (</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP21" class="function-link"><span class="function-syntax">ParseTree::new</span></a><span class="plain-syntax">(</span><span class="constant-syntax">INVALID_NT</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP35" class="function-link"><span class="function-syntax">ParseTree::copy_subtree</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">, </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">, </span><span class="identifier-syntax">level</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">level</span><span class="plain-syntax">&gt;0) &amp;&amp; (</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP21" class="function-link"><span class="function-syntax">ParseTree::new</span></a><span class="plain-syntax">(</span><span class="constant-syntax">INVALID_NT</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP35" class="function-link"><span class="function-syntax">ParseTree::copy_subtree</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">, </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">, </span><span class="identifier-syntax">level</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP36"></a><b>&#167;36. Child count. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::no_children</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax">=0;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">pn</span><span class="plain-syntax">)?(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">):</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) </span><span class="identifier-syntax">c</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">c</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP37"></a><b>&#167;37. Detection of subnodes. </b>This is needed when producing problem messages: we may need to work up from
an arbitrary leaf to the main sentence branch containing it. At any rate,
given a node <span class="extract"><span class="extract-syntax">PN</span></span>, we want to know if another node <span class="extract"><span class="extract-syntax">to_find</span></span> lies beneath
it. (This will never be called when <span class="extract"><span class="extract-syntax">PN</span></span> is the root, and from all other
nodes it will certainly run quickly, since the tree is otherwise neither
wide nor deep.)
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::contains</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PN</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to_find</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">to_try</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PN</span><span class="plain-syntax"> == </span><span class="identifier-syntax">to_find</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">to_try</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PN</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">; </span><span class="identifier-syntax">to_try</span><span class="plain-syntax">; </span><span class="identifier-syntax">to_try</span><span class="plain-syntax"> = </span><span class="identifier-syntax">to_try</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP37" class="function-link"><span class="function-syntax">ParseTree::contains</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">to_try</span><span class="plain-syntax">, </span><span class="identifier-syntax">to_find</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP38"></a><b>&#167;38. The word range beneath a given node. </b>Any given node may be the root of a subtree concerning the structure of
a given contiguous range of words in the original source text. The
"left edge" of a node <span class="extract"><span class="extract-syntax">PN</span></span> is the least-numbered word considered by any
node at or below <span class="extract"><span class="extract-syntax">PN</span></span> in the tree; the "right edge" is the highest-numbered
word similarly considered.
</p>
<p class="commentary">The left edge is calculated by taking the minimum value of the word number
for <span class="extract"><span class="extract-syntax">PN</span></span> and the left edges of its children, except that \(-1\) is not counted.
(A left edge of \(-1\) means no source text is here.)
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::left_edge_of</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PN</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">child</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">l</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><a href="2-pt.html#SP23" class="function-link"><span class="function-syntax">ParseTree::get_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">PN</span><span class="plain-syntax">)), </span><span class="identifier-syntax">lc</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">child</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PN</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">; </span><span class="identifier-syntax">child</span><span class="plain-syntax">; </span><span class="identifier-syntax">child</span><span class="plain-syntax"> = </span><span class="identifier-syntax">child</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">lc</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP38" class="function-link"><span class="function-syntax">ParseTree::left_edge_of</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">child</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">lc</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; ((</span><span class="identifier-syntax">l</span><span class="plain-syntax"> == -1) || (</span><span class="identifier-syntax">lc</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">l</span><span class="plain-syntax">))) </span><span class="identifier-syntax">l</span><span class="plain-syntax"> = </span><span class="identifier-syntax">lc</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">l</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP39"></a><b>&#167;39. </b>Symmetrically, the right edge is found by taking the maximum word number
for <span class="extract"><span class="extract-syntax">PN</span></span> and the right edges of its children.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::right_edge_of</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">PN</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">child</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">r</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Wordings::last_wn</span><span class="plain-syntax">(</span><a href="2-pt.html#SP23" class="function-link"><span class="function-syntax">ParseTree::get_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">PN</span><span class="plain-syntax">)), </span><span class="identifier-syntax">rc</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><a href="2-pt.html#SP23" class="function-link"><span class="function-syntax">ParseTree::get_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">PN</span><span class="plain-syntax">)) &lt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">r</span><span class="plain-syntax"> = -1;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">child</span><span class="plain-syntax"> = </span><span class="identifier-syntax">PN</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">; </span><span class="identifier-syntax">child</span><span class="plain-syntax">; </span><span class="identifier-syntax">child</span><span class="plain-syntax"> = </span><span class="identifier-syntax">child</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">rc</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP39" class="function-link"><span class="function-syntax">ParseTree::right_edge_of</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">child</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">rc</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; ((</span><span class="identifier-syntax">r</span><span class="plain-syntax"> == -1) || (</span><span class="identifier-syntax">rc</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">r</span><span class="plain-syntax">))) </span><span class="identifier-syntax">r</span><span class="plain-syntax"> = </span><span class="identifier-syntax">rc</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">r</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP40"></a><b>&#167;40. </b>Every node in the tree is indirectly a child of the root node. Such trees
tends to be very wide: since each sentence in the original source text is a
different child of the root, the root may have 5000 or so children, though
the maximum depth of the tree might be only 10.
</p>
<p class="commentary">That means that perpetually scanning through them in order to add another one
on the end is inefficient: so we cache the "last sentence" in the tree,
meaning, the youngest child of root. (But we must only do this when we are not
also performing surgery on the tree at the same time, which is why it is not
always allowed.)
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">youngest_child_of_root</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="comment-syntax"> youngest child of tree root</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">allow_last_sentence_cacheing</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::enable_last_sentence_cacheing</span><button class="popup" onclick="togglePopup('usagePopup27')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup27">Usage of <span class="code-font"><span class="function-syntax">ParseTree::enable_last_sentence_cacheing</span></span>:<br/>Sentences - <a href="2-snt.html#SP5">&#167;5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">youngest_child_of_root</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="comment-syntax"> because this may have changed since last enabled</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">allow_last_sentence_cacheing</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::disable_last_sentence_cacheing</span><button class="popup" onclick="togglePopup('usagePopup28')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup28">Usage of <span class="code-font"><span class="function-syntax">ParseTree::disable_last_sentence_cacheing</span></span>:<br/>Sentences - <a href="2-snt.html#SP5">&#167;5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">allow_last_sentence_cacheing</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP41"></a><b>&#167;41. </b>Now the metaphors get mixed. The routine below is called <span class="extract"><span class="extract-syntax">ParseTree::graft</span></span>
by analogy with gardening, where the rootstock of one plant is joined to a
scion (or cutting) of another, so that a root chosen for strength can be
combined with the fruits or blossom of the scion. This is fairly apt for
the process of joining one subtree onto a node of another. But since
gardening lacks words to describe branches as being eldest or youngest,
and so on, for the actual body of the routine we talk about family trees
instead.
</p>
<p class="commentary"><span class="extract"><span class="extract-syntax">ParseTree::graft</span></span> returns the node for which <span class="extract"><span class="extract-syntax">newborn</span></span> is the immediate sibling,
that is, it returns the previously youngest child of the <span class="extract"><span class="extract-syntax">parent</span></span> (or <span class="extract"><span class="extract-syntax">NULL</span></span>
if it previously had no children).
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="function-syntax">ParseTree::graft</span><button class="popup" onclick="togglePopup('usagePopup29')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup29">Usage of <span class="code-font"><span class="function-syntax">ParseTree::graft</span></span>:<br/><a href="2-pt.html#SP44">&#167;44</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">newborn</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parent</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">elder</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">newborn</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"newborn is null in tree ParseTree::graft"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">parent</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"parent is null in tree ParseTree::graft"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> is the new node to be the only child of the old?</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">parent</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">parent</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax"> = </span><span class="identifier-syntax">newborn</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> can last sentence cacheing save us a long search through many children of root?</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">parent</span><span class="plain-syntax"> == </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">allow_last_sentence_cacheing</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">youngest_child_of_root</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">elder</span><span class="plain-syntax"> = </span><span class="identifier-syntax">youngest_child_of_root</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">elder</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax"> = </span><span class="identifier-syntax">newborn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">youngest_child_of_root</span><span class="plain-syntax"> = </span><span class="identifier-syntax">newborn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">elder</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> we don't know who's the youngest child now, but we know who soon will be:</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">youngest_child_of_root</span><span class="plain-syntax"> = </span><span class="identifier-syntax">newborn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> find youngest child of attach node...</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">elder</span><span class="plain-syntax"> = </span><span class="identifier-syntax">parent</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">; </span><span class="identifier-syntax">elder</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">; </span><span class="identifier-syntax">elder</span><span class="plain-syntax"> = </span><span class="identifier-syntax">elder</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) ;</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> ...and make the new node its younger sibling</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">elder</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next</span><span class="plain-syntax"> = </span><span class="identifier-syntax">newborn</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">elder</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP42"></a><b>&#167;42. </b>No speed worries on the much smaller trees with alternative readings:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="function-syntax">ParseTree::graft_alternative</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">newborn</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parent</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">newborn</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"newborn is null in tree ParseTree::graft_alternative"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">parent</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"parent is null in tree ParseTree::graft_alternative"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> is the new node to be the only child of the old?</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">parent</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">parent</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax"> = </span><span class="identifier-syntax">newborn</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> find youngest child of attach node...</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">elder</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">elder</span><span class="plain-syntax"> = </span><span class="identifier-syntax">parent</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">; </span><span class="identifier-syntax">elder</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">; </span><span class="identifier-syntax">elder</span><span class="plain-syntax"> = </span><span class="identifier-syntax">elder</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">) ;</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> ...and make the new node its younger sibling</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">elder</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax"> = </span><span class="identifier-syntax">newborn</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">elder</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP43"></a><b>&#167;43. </b>And we can loop through these like so:
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="identifier-syntax">LOOP_THROUGH_ALTERNATIVES</span><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">from</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">)</span>
</pre>
<p class="commentary firstcommentary"><a id="SP44"></a><b>&#167;44. </b>Sentences are attached as so: at the one-off point if set, or at the
relevant stacked position.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::insert_sentence</span><button class="popup" onclick="togglePopup('usagePopup30')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup30">Usage of <span class="code-font"><span class="function-syntax">ParseTree::insert_sentence</span></span>:<br/>Sentences - <a href="2-snt.html#SP6_1">&#167;6.1</a>, <a href="2-snt.html#SP6_6">&#167;6.6</a>, <a href="2-snt.html#SP6_9_4">&#167;6.9.4</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">new</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">one_off_attachment_point</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax"> = </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">one_off_attachment_point</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">one_off_attachment_point</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax"> = </span><span class="identifier-syntax">new</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">new</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax"> = </span><span class="identifier-syntax">L</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">one_off_attachment_point</span><span class="plain-syntax"> = </span><span class="identifier-syntax">new</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">attachment_sp</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no attachment point"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::get_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">new</span><span class="plain-syntax">) == </span><span class="constant-syntax">HEADING_NT</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="2-pt.html#SP44_1" class="named-paragraph-link"><span class="named-paragraph">Adjust attachment point for a heading</span><span class="named-paragraph-number">44.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sentence_attachment_point</span><span class="plain-syntax"> = </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">attachment_stack_parent</span><span class="plain-syntax">[</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">attachment_sp</span><span class="plain-syntax">-1];</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP41" class="function-link"><span class="function-syntax">ParseTree::graft</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="identifier-syntax">new</span><span class="plain-syntax">, </span><span class="identifier-syntax">sentence_attachment_point</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::get_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">new</span><span class="plain-syntax">) == </span><span class="constant-syntax">HEADING_NT</span><span class="plain-syntax">) </span><a href="2-pt.html#SP2" class="function-link"><span class="function-syntax">ParseTree::push_attachment_point</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="identifier-syntax">new</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP44_1"></a><b>&#167;44.1. </b>When what's attached is a heading node, that changes the stack, of course:
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Adjust attachment point for a heading</span><span class="named-paragraph-number">44.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">heading_level</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP29" class="function-link"><span class="function-syntax">ParseTree::int_annotation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">new</span><span class="plain-syntax">, </span><span class="constant-syntax">heading_level_ANNOT</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">heading_level</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">attachment_sp</span><span class="plain-syntax">-1; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&gt;=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">--) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">attachment_stack_parent</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::get_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">) == </span><span class="constant-syntax">HEADING_NT</span><span class="plain-syntax">) &amp;&amp;</span>
<span class="plain-syntax"> (</span><a href="2-pt.html#SP29" class="function-link"><span class="function-syntax">ParseTree::int_annotation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="constant-syntax">heading_level_ANNOT</span><span class="plain-syntax">) &gt;= </span><span class="identifier-syntax">heading_level</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">attachment_sp</span><span class="plain-syntax"> = </span><span class="identifier-syntax">i</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pt.html#SP44">&#167;44</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP45"></a><b>&#167;45. Logging the parse tree. </b>For most trees, logging is a fearsome prospect, but here we only mean printing
out a textual representation to the debugging log.
</p>
<p class="commentary">There are two ways to recurse through it: logging the entire tree as seen from
a given node, or logging just the "subtree" of that node: meaning, itself and
everything beneath it, but not its siblings or alternatives. Each recursion
has its own unique token value, used to prevent infinite loops in the event
that we're logging a badly-formed tree; this should never happen, but since
logging is a diagnostic tool, we want it to work even when Inform is sick.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">pn_log_token</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::log_tree</span><button class="popup" onclick="togglePopup('usagePopup31')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup31">Usage of <span class="code-font"><span class="function-syntax">ParseTree::log_tree</span></span>:<br/><a href="2-pt.html#SP49">&#167;49</a><br/>Syntax Module - <a href="1-sm.html#SP3_5">&#167;3.5</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">vpn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *) </span><span class="identifier-syntax">vpn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pn</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;null-meaning-list&gt;\n"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP46" class="function-link"><span class="function-syntax">ParseTree::log_subtree_recursively</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">, ++</span><span class="identifier-syntax">pn_log_token</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::log_subtree</span><button class="popup" onclick="togglePopup('usagePopup32')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup32">Usage of <span class="code-font"><span class="function-syntax">ParseTree::log_subtree</span></span>:<br/>Syntax Module - <a href="1-sm.html#SP3_5">&#167;3.5</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">vpn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *) </span><span class="identifier-syntax">vpn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pn</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;null-parse-node&gt;"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"$P\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG_INDENT</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP46" class="function-link"><span class="function-syntax">ParseTree::log_subtree_recursively</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">, ++</span><span class="identifier-syntax">pn_log_token</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG_OUTDENT</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP46"></a><b>&#167;46. </b>Either way, we recurse as follows, being careful not to make recursive calls
to pursue <span class="extract"><span class="extract-syntax">next</span></span> links, since otherwise a source text with more than 100,000
sentences or so will exceed the typical stack size Inform has to run in.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::log_subtree_recursively</span><button class="popup" onclick="togglePopup('usagePopup33')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup33">Usage of <span class="code-font"><span class="function-syntax">ParseTree::log_subtree_recursively</span></span>:<br/><a href="2-pt.html#SP45">&#167;45</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">num</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">of</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">gen</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">ltime</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">log_time</span><span class="plain-syntax"> == </span><span class="identifier-syntax">ltime</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"*** Not a tree: %W ***\n"</span><span class="plain-syntax">, </span><a href="2-pt.html#SP23" class="function-link"><span class="function-syntax">ParseTree::get_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">)); </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">log_time</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ltime</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pt.html#SP46_1" class="named-paragraph-link"><span class="named-paragraph">Calculate num and of such that this is [num/of] if they aren't already supplied</span><span class="named-paragraph-number">46.1</span></a></span><span class="character-syntax">;</span>
<span class="character-syntax"> if (pn == NULL) { WRITE("&lt;null-parse-node&gt;\n"); return; }</span>
<span class="character-syntax"> if (of &gt; 1) {</span>
<span class="character-syntax"> WRITE("[%d/%d] ", num, of);</span>
<span class="character-syntax"> if (ParseTree::get_score(pn) != 0) WRITE("(score %d) ", ParseTree::get_score(pn));</span>
<span class="character-syntax"> }</span>
<span class="character-syntax"> WRITE("$P\n", pn);</span>
<span class="character-syntax"> if (pn-&gt;down) {</span>
<span class="character-syntax"> LOG_INDENT;</span>
<span class="character-syntax"> ParseTree::log_subtree_recursively(OUT, pn-&gt;down, 0, 0, gen+1, ltime);</span>
<span class="character-syntax"> LOG_OUTDENT;</span>
<span class="character-syntax"> }</span>
<span class="character-syntax"> if (pn-&gt;next_alternative) ParseTree::log_subtree_recursively(OUT, pn-&gt;next_alternative, num+1, of, gen+1, ltime);</span>
<span class="character-syntax"> pn = pn-&gt;next; num = 0; of = 0; gen++;</span>
<span class="character-syntax"> }</span>
<span class="character-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP46_1"></a><b>&#167;46.1. </b>When the first alternative is called, <span class="extract"><span class="extract-syntax">ParseTree::log_subtree_recursively</span></span>
has arguments 0 and 0 for the possibility. The following code finds out the
correct value for <span class="extract"><span class="extract-syntax">of</span></span>, setting this possibility to be <span class="extract"><span class="extract-syntax">[1/of]</span></span>. When we later
iterate through other alternatives, we pass on correct values of <span class="extract"><span class="extract-syntax">num</span></span> and <span class="extract"><span class="extract-syntax">of</span></span>,
so that this code won't be used again on the same horizontal list of possibilities.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Calculate num and of such that this is [num/of] if they aren't already supplied</span><span class="named-paragraph-number">46.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">num</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn2</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pn2</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">of</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn2</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn2</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn2</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">, </span><span class="identifier-syntax">of</span><span class="plain-syntax">++) ;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">num</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pt.html#SP46">&#167;46</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP47"></a><b>&#167;47. </b>All of those routines make use of the following, which actually performs
the log of a parse node. Note that this always produces exactly one line of
text in the debugging log.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::log_node</span><button class="popup" onclick="togglePopup('usagePopup34')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup34">Usage of <span class="code-font"><span class="function-syntax">ParseTree::log_node</span></span>:<br/>Syntax Module - <a href="1-sm.html#SP3_5">&#167;3.5</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">OUTPUT_STREAM</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">vpn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = (</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *) </span><span class="identifier-syntax">vpn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pn</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;null-parse-node&gt;\n"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">PARSE_TREE_LOGGER</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">PARSE_TREE_LOGGER</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="reserved-syntax">else</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP20" class="function-link"><span class="function-syntax">ParseTree::log_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, (</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::nonempty</span><span class="plain-syntax">(</span><a href="2-pt.html#SP23" class="function-link"><span class="function-syntax">ParseTree::get_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">))) </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"'%W'"</span><span class="plain-syntax">, </span><a href="2-pt.html#SP23" class="function-link"><span class="function-syntax">ParseTree::get_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">LINGUISTICS_MODULE</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Diagrams::log_node</span><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">switch</span><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">HEADING_NT:</span><span class="plain-syntax"> </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">" (level %d)"</span><span class="plain-syntax">, </span><a href="2-pt.html#SP29" class="function-link"><span class="function-syntax">ParseTree::int_annotation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="constant-syntax">heading_level_ANNOT</span><span class="plain-syntax">)); </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">a</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">a</span><span class="plain-syntax">&lt;9)) </span><span class="identifier-syntax">a</span><span class="plain-syntax">++, </span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">a</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">WRITE</span><span class="plain-syntax">(</span><span class="string-syntax">"/%d"</span><span class="plain-syntax">, </span><span class="identifier-syntax">a</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP48"></a><b>&#167;48. </b>This is occasionally useful:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::log_with_annotations</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Diagnosis $P"</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pna</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"-%d"</span><span class="plain-syntax">, </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_of_annotation</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP49"></a><b>&#167;49. </b>Inform also has a mechanism for dumping the entire parse tree to a file,
really just for testing purposes:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::write_to_file</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="identifier-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">F</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> </span><span class="identifier-syntax">parse_tree_file</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">STREAM_OPEN_TO_FILE</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">parse_tree_file</span><span class="plain-syntax">, </span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="identifier-syntax">ISO_ENC</span><span class="plain-syntax">) == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"can't open file to write parse tree"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">save_DL</span><span class="plain-syntax"> = </span><span class="identifier-syntax">DL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DL</span><span class="plain-syntax"> = &amp;</span><span class="identifier-syntax">parse_tree_file</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Streams::enable_debugging</span><span class="plain-syntax">(</span><span class="identifier-syntax">DL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP45" class="function-link"><span class="function-syntax">ParseTree::log_tree</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">DL</span><span class="plain-syntax">, </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DL</span><span class="plain-syntax"> = </span><span class="identifier-syntax">save_DL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">STREAM_CLOSE</span><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">parse_tree_file</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP50"></a><b>&#167;50. General traversals. </b>It's convenient to have a general system for traversing the tree, visiting
each node in the connected component of the tree root. Unlike the logging
routine above, these all assume that the tree is well-formed.
</p>
<pre class="definitions code-font"><span class="plain-syntax">@</span><span class="reserved-syntax">default</span><span class="plain-syntax"> </span><span class="constant-syntax">PARSE_TREE_TRAVERSE_TYPE</span><span class="plain-syntax"> </span><span class="reserved-syntax">void</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *)) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_from</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">SCS</span><span class="plain-syntax"> = </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (; </span><span class="identifier-syntax">pn</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::top_level</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::visitable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP51" class="function-link"><span class="function-syntax">ParseTree::sentence_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">SCS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_dfirst</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *)) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_dfirst_from</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_dfirst_from</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">SCS</span><span class="plain-syntax"> = </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (; </span><span class="identifier-syntax">pn</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_dfirst_from</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP51" class="function-link"><span class="function-syntax">ParseTree::sentence_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">SCS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_wfirst</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *)) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_wfirst_from</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_wfirst_from</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">SCS</span><span class="plain-syntax"> = </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (; </span><span class="identifier-syntax">pn</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP51" class="function-link"><span class="function-syntax">ParseTree::sentence_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_wfirst_from</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">SCS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_with_stream</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *)) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_with_stream</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_from_with_stream</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">SCS</span><span class="plain-syntax"> = </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (; </span><span class="identifier-syntax">pn</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::top_level</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_with_stream</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::visitable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP51" class="function-link"><span class="function-syntax">ParseTree::sentence_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="identifier-syntax">OUT</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">SCS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_int</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *), </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *</span><span class="identifier-syntax">X</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_int</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_from_int</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *), </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *</span><span class="identifier-syntax">X</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">SCS</span><span class="plain-syntax"> = </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (; </span><span class="identifier-syntax">pn</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::top_level</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_int</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::visitable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP51" class="function-link"><span class="function-syntax">ParseTree::sentence_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">SCS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_int_int</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *), </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *</span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *</span><span class="identifier-syntax">Y</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_int_int</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="identifier-syntax">Y</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_from_int_int</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *), </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *</span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *</span><span class="identifier-syntax">Y</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">SCS</span><span class="plain-syntax"> = </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (; </span><span class="identifier-syntax">pn</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::top_level</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_int_int</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="identifier-syntax">Y</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::visitable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP51" class="function-link"><span class="function-syntax">ParseTree::sentence_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">, </span><span class="identifier-syntax">Y</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">SCS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_ppn</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> **), </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> **</span><span class="identifier-syntax">X</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_ppn</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_from_ppn</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> **), </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> **</span><span class="identifier-syntax">X</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">SCS</span><span class="plain-syntax"> = </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (; </span><span class="identifier-syntax">pn</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::top_level</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_ppn</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::visitable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP51" class="function-link"><span class="function-syntax">ParseTree::sentence_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">SCS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_ppni</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *), </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *</span><span class="identifier-syntax">N</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_ppni</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">N</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_from_ppni</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *), </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">last_h0</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *</span><span class="identifier-syntax">N</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">SCS</span><span class="plain-syntax"> = </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (; </span><span class="identifier-syntax">pn</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::top_level</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">H0</span><span class="plain-syntax"> = </span><span class="identifier-syntax">last_h0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::is</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="constant-syntax">HEADING_NT</span><span class="plain-syntax">)) &amp;&amp; (</span><a href="2-pt.html#SP29" class="function-link"><span class="function-syntax">ParseTree::int_annotation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="constant-syntax">heading_level_ANNOT</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">H0</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_ppni</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">, </span><span class="identifier-syntax">H0</span><span class="plain-syntax">, </span><span class="identifier-syntax">N</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::visitable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP51" class="function-link"><span class="function-syntax">ParseTree::sentence_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">last_h0</span><span class="plain-syntax">, </span><span class="identifier-syntax">N</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">SCS</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_up_to_ip</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">end</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="constant-syntax">PARSE_TREE_TRAVERSE_TYPE</span><span class="plain-syntax"> **), </span><span class="constant-syntax">PARSE_TREE_TRAVERSE_TYPE</span><span class="plain-syntax"> **</span><span class="identifier-syntax">X</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_up_to_ip</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">end</span><span class="plain-syntax">, </span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_from_up_to_ip</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">end</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="constant-syntax">PARSE_TREE_TRAVERSE_TYPE</span><span class="plain-syntax"> **), </span><span class="constant-syntax">PARSE_TREE_TRAVERSE_TYPE</span><span class="plain-syntax"> **</span><span class="identifier-syntax">X</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">SCS</span><span class="plain-syntax"> = </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (; </span><span class="identifier-syntax">pn</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pn</span><span class="plain-syntax"> == </span><span class="identifier-syntax">end</span><span class="plain-syntax">) { </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">SCS</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::top_level</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_up_to_ip</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">end</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">SCS</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::visitable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP51" class="function-link"><span class="function-syntax">ParseTree::sentence_node</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">SCS</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_ppn_nocs</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> **), </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> **</span><span class="identifier-syntax">X</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_ppn_nocs</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::traverse_from_ppn_nocs</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> **), </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> **</span><span class="identifier-syntax">X</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (; </span><span class="identifier-syntax">pn</span><span class="plain-syntax">; </span><span class="identifier-syntax">pn</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::visitable</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((*</span><span class="identifier-syntax">visitor</span><span class="plain-syntax">)(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">)) { </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::top_level</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">node_type</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">res</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP50" class="function-link"><span class="function-syntax">ParseTree::traverse_from_ppn_nocs</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pn</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">visitor</span><span class="plain-syntax">, </span><span class="identifier-syntax">pn</span><span class="plain-syntax">, </span><span class="identifier-syntax">X</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">res</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP51"></a><b>&#167;51. </b>This provides a way for users of the module to indicate what's a sentence:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::sentence_node</span><button class="popup" onclick="togglePopup('usagePopup35')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup35">Usage of <span class="code-font"><span class="function-syntax">ParseTree::sentence_node</span></span>:<br/><a href="2-pt.html#SP50">&#167;50</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">SENTENCE_NODE</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">SENTENCE_NODE</span><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifndef</span><span class="plain-syntax"> </span><span class="identifier-syntax">SENTENCE_NODE</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP52"></a><b>&#167;52. Verify integrity. </b>The first duty of a tree is to contain no loops, and the following checks
that (rejecting even undirected loops). In addition, it checks that each
node has an enumerated node type, rather than a meaning code.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">tree_stats_size</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">tree_stats_depth</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">, </span><span class="identifier-syntax">tree_stats_width</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::verify_integrity</span><button class="popup" onclick="togglePopup('usagePopup36')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup36">Usage of <span class="code-font"><span class="function-syntax">ParseTree::verify_integrity</span></span>:<br/><a href="2-pt.html#SP54">&#167;54</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">worth_logging</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tree_stats_size</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">tree_stats_depth</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">tree_stats_width</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP53" class="function-link"><span class="function-syntax">ParseTree::verify_tree_integrity_recursively</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="string-syntax">"down"</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">, ++</span><span class="identifier-syntax">pn_log_token</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">worth_logging</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">VERIFICATIONS</span><span class="plain-syntax">, </span><span class="string-syntax">"[Initial parse tree has %d nodes, width %d and depth %d.]\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">tree_stats_size</span><span class="plain-syntax">, </span><span class="identifier-syntax">tree_stats_width</span><span class="plain-syntax">, </span><span class="identifier-syntax">tree_stats_depth</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP53"></a><b>&#167;53. </b>The verification traverse is a very cautious manoeuvre: we step through
the tree, testing each branch with our outstretched foot in case it might
be illusory or broken. At the first sign of trouble we panic.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::verify_tree_integrity_recursively</span><button class="popup" onclick="togglePopup('usagePopup37')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup37">Usage of <span class="code-font"><span class="function-syntax">ParseTree::verify_tree_integrity_recursively</span></span>:<br/><a href="2-pt.html#SP52">&#167;52</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">way</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">depth</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">ltime</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">width</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pointer_sized_int</span><span class="plain-syntax"> </span><span class="identifier-syntax">probably_an_address</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">pointer_sized_int</span><span class="plain-syntax">) </span><span class="identifier-syntax">p</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">depth</span><span class="plain-syntax">++; </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">depth</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">tree_stats_depth</span><span class="plain-syntax">) </span><span class="identifier-syntax">tree_stats_depth</span><span class="plain-syntax"> = </span><span class="identifier-syntax">depth</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">width</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax">; </span><span class="identifier-syntax">p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">, </span><span class="identifier-syntax">width</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">probably_an_address</span><span class="plain-syntax"> == </span><span class="constant-syntax">0</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">probably_an_address</span><span class="plain-syntax"> == -1)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Link %s broken from:\n$P"</span><span class="plain-syntax">, </span><span class="identifier-syntax">way</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Errors::set_internal_handler</span><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Link broken in parse tree"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">log_time</span><span class="plain-syntax"> == </span><span class="identifier-syntax">ltime</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Cycle found in parse tree, found %s from:\n$P"</span><span class="plain-syntax">, </span><span class="identifier-syntax">way</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Errors::set_internal_handler</span><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Cycle found in parse tree"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">log_time</span><span class="plain-syntax"> = </span><span class="identifier-syntax">ltime</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::get_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::valid_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">)) </span><span class="identifier-syntax">tree_stats_size</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Invalid node type (%08x) found %s from:\n$P"</span><span class="plain-syntax">, (</span><span class="reserved-syntax">int</span><span class="plain-syntax">) </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">way</span><span class="plain-syntax">, </span><span class="identifier-syntax">from</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Errors::set_internal_handler</span><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Link broken in parse tree"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP53" class="function-link"><span class="function-syntax">ParseTree::verify_tree_integrity_recursively</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="string-syntax">"alt"</span><span class="plain-syntax">, </span><span class="identifier-syntax">depth</span><span class="plain-syntax">, </span><span class="identifier-syntax">ltime</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP53" class="function-link"><span class="function-syntax">ParseTree::verify_tree_integrity_recursively</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="string-syntax">"down"</span><span class="plain-syntax">, </span><span class="identifier-syntax">depth</span><span class="plain-syntax">, </span><span class="identifier-syntax">ltime</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">width</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">tree_stats_width</span><span class="plain-syntax">) </span><span class="identifier-syntax">tree_stats_width</span><span class="plain-syntax"> = </span><span class="identifier-syntax">width</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP54"></a><b>&#167;54. Verify structure. </b>The parse tree is a complicated structure, arbitrarily wide and deep, and
containing many different node types, each subject to its own rules of usage.
(For instance, a <span class="extract"><span class="extract-syntax">SENTENCE_NT</span></span> node cannot legally be beneath a
<span class="extract"><span class="extract-syntax">PROPER_NOUN_NT</span></span> one.) This is both good and bad: bad because complexity is
always the enemy of program correctness, good because it gives us an
independent opportunity to test a great deal of what earlier code has done.
If, given every test case, we always construct a well-formed tree, we must be
doing something right.
</p>
<p class="commentary">The collection of rules like this which the tree must satisfy is called its
"invariant", and is expressed by the code below. Note that this is
verification, not an attempt to correct matters. If any test fails, Inform
will stop with an internal error. (If there are multiple failures, we
itemise them to the debugging log, and only produce a single internal error
at the end.)
</p>
<p class="commentary">We protect ourselves by first checking that the tree is intact as a
structure: once we know the tree is safe to climb over, we can wander
about counting children with impunity.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::verify</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">T</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">VERIFICATIONS</span><span class="plain-syntax">, </span><span class="string-syntax">"[Verifying initial parse tree]\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">root_node</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Errors::set_internal_handler</span><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Root of parse tree NULL"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP54" class="function-link"><span class="function-syntax">ParseTree::verify_structure</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">T</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">root_node</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOGIF</span><span class="plain-syntax">(</span><span class="identifier-syntax">VERIFICATIONS</span><span class="plain-syntax">, </span><span class="string-syntax">"[Initial parse tree correct.]\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">node_errors</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::verify_structure</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP52" class="function-link"><span class="function-syntax">ParseTree::verify_integrity</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP56" class="function-link"><span class="function-syntax">ParseTree::make_parentage_allowed_table</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP59" class="function-link"><span class="function-syntax">ParseTree::make_annotation_allowed_table</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">node_errors</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP55" class="function-link"><span class="function-syntax">ParseTree::verify_structure_recursively</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">node_errors</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">0</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"[Verification failed: %d node errors]\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">node_errors</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Errors::set_internal_handler</span><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"Parse tree broken"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP55"></a><b>&#167;55. </b>Note that on every call to the following routine, (i) <span class="extract"><span class="extract-syntax">p</span></span> is a valid
parse node and (ii) either <span class="extract"><span class="extract-syntax">p</span></span> is the tree root, in which case <span class="extract"><span class="extract-syntax">parent</span></span> is
<span class="extract"><span class="extract-syntax">NULL</span></span>, or <span class="extract"><span class="extract-syntax">parent</span></span> is the unique node having <span class="extract"><span class="extract-syntax">p</span></span> (or an alternative to <span class="extract"><span class="extract-syntax">p</span></span>)
among its children.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::verify_structure_recursively</span><button class="popup" onclick="togglePopup('usagePopup38')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup38">Usage of <span class="code-font"><span class="function-syntax">ParseTree::verify_structure_recursively</span></span>:<br/><a href="2-pt.html#SP54">&#167;54</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">p</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">parent</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::get_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax"> *</span><span class="identifier-syntax">metadata</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP18" class="function-link"><span class="function-syntax">ParseTree::node_metadata</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">metadata</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"broken tree should have been reported"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pt.html#SP55_1" class="named-paragraph-link"><span class="named-paragraph">Check rule (1) of the invariant</span><span class="named-paragraph-number">55.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pt.html#SP55_2" class="named-paragraph-link"><span class="named-paragraph">Check rule (2) of the invariant</span><span class="named-paragraph-number">55.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">parent</span><span class="plain-syntax">) </span><span class="named-paragraph-container code-font"><a href="2-pt.html#SP55_3" class="named-paragraph-link"><span class="named-paragraph">Check rule (3) of the invariant</span><span class="named-paragraph-number">55.3</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">children_count</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">q</span><span class="plain-syntax">=</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">; </span><span class="identifier-syntax">q</span><span class="plain-syntax">; </span><span class="identifier-syntax">q</span><span class="plain-syntax">=</span><span class="identifier-syntax">q</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next</span><span class="plain-syntax">, </span><span class="identifier-syntax">children_count</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP55" class="function-link"><span class="function-syntax">ParseTree::verify_structure_recursively</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">q</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pt.html#SP55_4" class="named-paragraph-link"><span class="named-paragraph">Check rule (4) of the invariant</span><span class="named-paragraph-number">55.4</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP55" class="function-link"><span class="function-syntax">ParseTree::verify_structure_recursively</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">, </span><span class="identifier-syntax">parent</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP55_1"></a><b>&#167;55.1. </b>Rule (1): no INVALID nodes.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check rule (1) of the invariant</span><span class="named-paragraph-number">55.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">t</span><span class="plain-syntax"> == </span><span class="constant-syntax">INVALID_NT</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"N%d is $N, which is not allowed except temporarily\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pt.html#SP55_1_1" class="named-paragraph-link"><span class="named-paragraph">Log this invariant failure</span><span class="named-paragraph-number">55.1.1</span></a></span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pt.html#SP55">&#167;55</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP55_2"></a><b>&#167;55.2. </b>Rule (2): all annotations must be legal for the given node type.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check rule (2) of the invariant</span><span class="named-paragraph-number">55.2</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">parse_node_annotation</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">annotations</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">; </span><span class="identifier-syntax">pna</span><span class="plain-syntax">=</span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_annotation</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (!(</span><a href="2-pt.html#SP59" class="function-link"><span class="function-syntax">ParseTree::annotation_allowed</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_of_annotation</span><span class="plain-syntax">))) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"N%d is $N, which is not allowed to have annotation %d\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_of_annotation</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Node %08x, ann %d\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">pna</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">kind_of_annotation</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pt.html#SP55_1_1" class="named-paragraph-link"><span class="named-paragraph">Log this invariant failure</span><span class="named-paragraph-number">55.1.1</span></a></span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pt.html#SP55">&#167;55</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP55_3"></a><b>&#167;55.3. </b>Rule (3): can this combination of parent and child exist?
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check rule (3) of the invariant</span><span class="named-paragraph-number">55.3</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t_parent</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::get_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">parent</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">child_category</span><span class="plain-syntax"> = </span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">category</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_tree_node_type</span><span class="plain-syntax"> *</span><span class="identifier-syntax">metadata_parent</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP18" class="function-link"><span class="function-syntax">ParseTree::node_metadata</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t_parent</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">metadata_parent</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"broken tree should have been reported"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">parent_category</span><span class="plain-syntax"> = </span><span class="identifier-syntax">metadata_parent</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">category</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (!(</span><a href="2-pt.html#SP57" class="function-link"><span class="function-syntax">ParseTree::parentage_allowed</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t_parent</span><span class="plain-syntax">, </span><span class="identifier-syntax">parent_category</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">child_category</span><span class="plain-syntax">))) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"N%d is $N (category %d): should not be a child of $N (category %d)\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">child_category</span><span class="plain-syntax">, </span><span class="identifier-syntax">t_parent</span><span class="plain-syntax">, </span><span class="identifier-syntax">parent_category</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pt.html#SP55_1_1" class="named-paragraph-link"><span class="named-paragraph">Log this invariant failure</span><span class="named-paragraph-number">55.1.1</span></a></span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pt.html#SP55">&#167;55</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP55_4"></a><b>&#167;55.4. </b>Rule (4): The number of children has to be within the given extrema.
</p>
<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Check rule (4) of the invariant</span><span class="named-paragraph-number">55.4</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">children_count</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">min_children</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"N%d has %d children, but min for $N is %d:\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">children_count</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">min_children</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pt.html#SP55_1_1" class="named-paragraph-link"><span class="named-paragraph">Log this invariant failure</span><span class="named-paragraph-number">55.1.1</span></a></span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">children_count</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">max_children</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"N%d has %d children, but max for $N is %d:\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">p</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">children_count</span><span class="plain-syntax">, </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">metadata</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">max_children</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="2-pt.html#SP55_1_1" class="named-paragraph-link"><span class="named-paragraph">Log this invariant failure</span><span class="named-paragraph-number">55.1.1</span></a></span>
<span class="plain-syntax"> }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pt.html#SP55">&#167;55</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP55_1_1"></a><b>&#167;55.1.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Log this invariant failure</span><span class="named-paragraph-number">55.1.1</span></span><span class="comment-syntax"> =</span>
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::is</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">parent</span><span class="plain-syntax">, </span><span class="constant-syntax">ROOT_NT</span><span class="plain-syntax">)) </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Failing subtree:\n$T"</span><span class="plain-syntax">, </span><span class="identifier-syntax">p</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"Failing subtree:\n$T"</span><span class="plain-syntax">, </span><span class="identifier-syntax">parent</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">node_errors</span><span class="plain-syntax">++;</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="2-pt.html#SP55_1">&#167;55.1</a>, <a href="2-pt.html#SP55_2">&#167;55.2</a>, <a href="2-pt.html#SP55_3">&#167;55.3</a>, <a href="2-pt.html#SP55_4">&#167;55.4</a> (twice).</li></ul>
<p class="commentary firstcommentary"><a id="SP56"></a><b>&#167;56. Parentage rules. </b>It's mostly the case that node category determines whether one node can be
parent to another:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">parentage_allowed_set_up</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">parentage_allowed</span><span class="plain-syntax">[</span><span class="identifier-syntax">NO_DEFINED_NCAT_VALUES</span><span class="plain-syntax">][</span><span class="identifier-syntax">NO_DEFINED_NCAT_VALUES</span><span class="plain-syntax">];</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::make_parentage_allowed_table</span><button class="popup" onclick="togglePopup('usagePopup39')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup39">Usage of <span class="code-font"><span class="function-syntax">ParseTree::make_parentage_allowed_table</span></span>:<br/><a href="2-pt.html#SP54">&#167;54</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">parentage_allowed_set_up</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">parentage_allowed_set_up</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">NO_DEFINED_NCAT_VALUES</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">j</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">j</span><span class="plain-syntax"> &lt; </span><span class="identifier-syntax">NO_DEFINED_NCAT_VALUES</span><span class="plain-syntax">; </span><span class="identifier-syntax">j</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">parentage_allowed</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">][</span><span class="identifier-syntax">j</span><span class="plain-syntax">] = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">parentage_allowed</span><span class="plain-syntax">[</span><span class="constant-syntax">L1_NCAT</span><span class="plain-syntax">][</span><span class="constant-syntax">L1_NCAT</span><span class="plain-syntax">] = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP57"></a><b>&#167;57. </b>But there are exceptions. Note that an <span class="extract"><span class="extract-syntax">L2_NCAT</span></span> node can have no parent
at all, according to the broad rules above: in fact, it can, but only if
the parent is <span class="extract"><span class="extract-syntax">HEADING_NT</span></span>.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::parentage_allowed</span><button class="popup" onclick="togglePopup('usagePopup40')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup40">Usage of <span class="code-font"><span class="function-syntax">ParseTree::parentage_allowed</span></span>:<br/><a href="2-pt.html#SP55_3">&#167;55.3</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t_parent</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">cat_parent</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t_child</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">cat_child</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">parentage_allowed</span><span class="plain-syntax">[</span><span class="identifier-syntax">cat_parent</span><span class="plain-syntax">][</span><span class="identifier-syntax">cat_child</span><span class="plain-syntax">]) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">PARENTAGE_EXCEPTIONS</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">PARENTAGE_EXCEPTIONS</span><span class="plain-syntax">(</span><span class="identifier-syntax">t_parent</span><span class="plain-syntax">, </span><span class="identifier-syntax">cat_parent</span><span class="plain-syntax">, </span><span class="identifier-syntax">t_child</span><span class="plain-syntax">, </span><span class="identifier-syntax">cat_child</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">t_parent</span><span class="plain-syntax"> == </span><span class="constant-syntax">AMBIGUITY_NT</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">t_child</span><span class="plain-syntax"> == </span><span class="constant-syntax">AMBIGUITY_NT</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP58"></a><b>&#167;58. Annotation rules. </b>This is on an altogether grander scale.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="identifier-syntax">LOOP_OVER_NODE_TYPES</span><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">=</span><span class="constant-syntax">BASE_OF_ENUMERATED_NTS</span><span class="plain-syntax">; </span><span class="identifier-syntax">t</span><span class="plain-syntax">&lt;</span><span class="constant-syntax">BASE_OF_ENUMERATED_NTS</span><span class="plain-syntax">+</span><span class="identifier-syntax">NO_DEFINED_NT_VALUES</span><span class="plain-syntax">; </span><span class="identifier-syntax">t</span><span class="plain-syntax">++)</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">annotation_allowed_set_up</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">annotation_allowed</span><span class="plain-syntax">[</span><span class="identifier-syntax">NO_DEFINED_NT_VALUES</span><span class="plain-syntax">][</span><span class="constant-syntax">MAX_ANNOT_NUMBER</span><span class="plain-syntax">+1];</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::allow_annotation</span><button class="popup" onclick="togglePopup('usagePopup41')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup41">Usage of <span class="code-font"><span class="function-syntax">ParseTree::allow_annotation</span></span>:<br/><a href="2-pt.html#SP59">&#167;59</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">annot</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">annotation_allowed</span><span class="plain-syntax">[</span><span class="identifier-syntax">t</span><span class="plain-syntax"> - </span><span class="constant-syntax">BASE_OF_ENUMERATED_NTS</span><span class="plain-syntax">][</span><span class="identifier-syntax">annot</span><span class="plain-syntax">] = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::allow_annotation_to_category</span><button class="popup" onclick="togglePopup('usagePopup42')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup42">Usage of <span class="code-font"><span class="function-syntax">ParseTree::allow_annotation_to_category</span></span>:<br/><a href="2-pt.html#SP59">&#167;59</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">cat</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">annot</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER_NODE_TYPES</span><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP19" class="function-link"><span class="function-syntax">ParseTree::cat</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">) == </span><span class="identifier-syntax">cat</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP58" class="function-link"><span class="function-syntax">ParseTree::allow_annotation</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="identifier-syntax">annot</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP59"></a><b>&#167;59. </b>The eagle-eyed observer will note that the <span class="extract"><span class="extract-syntax">meaning</span></span> annotation is never
allowed. In fact it does exist, but only for meaning-coded parse nodes, which
never exist inside trees and are used only as parsing intermediates. So we
never see this annotation here.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::make_annotation_allowed_table</span><button class="popup" onclick="togglePopup('usagePopup43')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup43">Usage of <span class="code-font"><span class="function-syntax">ParseTree::make_annotation_allowed_table</span></span>:<br/><a href="2-pt.html#SP54">&#167;54</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">annotation_allowed_set_up</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">annotation_allowed_set_up</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP58" class="function-link"><span class="function-syntax">ParseTree::allow_annotation</span></a><span class="plain-syntax">(</span><span class="constant-syntax">HEADING_NT</span><span class="plain-syntax">, </span><span class="constant-syntax">heading_level_ANNOT</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP58" class="function-link"><span class="function-syntax">ParseTree::allow_annotation</span></a><span class="plain-syntax">(</span><span class="constant-syntax">SENTENCE_NT</span><span class="plain-syntax">, </span><span class="constant-syntax">language_element_ANNOT</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP58" class="function-link"><span class="function-syntax">ParseTree::allow_annotation_to_category</span></a><span class="plain-syntax">(</span><span class="constant-syntax">L1_NCAT</span><span class="plain-syntax">, </span><span class="constant-syntax">sentence_unparsed_ANNOT</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP58" class="function-link"><span class="function-syntax">ParseTree::allow_annotation_to_category</span></a><span class="plain-syntax">(</span><span class="constant-syntax">L2_NCAT</span><span class="plain-syntax">, </span><span class="constant-syntax">sentence_unparsed_ANNOT</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">ANNOTATION_PERMISSIONS_WRITER</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">ANNOTATION_PERMISSIONS_WRITER</span><span class="plain-syntax">();</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::annotation_allowed</span><button class="popup" onclick="togglePopup('usagePopup44')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup44">Usage of <span class="code-font"><span class="function-syntax">ParseTree::annotation_allowed</span></span>:<br/><a href="2-pt.html#SP25">&#167;25</a>, <a href="2-pt.html#SP55_2">&#167;55.2</a></span></button><span class="plain-syntax">(</span><span class="constant-syntax">node_type_t</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">annot</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">annot</span><span class="plain-syntax"> &lt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">annot</span><span class="plain-syntax"> &gt; </span><span class="constant-syntax">MAX_ANNOT_NUMBER</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"annotation number out of range"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">t</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">BASE_OF_ENUMERATED_NTS</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">t</span><span class="plain-syntax"> &lt; </span><span class="constant-syntax">BASE_OF_ENUMERATED_NTS</span><span class="plain-syntax">+</span><span class="identifier-syntax">NO_DEFINED_NT_VALUES</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">annotation_allowed</span><span class="plain-syntax">[</span><span class="identifier-syntax">t</span><span class="plain-syntax"> - </span><span class="constant-syntax">BASE_OF_ENUMERATED_NTS</span><span class="plain-syntax">][</span><span class="identifier-syntax">annot</span><span class="plain-syntax">];</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP60"></a><b>&#167;60. Ambiguity subtrees. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="function-syntax">ParseTree::add_possible_reading</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">existing</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">reading</span><span class="plain-syntax">, </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">existing</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">reading</span><span class="plain-syntax">;</span>
<span class="plain-syntax">#</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::is</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">reading</span><span class="plain-syntax">, </span><span class="identifier-syntax">UNKNOWN_NT</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">existing</span><span class="plain-syntax">;</span>
<span class="plain-syntax">#</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::is</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">reading</span><span class="plain-syntax">, </span><span class="constant-syntax">AMBIGUITY_NT</span><span class="plain-syntax">)) </span><span class="identifier-syntax">reading</span><span class="plain-syntax"> = </span><span class="identifier-syntax">reading</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::is</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">existing</span><span class="plain-syntax">, </span><span class="constant-syntax">AMBIGUITY_NT</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ParseTreeUsage::is_phrasal</span><span class="plain-syntax">(</span><span class="identifier-syntax">reading</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">E</span><span class="plain-syntax"> = </span><span class="identifier-syntax">existing</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">; </span><span class="identifier-syntax">E</span><span class="plain-syntax">; </span><span class="identifier-syntax">E</span><span class="plain-syntax"> = </span><span class="identifier-syntax">E</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::get_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">reading</span><span class="plain-syntax">) == </span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::get_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">E</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP60" class="function-link"><span class="function-syntax">ParseTree::add_pr_inv</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">E</span><span class="plain-syntax">, </span><span class="identifier-syntax">reading</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">existing</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax"> = </span><span class="identifier-syntax">existing</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">L</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">L</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">)) </span><span class="identifier-syntax">L</span><span class="plain-syntax"> = </span><span class="identifier-syntax">L</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">L</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">next_alternative</span><span class="plain-syntax"> = </span><span class="identifier-syntax">reading</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">existing</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">ParseTreeUsage::is_phrasal</span><span class="plain-syntax">(</span><span class="identifier-syntax">reading</span><span class="plain-syntax">)) &amp;&amp;</span>
<span class="plain-syntax"> (</span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::get_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">reading</span><span class="plain-syntax">) == </span><a href="2-pt.html#SP24" class="function-link"><span class="function-syntax">ParseTree::get_type</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">existing</span><span class="plain-syntax">))) {</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP60" class="function-link"><span class="function-syntax">ParseTree::add_pr_inv</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">existing</span><span class="plain-syntax">, </span><span class="identifier-syntax">reading</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">existing</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">A</span><span class="plain-syntax"> = </span><a href="2-pt.html#SP22" class="function-link"><span class="function-syntax">ParseTree::new_with_words</span></a><span class="plain-syntax">(</span><span class="constant-syntax">AMBIGUITY_NT</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">A</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax"> = </span><span class="identifier-syntax">existing</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">A</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax"> = </span><span class="identifier-syntax">reading</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">A</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="plain-syntax">#</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::add_pr_inv</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">E</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">reading</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">N</span><span class="plain-syntax"> = </span><span class="identifier-syntax">reading</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">, *</span><span class="identifier-syntax">next_N</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">N</span><span class="plain-syntax">)?(</span><span class="identifier-syntax">N</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">):</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="identifier-syntax">N</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">N</span><span class="plain-syntax"> = </span><span class="identifier-syntax">next_N</span><span class="plain-syntax">, </span><span class="identifier-syntax">next_N</span><span class="plain-syntax"> = (</span><span class="identifier-syntax">N</span><span class="plain-syntax">)?(</span><span class="identifier-syntax">N</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">):</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><a href="2-pt.html#SP60" class="function-link"><span class="function-syntax">ParseTree::add_single_pr_inv</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">E</span><span class="plain-syntax">, </span><span class="identifier-syntax">N</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">ParseTree::add_single_pr_inv</span><span class="plain-syntax">(</span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">E</span><span class="plain-syntax">, </span><span class="reserved-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">N</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">E</span><span class="plain-syntax"> = </span><span class="identifier-syntax">E</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">down</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">down</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Invocations::eq</span><span class="plain-syntax">(</span><span class="identifier-syntax">E</span><span class="plain-syntax">, </span><span class="identifier-syntax">N</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">while</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">E</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">E</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">E</span><span class="plain-syntax"> = </span><span class="identifier-syntax">E</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Invocations::eq</span><span class="plain-syntax">(</span><span class="identifier-syntax">E</span><span class="plain-syntax">, </span><span class="identifier-syntax">N</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">E</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax"> = </span><span class="identifier-syntax">N</span><span class="plain-syntax">; </span><span class="identifier-syntax">N</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_alternative</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="plain-syntax">#</span><span class="identifier-syntax">endif</span>
</pre>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="1-sm.html">&#10094;</a></li><li class="progresschapter"><a href="1-sm.html">1</a></li><li class="progresscurrentchapter">2</li><li class="progresscurrent">pt</li><li class="progresssection"><a href="2-snt.html">snt</a></li><li class="progressnext"><a href="2-snt.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>