mirror of
https://github.com/ganelson/inform.git
synced 2024-07-05 16:44:21 +03:00
1958 lines
259 KiB
HTML
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">§1. Trees store meanings</a></li><li><a href="#SP4">§4. Structural vs specifications</a></li><li><a href="#SP5">§5. Node types</a></li><li><a href="#SP7">§7. The structure</a></li><li><a href="#SP8">§8. Where we currently are in the text</a></li><li><a href="#SP12">§12. Node metadata</a></li><li><a href="#SP16">§16. The metadata table</a></li><li><a href="#SP20">§20. Logging node types</a></li><li><a href="#SP21">§21. Creation</a></li><li><a href="#SP24">§24. Annotations</a></li><li><a href="#SP33">§33. Copying parse nodes</a></li><li><a href="#SP36">§36. Child count</a></li><li><a href="#SP37">§37. Detection of subnodes</a></li><li><a href="#SP38">§38. The word range beneath a given node</a></li><li><a href="#SP45">§45. Logging the parse tree</a></li><li><a href="#SP50">§50. General traversals</a></li><li><a href="#SP52">§52. Verify integrity</a></li><li><a href="#SP54">§54. Verify structure</a></li><li><a href="#SP56">§56. Parentage rules</a></li><li><a href="#SP58">§58. Annotation rules</a></li><li><a href="#SP60">§60. Ambiguity subtrees</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§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 — if used — 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">-></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">-></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">-></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">-></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>§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">-></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">-></span><span class="element">attachment_sp</span><span class="plain"> >= </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">-></span><span class="element">attachment_stack_parent</span><span class="plain">[</span><span class="identifier">T</span><span class="plain">-></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">-></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">§1</a>, <a href="#SP44">§44</a>.</p>
|
|
|
|
<p class="endnote">The function ParseTree::pop_attachment_point appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§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">-></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>§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>§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>§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>§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>§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>§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>§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>§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>§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>§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>§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>§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>§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">§17</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP17"></a><b>§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">§3</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18"></a><b>§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"> >= </span><span class="constant">BASE_OF_ENUMERATED_NTS</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">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"> = &(</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">-></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">§19</a>, <a href="#SP20">§20</a>, <a href="#SP55">§55</a>, <a href="#SP55_3">§55.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19"></a><b>§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"> >= </span><span class="constant">BASE_OF_ENUMERATED_NTS</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">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">-></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">) && (</span><span class="identifier">metadata</span><span class="plain">-></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">) && ((</span><span class="identifier">metadata</span><span class="plain">-></span><span class="element">node_flags</span><span class="plain">) & </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">§16</a>, <a href="#SP53">§53</a>.</p>
|
|
|
|
<p class="endnote">The function ParseTree::cat is used in <a href="#SP58">§58</a>.</p>
|
|
|
|
<p class="endnote">The function ParseTree::top_level is used in <a href="#SP50">§50</a>.</p>
|
|
|
|
<p class="endnote">The function ParseTree::visitable is used in <a href="#SP50">§50</a>.</p>
|
|
|
|
<p class="endnote">The function ParseTree::test_flag is used in 2/snt (<a href="2-snt.html#SP5_2">§5.2</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20"></a><b>§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">-></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">-></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">§47</a>, 1/sm (<a href="1-sm.html#SP3_5">§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>§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">-></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">-></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">-></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">-></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">-></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">-></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">§1</a>, <a href="#SP22">§22</a>, <a href="#SP33">§33</a>, <a href="#SP35">§35</a>, 2/snt (<a href="2-snt.html#SP6_1">§6.1</a>, <a href="2-snt.html#SP6_6">§6.6</a>, <a href="2-snt.html#SP6_9_4">§6.9.4</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP22"></a><b>§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">§60</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23"></a><b>§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">-></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">-></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">§38</a>, <a href="#SP39">§39</a>, <a href="#SP46">§46</a>, <a href="#SP47">§47</a>.</p>
|
|
|
|
<p class="endnote">The function ParseTree::set_text is used in <a href="#SP21">§21</a>, <a href="#SP22">§22</a>, 2/snt (<a href="2-snt.html#SP6_1">§6.1</a>, <a href="2-snt.html#SP6_6">§6.6</a>, <a href="2-snt.html#SP6_9_4">§6.9.4</a>, <a href="2-snt.html#SP6_9_7">§6.9.7</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24"></a><b>§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">-></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">) && (</span><span class="identifier">pn</span><span class="plain">-></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">§44</a>, <a href="#SP44_1">§44.1</a>, <a href="#SP53">§53</a>, <a href="#SP55">§55</a>, <a href="#SP55_3">§55.3</a>, <a href="#SP60">§60</a>.</p>
|
|
|
|
<p class="endnote">The function ParseTree::is is used in <a href="#SP50">§50</a>, <a href="#SP55_1_1">§55.1.1</a>, <a href="#SP60">§60</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25"></a><b>§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">-></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">-></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">-></span><span class="element">annotations</span><span class="plain">) &&</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">-></span><span class="element">annotations</span><span class="plain">-></span><span class="element">kind_of_annotation</span><span class="plain">))))</span>
|
|
<span class="identifier">pn</span><span class="plain">-></span><span class="element">annotations</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-></span><span class="element">annotations</span><span class="plain">-></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">-></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">-></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">-></span><span class="identifier">next_annotation</span><span class="plain">) &&</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">-></span><span class="element">next_annotation</span><span class="plain">-></span><span class="element">kind_of_annotation</span><span class="plain">))))</span>
|
|
<span class="identifier">pna</span><span class="plain">-></span><span class="element">next_annotation</span><span class="plain"> = </span><span class="identifier">pna</span><span class="plain">-></span><span class="element">next_annotation</span><span class="plain">-></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">-></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">-></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">§6.9</a>, <a href="2-snt.html#SP6_9_5">§6.9.5</a>, <a href="2-snt.html#SP6_9_6">§6.9.6</a>, <a href="2-snt.html#SP6_9_7">§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>§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">-></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">-></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">§46</a>.</p>
|
|
|
|
<p class="endnote">The function ParseTree::set_score is used in <a href="#SP21">§21</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP27"></a><b>§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">-></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">-></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">-></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">-></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">§30</a>, <a href="#SP31">§31</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP28"></a><b>§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">-></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">-></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">-></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">§32</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP29"></a><b>§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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">§44.1</a>, <a href="#SP47">§47</a>, <a href="#SP50">§50</a>.</p>
|
|
|
|
<p class="endnote">The function ParseTree::pn_pointer_annotation is used in <a href="#SP32">§32</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP30"></a><b>§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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">§6.1</a>, <a href="2-snt.html#SP6_6">§6.6</a>, <a href="2-snt.html#SP6_9">§6.9</a>, <a href="2-snt.html#SP6_9_4">§6.9.4</a>, <a href="2-snt.html#SP6_9_5">§6.9.5</a>, <a href="2-snt.html#SP6_9_8">§6.9.8</a>, <a href="2-snt.html#SP6_9_9">§6.9.9</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP31"></a><b>§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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">§32</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP32"></a><b>§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>§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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">§34</a>, <a href="#SP35">§35</a>.</p>
|
|
|
|
<p class="endnote">The function ParseTree::duplicate appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP34"></a><b>§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">-></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">-></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">-></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">-></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">-></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">-></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>§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">-></span><span class="identifier">down</span><span class="plain">) {</span>
|
|
<span class="identifier">to</span><span class="plain">-></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">-></span><span class="element">down</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">-></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">>0) && (</span><span class="identifier">from</span><span class="plain">-></span><span class="element">next</span><span class="plain">)) {</span>
|
|
<span class="identifier">to</span><span class="plain">-></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">-></span><span class="element">next</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">-></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">>0) && (</span><span class="identifier">from</span><span class="plain">-></span><span class="element">next_alternative</span><span class="plain">)) {</span>
|
|
<span class="identifier">to</span><span class="plain">-></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">-></span><span class="element">next_alternative</span><span class="plain">, </span><span class="identifier">to</span><span class="plain">-></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>§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">-></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">-></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>§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">-></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">-></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>§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">-></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">-></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"> >= </span><span class="constant">0</span><span class="plain">) && ((</span><span class="identifier">l</span><span class="plain"> == -1) || (</span><span class="identifier">lc</span><span class="plain"> < </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>§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">)) < </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">-></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">-></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"> >= </span><span class="constant">0</span><span class="plain">) && ((</span><span class="identifier">r</span><span class="plain"> == -1) || (</span><span class="identifier">rc</span><span class="plain"> > </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>§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">§5</a>).</p>
|
|
|
|
<p class="endnote">The function ParseTree::disable_last_sentence_cacheing is used in 2/snt (<a href="2-snt.html#SP5">§5</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP41"></a><b>§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">-></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">-></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">-></span><span class="element">root_node</span><span class="plain">) && (</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">-></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">-></span><span class="element">down</span><span class="plain">; </span><span class="identifier">elder</span><span class="plain">-></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">-></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">-></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">§44</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP42"></a><b>§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">-></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">-></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">-></span><span class="element">down</span><span class="plain">; </span><span class="identifier">elder</span><span class="plain">-></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">-></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">-></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>§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">-></span><span class="element">next_alternative</span><span class="plain">)</span>
|
|
</pre>
|
|
<p class="inwebparagraph"><a id="SP44"></a><b>§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">-></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">-></span><span class="element">one_off_attachment_point</span><span class="plain">-></span><span class="element">next</span><span class="plain">;</span>
|
|
<span class="identifier">T</span><span class="plain">-></span><span class="element">one_off_attachment_point</span><span class="plain">-></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">-></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">-></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">-></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><<span class="cwebmacro">Adjust attachment point for a heading</span> <span class="cwebmacronumber">44.1</span>><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">-></span><span class="element">attachment_stack_parent</span><span class="plain">[</span><span class="identifier">T</span><span class="plain">-></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">§6.1</a>, <a href="2-snt.html#SP6_6">§6.6</a>, <a href="2-snt.html#SP6_9_4">§6.9.4</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP44_1"></a><b>§44.1. </b>When what's attached is a heading node, that changes the stack, of course:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Adjust attachment point for a heading</span> <span class="cwebmacronumber">44.1</span>> =
|
|
</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"> > </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">-></span><span class="element">attachment_sp</span><span class="plain">-1; </span><span class="identifier">i</span><span class="plain">>=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">-></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">) &&</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">) >= </span><span class="identifier">heading_level</span><span class="plain">))</span>
|
|
<span class="identifier">T</span><span class="plain">-></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">§44</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP45"></a><b>§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">"<null-meaning-list>\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">"<null-parse-node>"</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">-></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">-></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">§49</a>, 1/sm (<a href="1-sm.html#SP3_5">§3.5</a>).</p>
|
|
|
|
<p class="endnote">The function ParseTree::log_subtree is used in 1/sm (<a href="1-sm.html#SP3_5">§3.5</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP46"></a><b>§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">-></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">-></span><span class="element">log_time</span><span class="plain"> = </span><span class="identifier">ltime</span><span class="plain">;</span>
|
|
<<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>><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">"<null-parse-node>\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"> > </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">-></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">-></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">-></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">-></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">-></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">§45</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP46_1"></a><b>§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">
|
|
<<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>> =
|
|
</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">-></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">§46</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP47"></a><b>§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">"<null-parse-node>\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">-></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">-></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">-></span><span class="element">next_alternative</span><span class="plain">) && (</span><span class="identifier">a</span><span class="plain"><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">-></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"> > </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">§3.5</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP48"></a><b>§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">-></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">-></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">-></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>§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">(&</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"> = &</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">-></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">(&</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>§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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">)) && (</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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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>§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">§50</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP52"></a><b>§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">-></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">§54</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP53"></a><b>§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"> > </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">-></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">-></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">-></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">-></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">-></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">-></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">-></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"> > </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">§52</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP54"></a><b>§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">-></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">-></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"> > </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>§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>
|
|
|
|
<<span class="cwebmacro">Check rule (1) of the invariant</span> <span class="cwebmacronumber">55.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Check rule (2) of the invariant</span> <span class="cwebmacronumber">55.2</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="cwebmacro">Check rule (3) of the invariant</span> <span class="cwebmacronumber">55.3</span>><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">-></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">-></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>
|
|
|
|
<<span class="cwebmacro">Check rule (4) of the invariant</span> <span class="cwebmacronumber">55.4</span>><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">p</span><span class="plain">-></span><span class="element">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">-></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">§54</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP55_1"></a><b>§55.1. </b>Rule (1): no INVALID nodes.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Check rule (1) of the invariant</span> <span class="cwebmacronumber">55.1</span>> =
|
|
</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">-></span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">t</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Log this invariant failure</span> <span class="cwebmacronumber">55.1.1</span>>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP55">§55</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP55_2"></a><b>§55.2. </b>Rule (2): all annotations must be legal for the given node type.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Check rule (2) of the invariant</span> <span class="cwebmacronumber">55.2</span>> =
|
|
</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">-></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">-></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">-></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">-></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">-></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">-></span><span class="element">kind_of_annotation</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Log this invariant failure</span> <span class="cwebmacronumber">55.1.1</span>>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP55">§55</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP55_3"></a><b>§55.3. </b>Rule (3): can this combination of parent and child exist?
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Check rule (3) of the invariant</span> <span class="cwebmacronumber">55.3</span>> =
|
|
</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">-></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">-></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">-></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>
|
|
<<span class="cwebmacro">Log this invariant failure</span> <span class="cwebmacronumber">55.1.1</span>>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP55">§55</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP55_4"></a><b>§55.4. </b>Rule (4): The number of children has to be within the given extrema.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Check rule (4) of the invariant</span> <span class="cwebmacronumber">55.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">children_count</span><span class="plain"> < </span><span class="identifier">metadata</span><span class="plain">-></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">-></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">-></span><span class="element">min_children</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Log this invariant failure</span> <span class="cwebmacronumber">55.1.1</span>>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">children_count</span><span class="plain"> > </span><span class="identifier">metadata</span><span class="plain">-></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">-></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">-></span><span class="element">max_children</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Log this invariant failure</span> <span class="cwebmacronumber">55.1.1</span>>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP55">§55</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP55_1_1"></a><b>§55.1.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Log this invariant failure</span> <span class="cwebmacronumber">55.1.1</span>> =
|
|
</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">§55.1</a>, <a href="#SP55_2">§55.2</a>, <a href="#SP55_3">§55.3</a>, <a href="#SP55_4">§55.4</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP56"></a><b>§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"> < </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"> < </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">§54</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP57"></a><b>§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">§55.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP58"></a><b>§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"><</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">§59</a>.</p>
|
|
|
|
<p class="endnote">The function ParseTree::allow_annotation_to_category is used in <a href="#SP59">§59</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP59"></a><b>§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"> <= </span><span class="constant">0</span><span class="plain">) || (</span><span class="identifier">annot</span><span class="plain"> > </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"> >= </span><span class="constant">BASE_OF_ENUMERATED_NTS</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">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">§54</a>.</p>
|
|
|
|
<p class="endnote">The function ParseTree::annotation_allowed is used in <a href="#SP25">§25</a>, <a href="#SP55_2">§55.2</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP60"></a><b>§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">-></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">-></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">-></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">-></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">) && (</span><span class="identifier">L</span><span class="plain">-></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">-></span><span class="element">next_alternative</span><span class="plain">;</span>
|
|
<span class="identifier">L</span><span class="plain">-></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">)) &&</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">-></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">-></span><span class="element">down</span><span class="plain">-></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">-></span><span class="element">down</span><span class="plain">-></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">-></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">-></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">-></span><span class="element">down</span><span class="plain">-></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">) && (</span><span class="identifier">E</span><span class="plain">-></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">-></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">-></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">-></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>
|
|
|