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

1958 lines
259 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>1/sm</title>
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<nav role="navigation">
<h1><a href="../webs.html">Sources</a></h1>
<ul>
<li><a href="../compiler.html"><b>compiler tools</b></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="../inbuild-module/index.html">inbuild</a></li>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../html-module/index.html">html</a></li>
</ul>
<h2>Inform7 Modules</h2>
<ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../problems-module/index.html">problems</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="../index-module/index.html">index</a></li>
</ul>
<h2>Inter Modules</h2>
<ul>
<li><a href="../inter-module/index.html">inter</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul>
<h2>Foundation</h2>
<ul>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of '2/pt' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../compiler.html">Compiler 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><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="#SP1">&#167;1. Trees store meanings</a></li><li><a href="#SP4">&#167;4. Structural vs specifications</a></li><li><a href="#SP5">&#167;5. Node types</a></li><li><a href="#SP7">&#167;7. The structure</a></li><li><a href="#SP8">&#167;8. Where we currently are in the text</a></li><li><a href="#SP12">&#167;12. Node metadata</a></li><li><a href="#SP16">&#167;16. The metadata table</a></li><li><a href="#SP20">&#167;20. Logging node types</a></li><li><a href="#SP21">&#167;21. Creation</a></li><li><a href="#SP24">&#167;24. Annotations</a></li><li><a href="#SP33">&#167;33. Copying parse nodes</a></li><li><a href="#SP36">&#167;36. Child count</a></li><li><a href="#SP37">&#167;37. Detection of subnodes</a></li><li><a href="#SP38">&#167;38. The word range beneath a given node</a></li><li><a href="#SP45">&#167;45. Logging the parse tree</a></li><li><a href="#SP50">&#167;50. General traversals</a></li><li><a href="#SP52">&#167;52. Verify integrity</a></li><li><a href="#SP54">&#167;54. Verify structure</a></li><li><a href="#SP56">&#167;56. Parentage rules</a></li><li><a href="#SP58">&#167;58. Annotation rules</a></li><li><a href="#SP60">&#167;60. Ambiguity subtrees</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><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="inwebparagraph">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="inwebparagraph">The tree is stored as a collection of "parse nodes", with <code class="display"><span class="extract">next</span></code> and
<code class="display"><span class="extract">down</span></code> links between them to represent siblings and children.
</p>
<p class="inwebparagraph">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 <code class="display"><span class="extract">next_alternative</span></code> link, which &mdash; if used &mdash; forks the tree into
different possible readings.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_ATTACHMENT_STACK_SIZE</span><span class="plain"> </span><span class="constant">100</span><span class="plain"> </span><span class="comment">must be at least the number of heading levels plus 3</span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">parse_node_tree</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">root_node</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">attachment_sp</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">attachment_stack_parent</span><span class="plain">[</span><span class="constant">MAX_ATTACHMENT_STACK_SIZE</span><span class="plain">];</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">one_off_attachment_point</span><span class="plain">;</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">parse_node_tree</span><span class="plain">;</span>
<span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="functiontext">ParseTree::new_tree</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain">);</span>
<span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain"> = </span><span class="functiontext">ParseTree::new</span><span class="plain">(</span><span class="constant">ROOT_NT</span><span class="plain">);</span>
<span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">attachment_sp</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">one_off_attachment_point</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="functiontext">ParseTree::push_attachment_point</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">T</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::new_tree appears nowhere else.</p>
<p class="endnote">The structure parse_node_tree is private to this section.</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::push_attachment_point</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">l</span><span class="plain"> = </span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="identifier">attachment_sp</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">attachment_sp</span><span class="plain"> &gt;= </span><span class="constant">MAX_ATTACHMENT_STACK_SIZE</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"attachment stack overflow"</span><span class="plain">);</span>
<span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">attachment_stack_parent</span><span class="plain">[</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">attachment_sp</span><span class="plain">++] = </span><span class="identifier">to</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">l</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::pop_attachment_point</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">l</span><span class="plain">) {</span>
<span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">attachment_sp</span><span class="plain"> = </span><span class="identifier">l</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::push_attachment_point is used in <a href="#SP1">&#167;1</a>, <a href="#SP44">&#167;44</a>.</p>
<p class="endnote">The function ParseTree::pop_attachment_point appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>In addition, we can temporarily override this system:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::set_attachment_point_one_off</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain">) {</span>
<span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">one_off_attachment_point</span><span class="plain"> = </span><span class="identifier">to</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::set_attachment_point_one_off appears nowhere else.</p>
<p class="inwebparagraph"><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="inwebparagraph">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="inwebparagraph">the value "124" is stored as a single specification node, of node type
<code class="display"><span class="extract">CONSTANT_NT</span></code>. But more elaborate possibilities exist:
</p>
<blockquote>
<p>tally is 124 and the player is in the Library</p>
</blockquote>
<p class="inwebparagraph">is stored as a tree of three specification nodes:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">LOGICAL_AND_NT</span>
</pre>
<p class="inwebparagraph"> <code class="display"><span class="extract">TEST_PROPOSITION_NT "tally is 124"</span></code>
<code class="display"><span class="extract">TEST_PROPOSITION_NT "the player is in the Library"</span></code>
</p>
<p class="inwebparagraph">The tree is heavily annotated, so that nodes can carry more meaning than
just their type alone. For example, the <code class="display"><span class="extract">CONSTANT_NT</span></code> node for "124"
is annotated with the kind <code class="display"><span class="extract">K_number</span></code>, showing what kind of constant it
represents. The <code class="display"><span class="extract">TEST_PROPOSITION_NT</span></code> 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 <code class="display"><span class="extract">pcalc_prop</span></code> structure which indirectly contains the values "tally"
and "124", which are both represented as parse nodes.
</p>
<p class="inwebparagraph"><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 <code class="display"><span class="extract">*_MC</span></code>
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">
<span class="definitionkeyword">define</span> <span class="constant">node_type_t</span><span class="plain"> </span><span class="reserved">unsigned</span><span class="plain"> </span><span class="reserved">int</span><span class="plain"> </span><span class="comment">(not a typedef only because it makes trouble for inweb)</span>
</pre>
<p class="inwebparagraph"><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="inwebparagraph">Structural node types are enumerated first:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">BASE_OF_ENUMERATED_NTS</span><span class="plain"> </span><span class="constant">0x80000000</span>
<span class="definitionkeyword">enum</span> <span class="constant">INVALID_NT</span><span class="definitionkeyword"> from </span><span class="constant">0x80000000</span> <span class="comment">No node with this node type should ever exist</span>
<span class="definitionkeyword">enum</span> <span class="constant">ROOT_NT</span><span class="plain"> </span><span class="comment">Only one such node exists: the tree root</span>
<span class="definitionkeyword">enum</span> <span class="constant">INCLUSION_NT</span><span class="plain"> </span><span class="comment">Holds a block of source material</span>
<span class="definitionkeyword">enum</span> <span class="constant">HEADING_NT</span><span class="plain"> </span><span class="comment">"Chapter VIII: Never Turn Your Back On A Shreve"</span>
<span class="definitionkeyword">enum</span> <span class="constant">INCLUDE_NT</span><span class="plain"> </span><span class="comment">"Include School Rules by Argus Filch"</span>
<span class="definitionkeyword">enum</span> <span class="constant">BEGINHERE_NT</span><span class="plain"> </span><span class="comment">"The Standard Rules begin here"</span>
<span class="definitionkeyword">enum</span> <span class="constant">ENDHERE_NT</span><span class="plain"> </span><span class="comment">"The Standard Rules end here"</span>
<span class="definitionkeyword">enum</span> <span class="constant">SENTENCE_NT</span><span class="plain"> </span><span class="comment">"The Garden is a room"</span>
<span class="definitionkeyword">enum</span> <span class="constant">AMBIGUITY_NT</span><span class="plain"> </span><span class="comment">Marks an ambiguous set of readings in the tree</span>
</pre>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. The structure. </b>Finally, then, the data structure.
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">parse_node</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">text_parsed</span><span class="plain">; </span><span class="comment">the text being interpreted by this node</span>
<span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">node_type</span><span class="plain">; </span><span class="comment">what the node basically represents</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="identifier">annotations</span><span class="plain">; </span><span class="comment">linked list of miscellaneous annotations</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">down</span><span class="plain">; </span><span class="comment">pointers within the current interpretation</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">next</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">score</span><span class="plain">; </span><span class="comment">used to choose most likely interpretation</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">next_alternative</span><span class="plain">; </span><span class="comment">fork to alternative interpretation</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">log_time</span><span class="plain">; </span><span class="comment">used purely as a defensive measure when writing debugging log</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">parse_node</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure parse_node is private to this section.</p>
<p class="inwebparagraph"><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="inwebparagraph">During such traverses, <code class="display"><span class="extract">current_sentence</span></code> is always the subtree being looked
at: it is always a child of the tree root, and is usually a <code class="display"><span class="extract">SENTENCE_NT</span></code>
node, hence the name.
</p>
<pre class="display">
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><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="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">parse_node_annotation</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">kind_of_annotation</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">annotation_integer</span><span class="plain">;</span>
<span class="identifier">general_pointer</span><span class="plain"> </span><span class="identifier">annotation_pointer</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="identifier">next_annotation</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">parse_node_annotation</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure parse_node_annotation is private to this section.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b></p>
<pre class="definitions">
<span class="definitionkeyword">enum</span> <span class="constant">heading_level_ANNOT</span><span class="definitionkeyword"> from </span><span class="constant">1</span> <span class="comment">int: for HEADING nodes, a hierarchical level, 0 (highest) to 9 (lowest)</span>
<span class="definitionkeyword">enum</span> <span class="constant">language_element_ANNOT</span><span class="plain"> </span><span class="comment"><code class="display"><span class="extract">int</span></code>: this node is not really a sentence, but a language definition Use</span>
<span class="definitionkeyword">enum</span> <span class="constant">sentence_unparsed_ANNOT</span><span class="plain"> </span><span class="comment">int: set if verbs haven't been sought yet here</span>
<span class="definitionkeyword">enum</span> <span class="constant">suppress_heading_dependencies_ANNOT</span><span class="plain"> </span><span class="comment">int: ignore extension dependencies on this heading node</span>
<span class="definitionkeyword">enum</span> <span class="constant">implied_heading_ANNOT</span><span class="plain"> </span><span class="comment">int: set only for the heading of implied inclusions</span>
<span class="definitionkeyword">define</span> <span class="constant">MAX_ANNOT_NUMBER</span><span class="plain"> (</span><span class="identifier">NO_DEFINED_ANNOT_VALUES</span><span class="plain">+1)</span>
</pre>
<p class="inwebparagraph"><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">
<span class="definitionkeyword">define</span> <span class="identifier">DECLARE_ANNOTATION_FUNCTIONS</span><span class="plain">(</span><span class="identifier">annotation_name</span><span class="plain">, </span><span class="identifier">pointer_type</span><span class="plain">)</span>
<span class="reserved">void</span><span class="plain"> </span><span class="identifier">ParseTree::set_</span><span class="plain">##</span><span class="identifier">annotation_name</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">pointer_type</span><span class="plain"> *</span><span class="identifier">bp</span><span class="plain">);</span>
<span class="identifier">pointer_type</span><span class="plain"> *</span><span class="identifier">ParseTree::get_</span><span class="plain">##</span><span class="identifier">annotation_name</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"><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="inwebparagraph">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="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">parse_tree_node_type</span><span class="plain"> {</span>
<span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">identity</span><span class="plain">;</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="identifier">node_type_name</span><span class="plain">; </span><span class="comment">text of name of type, such as <code class="display"><span class="extract">"INVOCATION_LIST_NT"</span></code></span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">min_children</span><span class="plain">; </span><span class="comment">minimum legal number of child nodes</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">max_children</span><span class="plain">; </span><span class="comment">maximum legal number of child nodes</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">category</span><span class="plain">; </span><span class="comment">one of the <code class="display"><span class="extract">*_NCAT</span></code> values below</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">node_flags</span><span class="plain">; </span><span class="comment">bitmap of node flags</span>
<span class="plain">} </span><span class="reserved">parse_tree_node_type</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure parse_tree_node_type is private to this section.</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>The categories are:
</p>
<pre class="definitions">
<span class="definitionkeyword">enum</span> <span class="constant">INVALID_NCAT</span><span class="definitionkeyword"> from </span><span class="constant">0</span>
<span class="definitionkeyword">enum</span> <span class="constant">L1_NCAT</span>
<span class="definitionkeyword">enum</span> <span class="constant">L2_NCAT</span>
</pre>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. </b>The bitmap of node flags begins with:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">DONT_VISIT_NFLAG</span><span class="plain"> </span><span class="constant">0x00000001</span><span class="plain"> </span><span class="comment">not visited in traverses</span>
<span class="definitionkeyword">define</span> <span class="constant">TABBED_CONTENT_NFLAG</span><span class="plain"> </span><span class="constant">0x00000002</span><span class="plain"> </span><span class="comment">contains tab-delimited lists</span>
</pre>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. </b>Various modules conventionally use this global setting to toggle debugging
log output:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">trace_sentences</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><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">
<span class="definitionkeyword">define</span> <span class="constant">INFTY</span><span class="plain"> </span><span class="constant">1000000000</span><span class="plain"> </span><span class="comment">if ever a node has more than a billion children, we are in trouble anyway</span>
</pre>
<pre class="display">
<span class="reserved">parse_tree_node_type</span><span class="plain"> </span><span class="identifier">parse_tree_node_types</span><span class="plain">[</span><span class="identifier">NO_DEFINED_NT_VALUES</span><span class="plain">];</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::md</span><span class="plain">(</span><span class="reserved">parse_tree_node_type</span><span class="plain"> </span><span class="identifier">ptnt</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::valid_type</span><span class="plain">(</span><span class="identifier">ptnt</span><span class="plain">.</span><span class="element">identity</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"set bad metadata"</span><span class="plain">);</span>
<span class="identifier">parse_tree_node_types</span><span class="plain">[</span><span class="identifier">ptnt</span><span class="plain">.</span><span class="element">identity</span><span class="plain"> - </span><span class="constant">BASE_OF_ENUMERATED_NTS</span><span class="plain">] = </span><span class="identifier">ptnt</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::md is used in <a href="#SP17">&#167;17</a>.</p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::metadata_setup</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="functiontext">ParseTree::md</span><span class="plain">((</span><span class="reserved">parse_tree_node_type</span><span class="plain">) { </span><span class="constant">INVALID_NT</span><span class="plain">, </span><span class="string">"(INVALID_NT)"</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">INFTY</span><span class="plain">, </span><span class="constant">INVALID_NCAT</span><span class="plain">, </span><span class="constant">0</span><span class="plain"> });</span>
<span class="functiontext">ParseTree::md</span><span class="plain">((</span><span class="reserved">parse_tree_node_type</span><span class="plain">) { </span><span class="constant">ROOT_NT</span><span class="plain">, </span><span class="string">"ROOT_NT"</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">INFTY</span><span class="plain">, </span><span class="constant">L1_NCAT</span><span class="plain">, </span><span class="constant">DONT_VISIT_NFLAG</span><span class="plain"> });</span>
<span class="functiontext">ParseTree::md</span><span class="plain">((</span><span class="reserved">parse_tree_node_type</span><span class="plain">) { </span><span class="constant">INCLUSION_NT</span><span class="plain">, </span><span class="string">"INCLUSION_NT"</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">INFTY</span><span class="plain">, </span><span class="constant">L1_NCAT</span><span class="plain">, </span><span class="constant">DONT_VISIT_NFLAG</span><span class="plain"> });</span>
<span class="functiontext">ParseTree::md</span><span class="plain">((</span><span class="reserved">parse_tree_node_type</span><span class="plain">) { </span><span class="constant">HEADING_NT</span><span class="plain">, </span><span class="string">"HEADING_NT"</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">INFTY</span><span class="plain">, </span><span class="constant">L1_NCAT</span><span class="plain">, </span><span class="constant">0</span><span class="plain"> });</span>
<span class="functiontext">ParseTree::md</span><span class="plain">((</span><span class="reserved">parse_tree_node_type</span><span class="plain">) { </span><span class="constant">INCLUDE_NT</span><span class="plain">, </span><span class="string">"INCLUDE_NT"</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">L2_NCAT</span><span class="plain">, </span><span class="constant">0</span><span class="plain"> });</span>
<span class="functiontext">ParseTree::md</span><span class="plain">((</span><span class="reserved">parse_tree_node_type</span><span class="plain">) { </span><span class="constant">BEGINHERE_NT</span><span class="plain">, </span><span class="string">"BEGINHERE_NT"</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">L2_NCAT</span><span class="plain">, </span><span class="constant">0</span><span class="plain"> });</span>
<span class="functiontext">ParseTree::md</span><span class="plain">((</span><span class="reserved">parse_tree_node_type</span><span class="plain">) { </span><span class="constant">ENDHERE_NT</span><span class="plain">, </span><span class="string">"ENDHERE_NT"</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">L2_NCAT</span><span class="plain">, </span><span class="constant">0</span><span class="plain"> });</span>
<span class="functiontext">ParseTree::md</span><span class="plain">((</span><span class="reserved">parse_tree_node_type</span><span class="plain">) { </span><span class="constant">SENTENCE_NT</span><span class="plain">, </span><span class="string">"SENTENCE_NT"</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">INFTY</span><span class="plain">, </span><span class="constant">L2_NCAT</span><span class="plain">, </span><span class="constant">0</span><span class="plain"> });</span>
<span class="functiontext">ParseTree::md</span><span class="plain">((</span><span class="reserved">parse_tree_node_type</span><span class="plain">) { </span><span class="constant">AMBIGUITY_NT</span><span class="plain">, </span><span class="string">"AMBIGUITY_NT"</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">INFTY</span><span class="plain">, </span><span class="constant">L1_NCAT</span><span class="plain">, </span><span class="constant">0</span><span class="plain"> });</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">UNKNOWN_NT</span>
<span class="functiontext">ParseTree::md</span><span class="plain">((</span><span class="reserved">parse_tree_node_type</span><span class="plain">) { </span><span class="identifier">UNKNOWN_NT</span><span class="plain">, </span><span class="string">"UNKNOWN_NT"</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">INFTY</span><span class="plain">, </span><span class="identifier">L3_NCAT</span><span class="plain">, </span><span class="constant">0</span><span class="plain"> });</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">PARSE_TREE_METADATA_SETUP</span>
<span class="identifier">PARSE_TREE_METADATA_SETUP</span><span class="plain">();</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::metadata_setup is used in 1/sm (<a href="1-sm.html#SP3">&#167;3</a>).</p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. </b>We can only retrieve metadata on enumerated node types, not on meaning
codes such as <code class="display"><span class="extract">RULE_MC</span></code>, for which the following will return <code class="display"><span class="extract">NULL</span></code>.
</p>
<pre class="display">
<span class="reserved">parse_tree_node_type</span><span class="plain"> *</span><span class="functiontext">ParseTree::node_metadata</span><span class="plain">(</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">t</span><span class="plain"> &gt;= </span><span class="constant">BASE_OF_ENUMERATED_NTS</span><span class="plain">) &amp;&amp; (</span><span class="identifier">t</span><span class="plain"> &lt; </span><span class="constant">BASE_OF_ENUMERATED_NTS</span><span class="plain">+</span><span class="identifier">NO_DEFINED_NT_VALUES</span><span class="plain">)) {</span>
<span class="reserved">parse_tree_node_type</span><span class="plain"> *</span><span class="identifier">metadata</span><span class="plain"> = &amp;(</span><span class="identifier">parse_tree_node_types</span><span class="plain">[</span><span class="identifier">t</span><span class="plain"> - </span><span class="constant">BASE_OF_ENUMERATED_NTS</span><span class="plain">]);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">metadata</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">metadata</span><span class="plain">-&gt;</span><span class="element">identity</span><span class="plain"> != </span><span class="identifier">t</span><span class="plain">)) {</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">STDERR</span><span class="plain">, </span><span class="string">"unable to locate node type %08x\n"</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"node type metadata lookup incorrect"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">metadata</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::node_metadata is used in <a href="#SP19">&#167;19</a>, <a href="#SP20">&#167;20</a>, <a href="#SP55">&#167;55</a>, <a href="#SP55_3">&#167;55.3</a>.</p>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::valid_type</span><span class="plain">(</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">t</span><span class="plain"> &gt;= </span><span class="constant">BASE_OF_ENUMERATED_NTS</span><span class="plain">) &amp;&amp; (</span><span class="identifier">t</span><span class="plain"> &lt; </span><span class="constant">BASE_OF_ENUMERATED_NTS</span><span class="plain">+</span><span class="identifier">NO_DEFINED_NT_VALUES</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::cat</span><span class="plain">(</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">) {</span>
<span class="reserved">parse_tree_node_type</span><span class="plain"> *</span><span class="identifier">metadata</span><span class="plain"> = </span><span class="functiontext">ParseTree::node_metadata</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">metadata</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">metadata</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">INVALID_NCAT</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::top_level</span><span class="plain">(</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">) {</span>
<span class="reserved">parse_tree_node_type</span><span class="plain"> *</span><span class="identifier">metadata</span><span class="plain"> = </span><span class="functiontext">ParseTree::node_metadata</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">metadata</span><span class="plain">) &amp;&amp; (</span><span class="identifier">metadata</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain"> == </span><span class="constant">L1_NCAT</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::visitable</span><span class="plain">(</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::test_flag</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="constant">DONT_VISIT_NFLAG</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::test_flag</span><span class="plain">(</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">f</span><span class="plain">) {</span>
<span class="reserved">parse_tree_node_type</span><span class="plain"> *</span><span class="identifier">metadata</span><span class="plain"> = </span><span class="functiontext">ParseTree::node_metadata</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">metadata</span><span class="plain">) &amp;&amp; ((</span><span class="identifier">metadata</span><span class="plain">-&gt;</span><span class="element">node_flags</span><span class="plain">) &amp; </span><span class="identifier">f</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::valid_type is used in <a href="#SP16">&#167;16</a>, <a href="#SP53">&#167;53</a>.</p>
<p class="endnote">The function ParseTree::cat is used in <a href="#SP58">&#167;58</a>.</p>
<p class="endnote">The function ParseTree::top_level is used in <a href="#SP50">&#167;50</a>.</p>
<p class="endnote">The function ParseTree::visitable is used in <a href="#SP50">&#167;50</a>.</p>
<p class="endnote">The function ParseTree::test_flag is used in 2/snt (<a href="2-snt.html#SP5_2">&#167;5.2</a>).</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::log_type</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">it</span><span class="plain">) {</span>
<span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain"> = (</span><span class="constant">node_type_t</span><span class="plain">) </span><span class="identifier">it</span><span class="plain">;</span>
<span class="reserved">parse_tree_node_type</span><span class="plain"> *</span><span class="identifier">metadata</span><span class="plain"> = </span><span class="functiontext">ParseTree::node_metadata</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">metadata</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%s"</span><span class="plain">, </span><span class="identifier">metadata</span><span class="plain">-&gt;</span><span class="element">node_type_name</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="identifier">UseExcerptMeanings::log_meaning_code</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">);</span>
<span class="plain">#</span><span class="reserved">else</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"?%08x_NT"</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">char</span><span class="plain"> *</span><span class="functiontext">ParseTree::get_type_name</span><span class="plain">(</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">) {</span>
<span class="reserved">parse_tree_node_type</span><span class="plain"> *</span><span class="identifier">metadata</span><span class="plain"> = </span><span class="functiontext">ParseTree::node_metadata</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">metadata</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="string">"?"</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">metadata</span><span class="plain">-&gt;</span><span class="element">node_type_name</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::log_type is used in <a href="#SP47">&#167;47</a>, 1/sm (<a href="1-sm.html#SP3_5">&#167;3.5</a>).</p>
<p class="endnote">The function ParseTree::get_type_name appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. Creation. </b></p>
<pre class="display">
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="functiontext">ParseTree::new</span><span class="plain">(</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain">);</span>
<span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain"> = </span><span class="identifier">t</span><span class="plain">;</span>
<span class="functiontext">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">EMPTY_WORDING</span><span class="plain">);</span>
<span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">log_time</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="functiontext">ParseTree::set_score</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="constant">0</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::new is used in <a href="#SP1">&#167;1</a>, <a href="#SP22">&#167;22</a>, <a href="#SP33">&#167;33</a>, <a href="#SP35">&#167;35</a>, 2/snt (<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>).</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="functiontext">ParseTree::new_with_words</span><span class="plain">(</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">code_number</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain"> = </span><span class="functiontext">ParseTree::new</span><span class="plain">(</span><span class="identifier">code_number</span><span class="plain">);</span>
<span class="functiontext">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::new_with_words is used in <a href="#SP60">&#167;60</a>.</p>
<p class="inwebparagraph"><a id="SP23"></a><b>&#167;23. </b>The attached text.
</p>
<pre class="display">
<span class="identifier">wording</span><span class="plain"> </span><span class="functiontext">ParseTree::get_text</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="identifier">text_parsed</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::set_text</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to set words for null node"</span><span class="plain">);</span>
<span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">text_parsed</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::get_text is used in <a href="#SP38">&#167;38</a>, <a href="#SP39">&#167;39</a>, <a href="#SP46">&#167;46</a>, <a href="#SP47">&#167;47</a>.</p>
<p class="endnote">The function ParseTree::set_text is used in <a href="#SP21">&#167;21</a>, <a href="#SP22">&#167;22</a>, 2/snt (<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>).</p>
<p class="inwebparagraph"><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="display">
<span class="constant">node_type_t</span><span class="plain"> </span><span class="functiontext">ParseTree::get_type</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="constant">INVALID_NT</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="identifier">node_type</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::is</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pn</span><span class="plain">) &amp;&amp; (</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain"> == </span><span class="identifier">t</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::get_type is used in <a href="#SP44">&#167;44</a>, <a href="#SP44_1">&#167;44.1</a>, <a href="#SP53">&#167;53</a>, <a href="#SP55">&#167;55</a>, <a href="#SP55_3">&#167;55.3</a>, <a href="#SP60">&#167;60</a>.</p>
<p class="endnote">The function ParseTree::is is used in <a href="#SP50">&#167;50</a>, <a href="#SP55_1_1">&#167;55.1.1</a>, <a href="#SP60">&#167;60</a>.</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::set_type</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">nt</span><span class="plain">) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IMMUTABLE_NODE</span>
<span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">from</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">IMMUTABLE_NODE</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">)) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$P changed to $N\n"</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">nt</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"immutable type changed"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain"> = </span><span class="identifier">nt</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(!(</span><span class="functiontext">ParseTree::annotation_allowed</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain">-&gt;</span><span class="element">kind_of_annotation</span><span class="plain">))))</span>
<span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="identifier">pna</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain"> = </span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="identifier">next_annotation</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(!(</span><span class="functiontext">ParseTree::annotation_allowed</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain">-&gt;</span><span class="element">kind_of_annotation</span><span class="plain">))))</span>
<span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain"> = </span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::set_type_and_clear_annotations</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">nt</span><span class="plain">) {</span>
<span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain"> = </span><span class="identifier">nt</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::set_type is used in 2/snt (<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>).</p>
<p class="endnote">The function ParseTree::set_type_and_clear_annotations appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP26"></a><b>&#167;26. </b>The integer score, used in choosing best matches:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::get_score</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">) { </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">score</span><span class="plain">; }</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::set_score</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">s</span><span class="plain">) { </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">score</span><span class="plain"> = </span><span class="identifier">s</span><span class="plain">; }</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::get_score is used in <a href="#SP46">&#167;46</a>.</p>
<p class="endnote">The function ParseTree::set_score is used in <a href="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="functiontext">ParseTree::pna_new</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">koa</span><span class="plain">) {</span>
<span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="identifier">pna</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">parse_node_annotation</span><span class="plain">);</span>
<span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">kind_of_annotation</span><span class="plain"> = </span><span class="identifier">koa</span><span class="plain">;</span>
<span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">annotation_integer</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">annotation_pointer</span><span class="plain"> = </span><span class="identifier">NULL_GENERAL_POINTER</span><span class="plain">;</span>
<span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">pna</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::pna_new is used in <a href="#SP30">&#167;30</a>, <a href="#SP31">&#167;31</a>.</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::has_annotation</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">PN</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">koa</span><span class="plain">) {</span>
<span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="identifier">pna</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PN</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">PN</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">kind_of_annotation</span><span class="plain"> == </span><span class="identifier">koa</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::has_annotation is used in <a href="#SP32">&#167;32</a>.</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::int_annotation</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">PN</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">koa</span><span class="plain">) {</span>
<span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="identifier">pna</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PN</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">PN</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">kind_of_annotation</span><span class="plain"> == </span><span class="identifier">koa</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">annotation_integer</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="constant">0</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">general_pointer</span><span class="plain"> </span><span class="functiontext">ParseTree::pn_pointer_annotation</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">PN</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">koa</span><span class="plain">) {</span>
<span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="identifier">pna</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PN</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">PN</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">kind_of_annotation</span><span class="plain"> == </span><span class="identifier">koa</span><span class="plain">)</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">annotation_pointer</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL_GENERAL_POINTER</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::int_annotation is used in <a href="#SP44_1">&#167;44.1</a>, <a href="#SP47">&#167;47</a>, <a href="#SP50">&#167;50</a>.</p>
<p class="endnote">The function ParseTree::pn_pointer_annotation is used in <a href="#SP32">&#167;32</a>.</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::annotate_int</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">PN</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">koa</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">v</span><span class="plain">) {</span>
<span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="identifier">newpna</span><span class="plain">, *</span><span class="identifier">pna</span><span class="plain">, *</span><span class="identifier">final</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PN</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"annotated null PN"</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">PN</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">kind_of_annotation</span><span class="plain"> == </span><span class="identifier">koa</span><span class="plain">) {</span>
<span class="comment">an annotation with this KOA exists already: overwrite it</span>
<span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">annotation_integer</span><span class="plain"> = </span><span class="identifier">v</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">final</span><span class="plain"> = </span><span class="identifier">pna</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">no annotation with this KOA exists: create a new one and add to end of node's list</span>
<span class="identifier">newpna</span><span class="plain"> = </span><span class="functiontext">ParseTree::pna_new</span><span class="plain">(</span><span class="identifier">koa</span><span class="plain">); </span><span class="identifier">newpna</span><span class="plain">-&gt;</span><span class="element">annotation_integer</span><span class="plain"> = </span><span class="identifier">v</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">final</span><span class="plain">) </span><span class="identifier">final</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain"> = </span><span class="identifier">newpna</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">PN</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain"> = </span><span class="identifier">newpna</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::annotate_int is used in 2/snt (<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>).</p>
<p class="inwebparagraph"><a id="SP31"></a><b>&#167;31. </b>Again, almost identical code handles the case of pointer-valued annotations:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::pn_annotate_pointer</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">PN</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">koa</span><span class="plain">, </span><span class="identifier">general_pointer</span><span class="plain"> </span><span class="identifier">data</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PN</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"annotated null PN"</span><span class="plain">);</span>
<span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="identifier">newpna</span><span class="plain">, *</span><span class="identifier">pna</span><span class="plain">, *</span><span class="identifier">final</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">PN</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">kind_of_annotation</span><span class="plain"> == </span><span class="identifier">koa</span><span class="plain">) {</span>
<span class="comment">an annotation with this KOA exists already: overwrite it</span>
<span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">annotation_pointer</span><span class="plain"> = </span><span class="identifier">data</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">final</span><span class="plain"> = </span><span class="identifier">pna</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">no annotation with this KOA exists: create a new one and add to end of node's list</span>
<span class="identifier">newpna</span><span class="plain"> = </span><span class="functiontext">ParseTree::pna_new</span><span class="plain">(</span><span class="identifier">koa</span><span class="plain">); </span><span class="identifier">newpna</span><span class="plain">-&gt;</span><span class="element">annotation_pointer</span><span class="plain"> = </span><span class="identifier">data</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">final</span><span class="plain">) </span><span class="identifier">final</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain"> = </span><span class="identifier">newpna</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">PN</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain"> = </span><span class="identifier">newpna</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::pn_annotate_pointer is used in <a href="#SP32">&#167;32</a>.</p>
<p class="inwebparagraph"><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">
<span class="definitionkeyword">define</span> <span class="identifier">MAKE_ANNOTATION_FUNCTIONS</span><span class="plain">(</span><span class="identifier">annotation_name</span><span class="plain">, </span><span class="identifier">pointer_type</span><span class="plain">)</span>
<span class="reserved">void</span><span class="plain"> </span><span class="identifier">ParseTree::set_</span><span class="plain">##</span><span class="identifier">annotation_name</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">pointer_type</span><span class="plain"> *</span><span class="identifier">bp</span><span class="plain">) {</span>
<span class="functiontext">ParseTree::pn_annotate_pointer</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">annotation_name</span><span class="plain">##</span><span class="identifier">_ANNOT</span><span class="plain">,</span>
<span class="identifier">STORE_POINTER_</span><span class="plain">##</span><span class="identifier">pointer_type</span><span class="plain">(</span><span class="identifier">bp</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="identifier">pointer_type</span><span class="plain"> *</span><span class="identifier">ParseTree::get_</span><span class="plain">##</span><span class="identifier">annotation_name</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">) {</span>
<span class="identifier">pointer_type</span><span class="plain"> *</span><span class="identifier">pt</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::has_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">annotation_name</span><span class="plain">##</span><span class="identifier">_ANNOT</span><span class="plain">))</span>
<span class="identifier">pt</span><span class="plain"> = </span><span class="identifier">RETRIEVE_POINTER_</span><span class="plain">##</span><span class="identifier">pointer_type</span><span class="plain">(</span>
<span class="functiontext">ParseTree::pn_pointer_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">annotation_name</span><span class="plain">##</span><span class="identifier">_ANNOT</span><span class="plain">));</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">pt</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"><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="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::copy</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">) {</span>
<span class="identifier">COPY</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain">);</span>
<span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="identifier">pna</span><span class="plain">, *</span><span class="identifier">latest</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">from</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain">) {</span>
<span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="identifier">pna_copy</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">parse_node_annotation</span><span class="plain">);</span>
<span class="plain">*</span><span class="identifier">pna_copy</span><span class="plain"> = *</span><span class="identifier">pna</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">PARSE_TREE_COPIER</span>
<span class="identifier">PARSE_TREE_COPIER</span><span class="plain">(</span><span class="identifier">pna_copy</span><span class="plain">, </span><span class="identifier">pna</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="identifier">pna_copy</span><span class="plain">-&gt;</span><span class="identifier">next_annotation</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">to</span><span class="plain">-&gt;</span><span class="identifier">annotations</span><span class="plain"> = </span><span class="identifier">pna_copy</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">latest</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain"> = </span><span class="identifier">pna_copy</span><span class="plain">;</span>
<span class="identifier">latest</span><span class="plain"> = </span><span class="identifier">pna_copy</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="functiontext">ParseTree::duplicate</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">dup</span><span class="plain"> = </span><span class="functiontext">ParseTree::new</span><span class="plain">(</span><span class="constant">INVALID_NT</span><span class="plain">);</span>
<span class="functiontext">ParseTree::copy</span><span class="plain">(</span><span class="identifier">dup</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">dup</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::copy is used in <a href="#SP34">&#167;34</a>, <a href="#SP35">&#167;35</a>.</p>
<p class="endnote">The function ParseTree::duplicate appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP34"></a><b>&#167;34. </b>This variation preserves links out.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::copy_in_place</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">next_link</span><span class="plain"> = </span><span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">;</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">alt_link</span><span class="plain"> = </span><span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">;</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">down_link</span><span class="plain"> = </span><span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">;</span>
<span class="functiontext">ParseTree::copy</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">);</span>
<span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">next_link</span><span class="plain">;</span>
<span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain"> = </span><span class="identifier">alt_link</span><span class="plain">;</span>
<span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="identifier">down_link</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::copy_in_place appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP35"></a><b>&#167;35. </b>And to deep-copy a whole subtree:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::copy_subtree</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">to</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">level</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">from</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">to</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Null deep copy"</span><span class="plain">);</span>
<span class="functiontext">ParseTree::copy</span><span class="plain">(</span><span class="identifier">to</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">from</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain">) {</span>
<span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="functiontext">ParseTree::new</span><span class="plain">(</span><span class="constant">INVALID_NT</span><span class="plain">);</span>
<span class="functiontext">ParseTree::copy_subtree</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">level</span><span class="plain">+1);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">level</span><span class="plain">&gt;0) &amp;&amp; (</span><span class="identifier">from</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)) {</span>
<span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="functiontext">ParseTree::new</span><span class="plain">(</span><span class="constant">INVALID_NT</span><span class="plain">);</span>
<span class="functiontext">ParseTree::copy_subtree</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">, </span><span class="identifier">level</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">level</span><span class="plain">&gt;0) &amp;&amp; (</span><span class="identifier">from</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">)) {</span>
<span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain"> = </span><span class="functiontext">ParseTree::new</span><span class="plain">(</span><span class="constant">INVALID_NT</span><span class="plain">);</span>
<span class="functiontext">ParseTree::copy_subtree</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">, </span><span class="identifier">level</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::copy_subtree appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP36"></a><b>&#167;36. Child count. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::no_children</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">=0;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = (</span><span class="identifier">pn</span><span class="plain">)?(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">):</span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) </span><span class="identifier">c</span><span class="plain">++;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::no_children appears nowhere else.</p>
<p class="inwebparagraph"><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 <code class="display"><span class="extract">PN</span></code>, we want to know if another node <code class="display"><span class="extract">to_find</span></code> lies beneath
it. (This will never be called when <code class="display"><span class="extract">PN</span></code> 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="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::contains</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">PN</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">to_find</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">to_try</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PN</span><span class="plain"> == </span><span class="identifier">to_find</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">to_try</span><span class="plain"> = </span><span class="identifier">PN</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">; </span><span class="identifier">to_try</span><span class="plain">; </span><span class="identifier">to_try</span><span class="plain"> = </span><span class="identifier">to_try</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::contains</span><span class="plain">(</span><span class="identifier">to_try</span><span class="plain">, </span><span class="identifier">to_find</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::contains appears nowhere else.</p>
<p class="inwebparagraph"><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 <code class="display"><span class="extract">PN</span></code> is the least-numbered word considered by any
node at or below <code class="display"><span class="extract">PN</span></code> in the tree; the "right edge" is the highest-numbered
word similarly considered.
</p>
<p class="inwebparagraph">The left edge is calculated by taking the minimum value of the word number
for <code class="display"><span class="extract">PN</span></code> 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="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::left_edge_of</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">PN</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">child</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">l</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="functiontext">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">)), </span><span class="identifier">lc</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">child</span><span class="plain"> = </span><span class="identifier">PN</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">; </span><span class="identifier">child</span><span class="plain">; </span><span class="identifier">child</span><span class="plain"> = </span><span class="identifier">child</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="identifier">lc</span><span class="plain"> = </span><span class="functiontext">ParseTree::left_edge_of</span><span class="plain">(</span><span class="identifier">child</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">lc</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) &amp;&amp; ((</span><span class="identifier">l</span><span class="plain"> == -1) || (</span><span class="identifier">lc</span><span class="plain"> &lt; </span><span class="identifier">l</span><span class="plain">))) </span><span class="identifier">l</span><span class="plain"> = </span><span class="identifier">lc</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">l</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::left_edge_of appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP39"></a><b>&#167;39. </b>Symmetrically, the right edge is found by taking the maximum word number
for <code class="display"><span class="extract">PN</span></code> and the right edges of its children.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::right_edge_of</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">PN</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">child</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">r</span><span class="plain"> = </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="functiontext">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">)), </span><span class="identifier">rc</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="functiontext">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">)) &lt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">r</span><span class="plain"> = -1;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">child</span><span class="plain"> = </span><span class="identifier">PN</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">; </span><span class="identifier">child</span><span class="plain">; </span><span class="identifier">child</span><span class="plain"> = </span><span class="identifier">child</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="identifier">rc</span><span class="plain"> = </span><span class="functiontext">ParseTree::right_edge_of</span><span class="plain">(</span><span class="identifier">child</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">rc</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) &amp;&amp; ((</span><span class="identifier">r</span><span class="plain"> == -1) || (</span><span class="identifier">rc</span><span class="plain"> &gt; </span><span class="identifier">r</span><span class="plain">))) </span><span class="identifier">r</span><span class="plain"> = </span><span class="identifier">rc</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">r</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::right_edge_of appears nowhere else.</p>
<p class="inwebparagraph"><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="inwebparagraph">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="display">
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">youngest_child_of_root</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="comment">youngest child of tree root</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">allow_last_sentence_cacheing</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::enable_last_sentence_cacheing</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">youngest_child_of_root</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="comment">because this may have changed since last enabled</span>
<span class="identifier">allow_last_sentence_cacheing</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::disable_last_sentence_cacheing</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">allow_last_sentence_cacheing</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::enable_last_sentence_cacheing is used in 2/snt (<a href="2-snt.html#SP5">&#167;5</a>).</p>
<p class="endnote">The function ParseTree::disable_last_sentence_cacheing is used in 2/snt (<a href="2-snt.html#SP5">&#167;5</a>).</p>
<p class="inwebparagraph"><a id="SP41"></a><b>&#167;41. </b>Now the metaphors get mixed. The routine below is called <code class="display"><span class="extract">ParseTree::graft</span></code>
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="inwebparagraph"><code class="display"><span class="extract">ParseTree::graft</span></code> returns the node for which <code class="display"><span class="extract">newborn</span></code> is the immediate sibling,
that is, it returns the previously youngest child of the <code class="display"><span class="extract">parent</span></code> (or <code class="display"><span class="extract">NULL</span></code>
if it previously had no children).
</p>
<pre class="display">
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="functiontext">ParseTree::graft</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">newborn</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">parent</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">elder</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">newborn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"newborn is null in tree ParseTree::graft"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">parent</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"parent is null in tree ParseTree::graft"</span><span class="plain">);</span>
<span class="comment">is the new node to be the only child of the old?</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">parent</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">parent</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="identifier">newborn</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">; }</span>
<span class="comment">can last sentence cacheing save us a long search through many children of root?</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">parent</span><span class="plain"> == </span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">) &amp;&amp; (</span><span class="identifier">allow_last_sentence_cacheing</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">youngest_child_of_root</span><span class="plain">) {</span>
<span class="identifier">elder</span><span class="plain"> = </span><span class="identifier">youngest_child_of_root</span><span class="plain">;</span>
<span class="identifier">elder</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">newborn</span><span class="plain">;</span>
<span class="identifier">youngest_child_of_root</span><span class="plain"> = </span><span class="identifier">newborn</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">elder</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">we don't know who's the youngest child now, but we know who soon will be:</span>
<span class="identifier">youngest_child_of_root</span><span class="plain"> = </span><span class="identifier">newborn</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="comment">find youngest child of attach node...</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">elder</span><span class="plain"> = </span><span class="identifier">parent</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">; </span><span class="identifier">elder</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">; </span><span class="identifier">elder</span><span class="plain"> = </span><span class="identifier">elder</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) ;</span>
<span class="comment">...and make the new node its younger sibling</span>
<span class="identifier">elder</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">newborn</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">elder</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::graft is used in <a href="#SP44">&#167;44</a>.</p>
<p class="inwebparagraph"><a id="SP42"></a><b>&#167;42. </b>No speed worries on the much smaller trees with alternative readings:
</p>
<pre class="display">
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="functiontext">ParseTree::graft_alternative</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">newborn</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">parent</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">newborn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"newborn is null in tree ParseTree::graft_alternative"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">parent</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"parent is null in tree ParseTree::graft_alternative"</span><span class="plain">);</span>
<span class="comment">is the new node to be the only child of the old?</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">parent</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">parent</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="identifier">newborn</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">; }</span>
<span class="comment">find youngest child of attach node...</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">elder</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">elder</span><span class="plain"> = </span><span class="identifier">parent</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">; </span><span class="identifier">elder</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">; </span><span class="identifier">elder</span><span class="plain"> = </span><span class="identifier">elder</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">) ;</span>
<span class="comment">...and make the new node its younger sibling</span>
<span class="identifier">elder</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain"> = </span><span class="identifier">newborn</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">elder</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::graft_alternative appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP43"></a><b>&#167;43. </b>And we can loop through these like so:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_THROUGH_ALTERNATIVES</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">from</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">)</span>
</pre>
<p class="inwebparagraph"><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="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::insert_sentence</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">new</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">one_off_attachment_point</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">one_off_attachment_point</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">;</span>
<span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">one_off_attachment_point</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">new</span><span class="plain">;</span>
<span class="identifier">new</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">;</span>
<span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">one_off_attachment_point</span><span class="plain"> = </span><span class="identifier">new</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">attachment_sp</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no attachment point"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">) == </span><span class="constant">HEADING_NT</span><span class="plain">) </span>&lt;<span class="cwebmacro">Adjust attachment point for a heading</span> <span class="cwebmacronumber">44.1</span>&gt;<span class="plain">;</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">sentence_attachment_point</span><span class="plain"> = </span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">attachment_stack_parent</span><span class="plain">[</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">attachment_sp</span><span class="plain">-1];</span>
<span class="functiontext">ParseTree::graft</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">new</span><span class="plain">, </span><span class="identifier">sentence_attachment_point</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">) == </span><span class="constant">HEADING_NT</span><span class="plain">) </span><span class="functiontext">ParseTree::push_attachment_point</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">new</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::insert_sentence is used in 2/snt (<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>).</p>
<p class="inwebparagraph"><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="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Adjust attachment point for a heading</span> <span class="cwebmacronumber">44.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">heading_level</span><span class="plain"> = </span><span class="functiontext">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="constant">heading_level_ANNOT</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">heading_level</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">attachment_sp</span><span class="plain">-1; </span><span class="identifier">i</span><span class="plain">&gt;=0; </span><span class="identifier">i</span><span class="plain">--) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain"> = </span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">attachment_stack_parent</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">) == </span><span class="constant">HEADING_NT</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="constant">heading_level_ANNOT</span><span class="plain">) &gt;= </span><span class="identifier">heading_level</span><span class="plain">))</span>
<span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">attachment_sp</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP44">&#167;44</a>.</p>
<p class="inwebparagraph"><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="inwebparagraph">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="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pn_log_token</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::log_tree</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">vpn</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain"> = (</span><span class="reserved">parse_node</span><span class="plain"> *) </span><span class="identifier">vpn</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;null-meaning-list&gt;\n"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="functiontext">ParseTree::log_subtree_recursively</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">1</span><span class="plain">, ++</span><span class="identifier">pn_log_token</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::log_subtree</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">vpn</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain"> = (</span><span class="reserved">parse_node</span><span class="plain"> *) </span><span class="identifier">vpn</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;null-parse-node&gt;"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"$P\n"</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">) {</span>
<span class="identifier">LOG_INDENT</span><span class="plain">;</span>
<span class="functiontext">ParseTree::log_subtree_recursively</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">1</span><span class="plain">, ++</span><span class="identifier">pn_log_token</span><span class="plain">);</span>
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::log_tree is used in <a href="#SP49">&#167;49</a>, 1/sm (<a href="1-sm.html#SP3_5">&#167;3.5</a>).</p>
<p class="endnote">The function ParseTree::log_subtree is used in 1/sm (<a href="1-sm.html#SP3_5">&#167;3.5</a>).</p>
<p class="inwebparagraph"><a id="SP46"></a><b>&#167;46. </b>Either way, we recurse as follows, being careful not to make recursive calls
to pursue <code class="display"><span class="extract">next</span></code> 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="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::log_subtree_recursively</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">num</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">of</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">gen</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">ltime</span><span class="plain">) {</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">log_time</span><span class="plain"> == </span><span class="identifier">ltime</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"*** Not a tree: %W ***\n"</span><span class="plain">, </span><span class="functiontext">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">)); </span><span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">log_time</span><span class="plain"> = </span><span class="identifier">ltime</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Calculate num and of such that this is [num/of] if they aren't already supplied</span> <span class="cwebmacronumber">46.1</span>&gt;<span class="character">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;null-parse-node&gt;\n"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">of</span><span class="plain"> &gt; </span><span class="constant">1</span><span class="plain">) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"[%d/%d] "</span><span class="plain">, </span><span class="identifier">num</span><span class="plain">, </span><span class="identifier">of</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::get_score</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">) != </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"(score %d) "</span><span class="plain">, </span><span class="functiontext">ParseTree::get_score</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"$P\n"</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">) {</span>
<span class="identifier">LOG_INDENT</span><span class="plain">;</span>
<span class="functiontext">ParseTree::log_subtree_recursively</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">gen</span><span class="plain">+1, </span><span class="identifier">ltime</span><span class="plain">);</span>
<span class="identifier">LOG_OUTDENT</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">) </span><span class="functiontext">ParseTree::log_subtree_recursively</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">, </span><span class="identifier">num</span><span class="plain">+1, </span><span class="identifier">of</span><span class="plain">, </span><span class="identifier">gen</span><span class="plain">+1, </span><span class="identifier">ltime</span><span class="plain">);</span>
<span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">; </span><span class="identifier">num</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">of</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">gen</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::log_subtree_recursively is used in <a href="#SP45">&#167;45</a>.</p>
<p class="inwebparagraph"><a id="SP46_1"></a><b>&#167;46.1. </b>When the first alternative is called, <code class="display"><span class="extract">ParseTree::log_subtree_recursively</span></code>
has arguments 0 and 0 for the possibility. The following code finds out the
correct value for <code class="display"><span class="extract">of</span></code>, setting this possibility to be <code class="display"><span class="extract">[1/of]</span></code>. When we later
iterate through other alternatives, we pass on correct values of <code class="display"><span class="extract">num</span></code> and <code class="display"><span class="extract">of</span></code>,
so that this code won't be used again on the same horizontal list of possibilities.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Calculate num and of such that this is [num/of] if they aren't already supplied</span> <span class="cwebmacronumber">46.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">num</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn2</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pn2</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">of</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">pn2</span><span class="plain">; </span><span class="identifier">pn2</span><span class="plain"> = </span><span class="identifier">pn2</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">, </span><span class="identifier">of</span><span class="plain">++) ;</span>
<span class="identifier">num</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP46">&#167;46</a>.</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::log_node</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">vpn</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain"> = (</span><span class="reserved">parse_node</span><span class="plain"> *) </span><span class="identifier">vpn</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;null-parse-node&gt;\n"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">PARSE_TREE_LOGGER</span>
<span class="identifier">PARSE_TREE_LOGGER</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">);</span>
<span class="plain">#</span><span class="reserved">else</span>
<span class="functiontext">ParseTree::log_type</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, (</span><span class="reserved">int</span><span class="plain">) </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="functiontext">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">))) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"'%W'"</span><span class="plain">, </span><span class="functiontext">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">));</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">LINGUISTICS_MODULE</span>
<span class="identifier">Diagrams::log_node</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">switch</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="identifier">node_type</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="identifier">HEADING_NT:</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" (level %d)"</span><span class="plain">, </span><span class="functiontext">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="constant">heading_level_ANNOT</span><span class="plain">)); </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">a</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">) &amp;&amp; (</span><span class="identifier">a</span><span class="plain">&lt;9)) </span><span class="identifier">a</span><span class="plain">++, </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">a</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"/%d"</span><span class="plain">, </span><span class="identifier">a</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::log_node is used in 1/sm (<a href="1-sm.html#SP3_5">&#167;3.5</a>).</p>
<p class="inwebparagraph"><a id="SP48"></a><b>&#167;48. </b>This is occasionally useful:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::log_with_annotations</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Diagnosis $P"</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="identifier">pna</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain"> = </span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"-%d"</span><span class="plain">, </span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">kind_of_annotation</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::log_with_annotations appears nowhere else.</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::write_to_file</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">filename</span><span class="plain"> *</span><span class="identifier">F</span><span class="plain">) {</span>
<span class="identifier">text_stream</span><span class="plain"> </span><span class="identifier">parse_tree_file</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">STREAM_OPEN_TO_FILE</span><span class="plain">(&amp;</span><span class="identifier">parse_tree_file</span><span class="plain">, </span><span class="identifier">F</span><span class="plain">, </span><span class="identifier">ISO_ENC</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"can't open file to write parse tree"</span><span class="plain">);</span>
<span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">save_DL</span><span class="plain"> = </span><span class="identifier">DL</span><span class="plain">;</span>
<span class="identifier">DL</span><span class="plain"> = &amp;</span><span class="identifier">parse_tree_file</span><span class="plain">;</span>
<span class="identifier">Streams::enable_debugging</span><span class="plain">(</span><span class="identifier">DL</span><span class="plain">);</span>
<span class="functiontext">ParseTree::log_tree</span><span class="plain">(</span><span class="identifier">DL</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">);</span>
<span class="identifier">DL</span><span class="plain"> = </span><span class="identifier">save_DL</span><span class="plain">;</span>
<span class="identifier">STREAM_CLOSE</span><span class="plain">(&amp;</span><span class="identifier">parse_tree_file</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::write_to_file appears nowhere else.</p>
<p class="inwebparagraph"><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">
<span class="plain">@</span><span class="reserved">default</span><span class="plain"> </span><span class="constant">PARSE_TREE_TRAVERSE_TYPE</span><span class="plain"> </span><span class="reserved">void</span>
</pre>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *)) {</span>
<span class="functiontext">ParseTree::traverse_from</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_from</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *)) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">SCS</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::top_level</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) </span><span class="functiontext">ParseTree::traverse_from</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::visitable</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::sentence_node</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="identifier">node_type</span><span class="plain">)) </span><span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="plain">(*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="identifier">pn</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">SCS</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_dfirst</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *)) {</span>
<span class="functiontext">ParseTree::traverse_dfirst_from</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_dfirst_from</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *)) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">SCS</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="functiontext">ParseTree::traverse_dfirst_from</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::sentence_node</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="identifier">node_type</span><span class="plain">)) </span><span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="plain">(*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="identifier">pn</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">SCS</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_wfirst</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *)) {</span>
<span class="functiontext">ParseTree::traverse_wfirst_from</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_wfirst_from</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *)) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">SCS</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::sentence_node</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="identifier">node_type</span><span class="plain">)) </span><span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="functiontext">ParseTree::traverse_wfirst_from</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">);</span>
<span class="plain">(*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="identifier">pn</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">SCS</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_with_stream</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="reserved">parse_node</span><span class="plain"> *)) {</span>
<span class="functiontext">ParseTree::traverse_from_with_stream</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_from_with_stream</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">OUT</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="identifier">text_stream</span><span class="plain"> *, </span><span class="reserved">parse_node</span><span class="plain"> *)) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">SCS</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::top_level</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">))</span>
<span class="functiontext">ParseTree::traverse_from_with_stream</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::visitable</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::sentence_node</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="identifier">node_type</span><span class="plain">)) </span><span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="plain">(*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">SCS</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_int</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">int</span><span class="plain"> *), </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain">) {</span>
<span class="functiontext">ParseTree::traverse_from_int</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_from_int</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">int</span><span class="plain"> *), </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">SCS</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::top_level</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) </span><span class="functiontext">ParseTree::traverse_from_int</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::visitable</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::sentence_node</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="identifier">node_type</span><span class="plain">)) </span><span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="plain">(*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">SCS</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_int_int</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">int</span><span class="plain"> *, </span><span class="reserved">int</span><span class="plain"> *), </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">Y</span><span class="plain">) {</span>
<span class="functiontext">ParseTree::traverse_from_int_int</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_from_int_int</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">int</span><span class="plain"> *, </span><span class="reserved">int</span><span class="plain"> *), </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">X</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">Y</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">SCS</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::top_level</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) </span><span class="functiontext">ParseTree::traverse_from_int_int</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::visitable</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::sentence_node</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="identifier">node_type</span><span class="plain">)) </span><span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="plain">(*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">, </span><span class="identifier">Y</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">SCS</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_ppn</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">parse_node</span><span class="plain"> **), </span><span class="reserved">parse_node</span><span class="plain"> **</span><span class="identifier">X</span><span class="plain">) {</span>
<span class="functiontext">ParseTree::traverse_from_ppn</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_from_ppn</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">parse_node</span><span class="plain"> **), </span><span class="reserved">parse_node</span><span class="plain"> **</span><span class="identifier">X</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">SCS</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::top_level</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) </span><span class="functiontext">ParseTree::traverse_from_ppn</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::visitable</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::sentence_node</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="identifier">node_type</span><span class="plain">)) </span><span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="plain">(*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">SCS</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_ppni</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node_tree</span><span class="plain"> *, </span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">int</span><span class="plain"> *), </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">N</span><span class="plain">) {</span>
<span class="functiontext">ParseTree::traverse_from_ppni</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_from_ppni</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node_tree</span><span class="plain"> *, </span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">int</span><span class="plain"> *), </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">last_h0</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> *</span><span class="identifier">N</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">SCS</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::top_level</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">H0</span><span class="plain"> = </span><span class="identifier">last_h0</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">ParseTree::is</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="constant">HEADING_NT</span><span class="plain">)) &amp;&amp; (</span><span class="functiontext">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="constant">heading_level_ANNOT</span><span class="plain">) == </span><span class="constant">0</span><span class="plain">))</span>
<span class="identifier">H0</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="functiontext">ParseTree::traverse_from_ppni</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">, </span><span class="identifier">H0</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::visitable</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::sentence_node</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="identifier">node_type</span><span class="plain">)) </span><span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="plain">(*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">last_h0</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">SCS</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_up_to_ip</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">end</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="constant">PARSE_TREE_TRAVERSE_TYPE</span><span class="plain"> **), </span><span class="constant">PARSE_TREE_TRAVERSE_TYPE</span><span class="plain"> **</span><span class="identifier">X</span><span class="plain">) {</span>
<span class="functiontext">ParseTree::traverse_from_up_to_ip</span><span class="plain">(</span><span class="identifier">end</span><span class="plain">, </span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_from_up_to_ip</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">end</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="constant">PARSE_TREE_TRAVERSE_TYPE</span><span class="plain"> **), </span><span class="constant">PARSE_TREE_TRAVERSE_TYPE</span><span class="plain"> **</span><span class="identifier">X</span><span class="plain">) {</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">SCS</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> == </span><span class="identifier">end</span><span class="plain">) { </span><span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">SCS</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">; }</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::top_level</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::traverse_from_up_to_ip</span><span class="plain">(</span><span class="identifier">end</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">)) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">SCS</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::visitable</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::sentence_node</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="identifier">node_type</span><span class="plain">)) </span><span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="plain">(*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">SCS</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_ppn_nocs</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">parse_node</span><span class="plain"> **), </span><span class="reserved">parse_node</span><span class="plain"> **</span><span class="identifier">X</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_from_ppn_nocs</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::traverse_from_ppn_nocs</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> (*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">parse_node</span><span class="plain"> *, </span><span class="reserved">parse_node</span><span class="plain"> **), </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> **</span><span class="identifier">X</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::visitable</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> ((*</span><span class="identifier">visitor</span><span class="plain">)(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">)) { </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">; }</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::top_level</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">node_type</span><span class="plain">)) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">res</span><span class="plain"> = </span><span class="functiontext">ParseTree::traverse_from_ppn_nocs</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">visitor</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">X</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">res</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::traverse appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_from appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_dfirst appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_dfirst_from appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_wfirst appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_wfirst_from appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_with_stream appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_from_with_stream appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_int appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_from_int appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_int_int appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_from_int_int appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_ppn appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_from_ppn appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_ppni appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_from_ppni appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_up_to_ip appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_from_up_to_ip appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_ppn_nocs appears nowhere else.</p>
<p class="endnote">The function ParseTree::traverse_from_ppn_nocs appears nowhere else.</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::sentence_node</span><span class="plain">(</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">SENTENCE_NODE</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">SENTENCE_NODE</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="identifier">SENTENCE_NODE</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::sentence_node is used in <a href="#SP50">&#167;50</a>.</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">tree_stats_size</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">tree_stats_depth</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">, </span><span class="identifier">tree_stats_width</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::verify_integrity</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">worth_logging</span><span class="plain">) {</span>
<span class="identifier">tree_stats_size</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">tree_stats_depth</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">tree_stats_width</span><span class="plain"> = </span><span class="constant">1</span><span class="plain">;</span>
<span class="functiontext">ParseTree::verify_tree_integrity_recursively</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="string">"down"</span><span class="plain">, </span><span class="constant">0</span><span class="plain">, ++</span><span class="identifier">pn_log_token</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">worth_logging</span><span class="plain">)</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">VERIFICATIONS</span><span class="plain">, </span><span class="string">"[Initial parse tree has %d nodes, width %d and depth %d.]\n"</span><span class="plain">,</span>
<span class="identifier">tree_stats_size</span><span class="plain">, </span><span class="identifier">tree_stats_width</span><span class="plain">, </span><span class="identifier">tree_stats_depth</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::verify_integrity is used in <a href="#SP54">&#167;54</a>.</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::verify_tree_integrity_recursively</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">,</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">from</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">way</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">depth</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">ltime</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">width</span><span class="plain">;</span>
<span class="identifier">pointer_sized_int</span><span class="plain"> </span><span class="identifier">probably_an_address</span><span class="plain"> = (</span><span class="identifier">pointer_sized_int</span><span class="plain">) </span><span class="identifier">p</span><span class="plain">;</span>
<span class="identifier">depth</span><span class="plain">++; </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">depth</span><span class="plain"> &gt; </span><span class="identifier">tree_stats_depth</span><span class="plain">) </span><span class="identifier">tree_stats_depth</span><span class="plain"> = </span><span class="identifier">depth</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">width</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">, </span><span class="identifier">width</span><span class="plain">++) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">probably_an_address</span><span class="plain"> == </span><span class="constant">0</span><span class="plain">) || (</span><span class="identifier">probably_an_address</span><span class="plain"> == -1)) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Link %s broken from:\n$P"</span><span class="plain">, </span><span class="identifier">way</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">);</span>
<span class="identifier">Errors::set_internal_handler</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Link broken in parse tree"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">log_time</span><span class="plain"> == </span><span class="identifier">ltime</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Cycle found in parse tree, found %s from:\n$P"</span><span class="plain">, </span><span class="identifier">way</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">);</span>
<span class="identifier">Errors::set_internal_handler</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Cycle found in parse tree"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">log_time</span><span class="plain"> = </span><span class="identifier">ltime</span><span class="plain">;</span>
<span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain"> = </span><span class="functiontext">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::valid_type</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">)) </span><span class="identifier">tree_stats_size</span><span class="plain">++;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Invalid node type (%08x) found %s from:\n$P"</span><span class="plain">, (</span><span class="reserved">int</span><span class="plain">) </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">way</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">);</span>
<span class="identifier">Errors::set_internal_handler</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Link broken in parse tree"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">)</span>
<span class="functiontext">ParseTree::verify_tree_integrity_recursively</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="string">"alt"</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">, </span><span class="identifier">ltime</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">)</span>
<span class="functiontext">ParseTree::verify_tree_integrity_recursively</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">, </span><span class="string">"down"</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">, </span><span class="identifier">ltime</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">width</span><span class="plain"> &gt; </span><span class="identifier">tree_stats_width</span><span class="plain">) </span><span class="identifier">tree_stats_width</span><span class="plain"> = </span><span class="identifier">width</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::verify_tree_integrity_recursively is used in <a href="#SP52">&#167;52</a>.</p>
<p class="inwebparagraph"><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 <code class="display"><span class="extract">SENTENCE_NT</span></code> node cannot legally be beneath a
<code class="display"><span class="extract">PROPER_NOUN_NT</span></code> 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="inwebparagraph">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="inwebparagraph">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="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::verify</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">VERIFICATIONS</span><span class="plain">, </span><span class="string">"[Verifying initial parse tree]\n"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">Errors::set_internal_handler</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Root of parse tree NULL"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">ParseTree::verify_structure</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">-&gt;</span><span class="element">root_node</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">VERIFICATIONS</span><span class="plain">, </span><span class="string">"[Initial parse tree correct.]\n"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">node_errors</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::verify_structure</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
<span class="functiontext">ParseTree::verify_integrity</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="functiontext">ParseTree::make_parentage_allowed_table</span><span class="plain">();</span>
<span class="functiontext">ParseTree::make_annotation_allowed_table</span><span class="plain">();</span>
<span class="identifier">node_errors</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="functiontext">ParseTree::verify_structure_recursively</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">node_errors</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"[Verification failed: %d node errors]\n"</span><span class="plain">, </span><span class="identifier">node_errors</span><span class="plain">);</span>
<span class="identifier">Errors::set_internal_handler</span><span class="plain">(</span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Parse tree broken"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::verify appears nowhere else.</p>
<p class="endnote">The function ParseTree::verify_structure appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP55"></a><b>&#167;55. </b>Note that on every call to the following routine, (i) <code class="display"><span class="extract">p</span></code> is a valid
parse node and (ii) either <code class="display"><span class="extract">p</span></code> is the tree root, in which case <code class="display"><span class="extract">parent</span></code> is
<code class="display"><span class="extract">NULL</span></code>, or <code class="display"><span class="extract">parent</span></code> is the unique node having <code class="display"><span class="extract">p</span></code> (or an alternative to <code class="display"><span class="extract">p</span></code>)
among its children.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::verify_structure_recursively</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">parent</span><span class="plain">) {</span>
<span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain"> = </span><span class="functiontext">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">parse_tree_node_type</span><span class="plain"> *</span><span class="identifier">metadata</span><span class="plain"> = </span><span class="functiontext">ParseTree::node_metadata</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">metadata</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"broken tree should have been reported"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Check rule (1) of the invariant</span> <span class="cwebmacronumber">55.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Check rule (2) of the invariant</span> <span class="cwebmacronumber">55.2</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">parent</span><span class="plain">) </span>&lt;<span class="cwebmacro">Check rule (3) of the invariant</span> <span class="cwebmacronumber">55.3</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">children_count</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">q</span><span class="plain">=</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">; </span><span class="identifier">q</span><span class="plain">; </span><span class="identifier">q</span><span class="plain">=</span><span class="identifier">q</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain">, </span><span class="identifier">children_count</span><span class="plain">++)</span>
<span class="functiontext">ParseTree::verify_structure_recursively</span><span class="plain">(</span><span class="identifier">q</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Check rule (4) of the invariant</span> <span class="cwebmacronumber">55.4</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">)</span>
<span class="functiontext">ParseTree::verify_structure_recursively</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">, </span><span class="identifier">parent</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::verify_structure_recursively is used in <a href="#SP54">&#167;54</a>.</p>
<p class="inwebparagraph"><a id="SP55_1"></a><b>&#167;55.1. </b>Rule (1): no INVALID nodes.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Check rule (1) of the invariant</span> <span class="cwebmacronumber">55.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">t</span><span class="plain"> == </span><span class="constant">INVALID_NT</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"N%d is $N, which is not allowed except temporarily\n"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Log this invariant failure</span> <span class="cwebmacronumber">55.1.1</span>&gt;
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP55">&#167;55</a>.</p>
<p class="inwebparagraph"><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="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Check rule (2) of the invariant</span> <span class="cwebmacronumber">55.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">parse_node_annotation</span><span class="plain"> *</span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="element">annotations</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">; </span><span class="identifier">pna</span><span class="plain">=</span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">next_annotation</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (!(</span><span class="functiontext">ParseTree::annotation_allowed</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">kind_of_annotation</span><span class="plain">))) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"N%d is $N, which is not allowed to have annotation %d\n"</span><span class="plain">,</span>
<span class="identifier">p</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">kind_of_annotation</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Node %08x, ann %d\n"</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">pna</span><span class="plain">-&gt;</span><span class="element">kind_of_annotation</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Log this invariant failure</span> <span class="cwebmacronumber">55.1.1</span>&gt;
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP55">&#167;55</a>.</p>
<p class="inwebparagraph"><a id="SP55_3"></a><b>&#167;55.3. </b>Rule (3): can this combination of parent and child exist?
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Check rule (3) of the invariant</span> <span class="cwebmacronumber">55.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t_parent</span><span class="plain"> = </span><span class="functiontext">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">parent</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">child_category</span><span class="plain"> = </span><span class="identifier">metadata</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain">;</span>
<span class="reserved">parse_tree_node_type</span><span class="plain"> *</span><span class="identifier">metadata_parent</span><span class="plain"> = </span><span class="functiontext">ParseTree::node_metadata</span><span class="plain">(</span><span class="identifier">t_parent</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">metadata_parent</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"broken tree should have been reported"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">parent_category</span><span class="plain"> = </span><span class="identifier">metadata_parent</span><span class="plain">-&gt;</span><span class="element">category</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (!(</span><span class="functiontext">ParseTree::parentage_allowed</span><span class="plain">(</span><span class="identifier">t_parent</span><span class="plain">, </span><span class="identifier">parent_category</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">child_category</span><span class="plain">))) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"N%d is $N (category %d): should not be a child of $N (category %d)\n"</span><span class="plain">,</span>
<span class="identifier">p</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">child_category</span><span class="plain">, </span><span class="identifier">t_parent</span><span class="plain">, </span><span class="identifier">parent_category</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Log this invariant failure</span> <span class="cwebmacronumber">55.1.1</span>&gt;
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP55">&#167;55</a>.</p>
<p class="inwebparagraph"><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="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Check rule (4) of the invariant</span> <span class="cwebmacronumber">55.4</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">children_count</span><span class="plain"> &lt; </span><span class="identifier">metadata</span><span class="plain">-&gt;</span><span class="element">min_children</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"N%d has %d children, but min for $N is %d:\n"</span><span class="plain">,</span>
<span class="identifier">p</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">children_count</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">metadata</span><span class="plain">-&gt;</span><span class="element">min_children</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Log this invariant failure</span> <span class="cwebmacronumber">55.1.1</span>&gt;
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">children_count</span><span class="plain"> &gt; </span><span class="identifier">metadata</span><span class="plain">-&gt;</span><span class="element">max_children</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"N%d has %d children, but max for $N is %d:\n"</span><span class="plain">,</span>
<span class="identifier">p</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">children_count</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">metadata</span><span class="plain">-&gt;</span><span class="element">max_children</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Log this invariant failure</span> <span class="cwebmacronumber">55.1.1</span>&gt;
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP55">&#167;55</a>.</p>
<p class="inwebparagraph"><a id="SP55_1_1"></a><b>&#167;55.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Log this invariant failure</span> <span class="cwebmacronumber">55.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::is</span><span class="plain">(</span><span class="identifier">parent</span><span class="plain">, </span><span class="constant">ROOT_NT</span><span class="plain">)) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Failing subtree:\n$T"</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Failing subtree:\n$T"</span><span class="plain">, </span><span class="identifier">parent</span><span class="plain">);</span>
<span class="identifier">node_errors</span><span class="plain">++;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP55_1">&#167;55.1</a>, <a href="#SP55_2">&#167;55.2</a>, <a href="#SP55_3">&#167;55.3</a>, <a href="#SP55_4">&#167;55.4</a> (twice).</p>
<p class="inwebparagraph"><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="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">parentage_allowed_set_up</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">parentage_allowed</span><span class="plain">[</span><span class="identifier">NO_DEFINED_NCAT_VALUES</span><span class="plain">][</span><span class="identifier">NO_DEFINED_NCAT_VALUES</span><span class="plain">];</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::make_parentage_allowed_table</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">parentage_allowed_set_up</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">parentage_allowed_set_up</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">i</span><span class="plain"> &lt; </span><span class="identifier">NO_DEFINED_NCAT_VALUES</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">j</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">j</span><span class="plain"> &lt; </span><span class="identifier">NO_DEFINED_NCAT_VALUES</span><span class="plain">; </span><span class="identifier">j</span><span class="plain">++)</span>
<span class="identifier">parentage_allowed</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">][</span><span class="identifier">j</span><span class="plain">] = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">parentage_allowed</span><span class="plain">[</span><span class="constant">L1_NCAT</span><span class="plain">][</span><span class="constant">L1_NCAT</span><span class="plain">] = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::make_parentage_allowed_table is used in <a href="#SP54">&#167;54</a>.</p>
<p class="inwebparagraph"><a id="SP57"></a><b>&#167;57. </b>But there are exceptions. Note that an <code class="display"><span class="extract">L2_NCAT</span></code> node can have no parent
at all, according to the broad rules above: in fact, it can, but only if
the parent is <code class="display"><span class="extract">HEADING_NT</span></code>.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::parentage_allowed</span><span class="plain">(</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t_parent</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">cat_parent</span><span class="plain">,</span>
<span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t_child</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">cat_child</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">parentage_allowed</span><span class="plain">[</span><span class="identifier">cat_parent</span><span class="plain">][</span><span class="identifier">cat_child</span><span class="plain">]) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">PARENTAGE_EXCEPTIONS</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PARENTAGE_EXCEPTIONS</span><span class="plain">(</span><span class="identifier">t_parent</span><span class="plain">, </span><span class="identifier">cat_parent</span><span class="plain">, </span><span class="identifier">t_child</span><span class="plain">, </span><span class="identifier">cat_child</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">t_parent</span><span class="plain"> == </span><span class="constant">AMBIGUITY_NT</span><span class="plain">) || (</span><span class="identifier">t_child</span><span class="plain"> == </span><span class="constant">AMBIGUITY_NT</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::parentage_allowed is used in <a href="#SP55_3">&#167;55.3</a>.</p>
<p class="inwebparagraph"><a id="SP58"></a><b>&#167;58. Annotation rules. </b>This is on an altogether grander scale.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_NODE_TYPES</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">)</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">=</span><span class="constant">BASE_OF_ENUMERATED_NTS</span><span class="plain">; </span><span class="identifier">t</span><span class="plain">&lt;</span><span class="constant">BASE_OF_ENUMERATED_NTS</span><span class="plain">+</span><span class="identifier">NO_DEFINED_NT_VALUES</span><span class="plain">; </span><span class="identifier">t</span><span class="plain">++)</span>
</pre>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">annotation_allowed_set_up</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">annotation_allowed</span><span class="plain">[</span><span class="identifier">NO_DEFINED_NT_VALUES</span><span class="plain">][</span><span class="constant">MAX_ANNOT_NUMBER</span><span class="plain">+1];</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::allow_annotation</span><span class="plain">(</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">annot</span><span class="plain">) {</span>
<span class="identifier">annotation_allowed</span><span class="plain">[</span><span class="identifier">t</span><span class="plain"> - </span><span class="constant">BASE_OF_ENUMERATED_NTS</span><span class="plain">][</span><span class="identifier">annot</span><span class="plain">] = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::allow_annotation_to_category</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">cat</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">annot</span><span class="plain">) {</span>
<span class="identifier">LOOP_OVER_NODE_TYPES</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::cat</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">) == </span><span class="identifier">cat</span><span class="plain">)</span>
<span class="functiontext">ParseTree::allow_annotation</span><span class="plain">(</span><span class="identifier">t</span><span class="plain">, </span><span class="identifier">annot</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::allow_annotation is used in <a href="#SP59">&#167;59</a>.</p>
<p class="endnote">The function ParseTree::allow_annotation_to_category is used in <a href="#SP59">&#167;59</a>.</p>
<p class="inwebparagraph"><a id="SP59"></a><b>&#167;59. </b>The eagle-eyed observer will note that the <code class="display"><span class="extract">meaning</span></code> 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="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::make_annotation_allowed_table</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">annotation_allowed_set_up</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">annotation_allowed_set_up</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="functiontext">ParseTree::allow_annotation</span><span class="plain">(</span><span class="constant">HEADING_NT</span><span class="plain">, </span><span class="constant">heading_level_ANNOT</span><span class="plain">);</span>
<span class="functiontext">ParseTree::allow_annotation</span><span class="plain">(</span><span class="constant">SENTENCE_NT</span><span class="plain">, </span><span class="constant">language_element_ANNOT</span><span class="plain">);</span>
<span class="functiontext">ParseTree::allow_annotation_to_category</span><span class="plain">(</span><span class="constant">L1_NCAT</span><span class="plain">, </span><span class="constant">sentence_unparsed_ANNOT</span><span class="plain">);</span>
<span class="functiontext">ParseTree::allow_annotation_to_category</span><span class="plain">(</span><span class="constant">L2_NCAT</span><span class="plain">, </span><span class="constant">sentence_unparsed_ANNOT</span><span class="plain">);</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">ANNOTATION_PERMISSIONS_WRITER</span>
<span class="identifier">ANNOTATION_PERMISSIONS_WRITER</span><span class="plain">();</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">ParseTree::annotation_allowed</span><span class="plain">(</span><span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">t</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">annot</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">annot</span><span class="plain"> &lt;= </span><span class="constant">0</span><span class="plain">) || (</span><span class="identifier">annot</span><span class="plain"> &gt; </span><span class="constant">MAX_ANNOT_NUMBER</span><span class="plain">))</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"annotation number out of range"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">t</span><span class="plain"> &gt;= </span><span class="constant">BASE_OF_ENUMERATED_NTS</span><span class="plain">) &amp;&amp; (</span><span class="identifier">t</span><span class="plain"> &lt; </span><span class="constant">BASE_OF_ENUMERATED_NTS</span><span class="plain">+</span><span class="identifier">NO_DEFINED_NT_VALUES</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">annotation_allowed</span><span class="plain">[</span><span class="identifier">t</span><span class="plain"> - </span><span class="constant">BASE_OF_ENUMERATED_NTS</span><span class="plain">][</span><span class="identifier">annot</span><span class="plain">];</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::make_annotation_allowed_table is used in <a href="#SP54">&#167;54</a>.</p>
<p class="endnote">The function ParseTree::annotation_allowed is used in <a href="#SP25">&#167;25</a>, <a href="#SP55_2">&#167;55.2</a>.</p>
<p class="inwebparagraph"><a id="SP60"></a><b>&#167;60. Ambiguity subtrees. </b></p>
<pre class="display">
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="functiontext">ParseTree::add_possible_reading</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">existing</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">reading</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">existing</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">reading</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::is</span><span class="plain">(</span><span class="identifier">reading</span><span class="plain">, </span><span class="identifier">UNKNOWN_NT</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">existing</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::is</span><span class="plain">(</span><span class="identifier">reading</span><span class="plain">, </span><span class="constant">AMBIGUITY_NT</span><span class="plain">)) </span><span class="identifier">reading</span><span class="plain"> = </span><span class="identifier">reading</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::is</span><span class="plain">(</span><span class="identifier">existing</span><span class="plain">, </span><span class="constant">AMBIGUITY_NT</span><span class="plain">)) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTreeUsage::is_phrasal</span><span class="plain">(</span><span class="identifier">reading</span><span class="plain">))</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain"> = </span><span class="identifier">existing</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">; </span><span class="identifier">E</span><span class="plain">; </span><span class="identifier">E</span><span class="plain"> = </span><span class="identifier">E</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">reading</span><span class="plain">) == </span><span class="functiontext">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">)) {</span>
<span class="functiontext">ParseTree::add_pr_inv</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">reading</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">existing</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">existing</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">L</span><span class="plain">) &amp;&amp; (</span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">)) </span><span class="identifier">L</span><span class="plain"> = </span><span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">;</span>
<span class="identifier">L</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain"> = </span><span class="identifier">reading</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">existing</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTreeUsage::is_phrasal</span><span class="plain">(</span><span class="identifier">reading</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">reading</span><span class="plain">) == </span><span class="functiontext">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">existing</span><span class="plain">))) {</span>
<span class="functiontext">ParseTree::add_pr_inv</span><span class="plain">(</span><span class="identifier">existing</span><span class="plain">, </span><span class="identifier">reading</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">existing</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">A</span><span class="plain"> = </span><span class="functiontext">ParseTree::new_with_words</span><span class="plain">(</span><span class="constant">AMBIGUITY_NT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">A</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="identifier">existing</span><span class="plain">;</span>
<span class="identifier">A</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain"> = </span><span class="identifier">reading</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">A</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::add_pr_inv</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">reading</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">N</span><span class="plain"> = </span><span class="identifier">reading</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, *</span><span class="identifier">next_N</span><span class="plain"> = (</span><span class="identifier">N</span><span class="plain">)?(</span><span class="identifier">N</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">):</span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">N</span><span class="plain">;</span>
<span class="identifier">N</span><span class="plain"> = </span><span class="identifier">next_N</span><span class="plain">, </span><span class="identifier">next_N</span><span class="plain"> = (</span><span class="identifier">N</span><span class="plain">)?(</span><span class="identifier">N</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">):</span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="functiontext">ParseTree::add_single_pr_inv</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ParseTree::add_single_pr_inv</span><span class="plain">(</span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">E</span><span class="plain">, </span><span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">N</span><span class="plain">) {</span>
<span class="identifier">E</span><span class="plain"> = </span><span class="identifier">E</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Invocations::eq</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">E</span><span class="plain">) &amp;&amp; (</span><span class="identifier">E</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">)) {</span>
<span class="identifier">E</span><span class="plain"> = </span><span class="identifier">E</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Invocations::eq</span><span class="plain">(</span><span class="identifier">E</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">E</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain"> = </span><span class="identifier">N</span><span class="plain">; </span><span class="identifier">N</span><span class="plain">-&gt;</span><span class="element">next_alternative</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ParseTree::add_possible_reading appears nowhere else.</p>
<p class="endnote">The function ParseTree::add_pr_inv appears nowhere else.</p>
<p class="endnote">The function ParseTree::add_single_pr_inv appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><i>(This section begins Chapter 2: The Parse Tree.)</i></li><li><a href="2-snt.html">Continue with 'Sentences'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>