mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 18:14:21 +03:00
1765 lines
190 KiB
HTML
1765 lines
190 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>7/ss</title>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
</head>
|
|
<body>
|
|
|
|
<!--Weave of '7/hdn' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../webs.html">★</a></li><li><a href="index.html">core</a></li><li><a href="index.html#7">Chapter 7: Sentences</a></li><li><b>Headings</b></li></ul><p class="purpose">To keep track of the hierarchy of headings and subheadings found in the source text.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Definitions</a></li><li><a href="#SP9">§9. Declarations</a></li><li><a href="#SP10_2">§10.2. Parsing heading qualifiers</a></li><li><a href="#SP12">§12. The heading tree</a></li><li><a href="#SP14">§14. Verifying the heading tree</a></li><li><a href="#SP15">§15. Miscellaneous heading services</a></li><li><a href="#SP19">§19. Headings with extension dependencies</a></li><li><a href="#SP22">§22. World objects under each heading</a></li><li><a href="#SP24">§24. The noun search list</a></li><li><a href="#SP30">§30. Handling headings during the main traverses</a></li><li><a href="#SP31">§31. Describing the heading structure, 1: to the debugging log</a></li><li><a href="#SP33">§33. Describing the heading structure, 2: to the index</a></li><li><a href="#SP34">§34. Describing the heading structure, 3: to a freestanding XML file</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="inwebparagraph"><a id="SP1"></a><b>§1. Definitions. </b></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP2"></a><b>§2. </b>To take up the narrative of how Inform runs once more, we have read the
|
|
source text in from the primary source file and from the extensions it
|
|
requested: nothing more will be supplied from disc, and the whole combined
|
|
text is arranged as a string of sentence nodes, each direct children of the
|
|
root. In this section, we are concerned with HEADING nodes.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Most of these occur when the user has explicitly typed a heading such as:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Part VII - The Ghost of the Aragon</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">The sentence-breaker called <code class="display"><span class="extract">Sentences::Headings::declare</span></code> each time it found one of
|
|
these, but also when a new source file started, because a file boundary is
|
|
construed as beginning with a hidden "heading" of a higher rank than any
|
|
other, and the sentence-breaker made a corresponding HEADING node there
|
|
too. This is important because the doctrine is that each heading starts
|
|
afresh with a new hierarchy of lower-order headings: thus changing the Part
|
|
means we can start again with Chapter 1 if we like, and so on. Because each
|
|
source file starts with an implicit super-heading, each source file gets
|
|
its own independent hierarchy of Volume, and so on. But the convention is
|
|
also important because we need to be able to say that every word loaded
|
|
from disc ultimately falls under some heading, even if the source text as
|
|
typed by the designer does not obviously have any headings in it.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The hierarchy thus runs: File (0), Volume (1), Book (2), Part (3),
|
|
Chapter (4), Section (5). (The implementation below allows for even lower
|
|
levels of subheading, from 6 to 9, but Inform doesn't use them.) Every run
|
|
of Inform declares at least two File (0) headings, representing the start of
|
|
main text and the start of the Standard Rules, and these latter have a
|
|
couple of dozen headings themselves, so the typical number of headings
|
|
in a source text is 30 to 100.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">NO_HEADING_LEVELS</span><span class="plain"> 10</span>
|
|
</pre>
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. </b>Although it is implicit in the parse tree already, the heading structure
|
|
is not easy to deduce, and so in this section we build a much smaller tree
|
|
consisting just of the hierarchy of headings. The heading tree has nodes
|
|
made from the following structures:
|
|
</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">heading</span><span class="plain"> {</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">sentence_declaring</span><span class="plain">; </span> <span class="comment">if any: file starts are undeclared</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">source_location</span><span class="plain"> </span><span class="identifier">start_location</span><span class="plain">; </span> <span class="comment">first word under this heading is here</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">level</span><span class="plain">; </span> <span class="comment">0 for Volume (highest) to 5 for Section (lowest)</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">indentation</span><span class="plain">; </span> <span class="comment">in a hierarchical listing</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">index_definitions_made_under_this</span><span class="plain">; </span> <span class="comment">for instance, global variables made here?</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">for_release</span><span class="plain">; </span> <span class="comment">include this material in a release version?</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">omit_material</span><span class="plain">; </span> <span class="comment">if set, simply ignore all of this</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">use_with_or_without</span><span class="plain">; </span> <span class="comment">if TRUE, use with the extension; if FALSE, without</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">extension_identifier</span><span class="plain"> </span><span class="identifier">for_use_with</span><span class="plain">; </span> <span class="comment">e.g. "for use with ... by ..."</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">in_place_of_text</span><span class="plain">; </span> <span class="comment">e.g. "in place of ... in ... by ..."</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">heading_text</span><span class="plain">; </span> <span class="comment">once provisos have been stripped away</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">list_of_contents</span><span class="plain">; </span> <span class="comment">tagged names defined under this</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">last_in_list_of_contents</span><span class="plain">;</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">parent_heading</span><span class="plain">;</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">child_heading</span><span class="plain">;</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">next_heading</span><span class="plain">;</span>
|
|
<span class="identifier">MEMORY_MANAGEMENT</span>
|
|
<span class="plain">} </span><span class="reserved">heading</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure heading is accessed in 27/cm and here.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. </b>The headings and subheadings are formed into a tree in which each heading
|
|
contains its lesser-order headings. The pseudo-heading exists to be the root
|
|
of this tree; the entire text falls under it. It is not a real heading at all,
|
|
and has no "level" or "indentation" as such.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">heading</span><span class="plain"> </span><span class="identifier">pseudo_heading</span><span class="plain">; </span> <span class="comment">The entire source falls under this top-level heading</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. </b>As an example, a sequence in the primary source text of (Chapter I, Book
|
|
Two, Section 5, Chapter I, Section 1, Chapter III) would be formed up into
|
|
the heading tree:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">(the pseudo-heading) level -1, indentation -1</span>
|
|
<span class="plain"> (File: Standard Rules) level 0, indentation 0</span>
|
|
<span class="plain"> ...</span>
|
|
<span class="plain"> (File: primary source text) level 0, indentation 0</span>
|
|
<span class="plain"> Chapter I level 4, indentation 1</span>
|
|
<span class="plain"> Book Two level 2, indentation 1</span>
|
|
<span class="plain"> Section 5 level 5, indentation 2</span>
|
|
<span class="plain"> Chapter I level 4, indentation 2</span>
|
|
<span class="plain"> Section 1 level 5, indentation 3</span>
|
|
<span class="plain"> Chapter III level 4, indentation 2</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">Note that the level of a heading is not the same thing as its depth in this
|
|
tree, which we call the "indentation", and there is no simple relationship
|
|
between the two numbers. Clearly we want to start at the left margin. If a
|
|
new heading is subordinate to its predecessor (i.e., has higher level),
|
|
we want to indent further, but by the least amount needed — a single tap step.
|
|
Adjacent equal-level headings are on a par with each other and should have
|
|
the same indentation. But when the new heading is lower level than its
|
|
predecessor (i.e., more important) then the indentation decreases to
|
|
match the last one equally important.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We can secure the last of those properties with a formal definition as
|
|
follows. The level l_n of a heading depends only on its wording (or
|
|
source file origin), but the indentation of the nth heading, i_n,
|
|
depends on (l_1, l_2, ..., l_n), the sequence of all levels so
|
|
far:
|
|
i_n = i_m + 1 where m = max { j | 0<= j < n, l_j < l_n }
|
|
where l_0 = i_0 = -1, so that this set always contains 0 and is
|
|
therefore not empty. We deduce that
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(a) i_1 = 0 and thereafter i_n >= 0, since l_n is never negative again,
|
|
</li></ul>
|
|
<ul class="items"><li>(b) if l_k = l_{k+1} then i_k = i_{k+1}, since the set over which
|
|
the maximum is taken is the same,
|
|
</li></ul>
|
|
<ul class="items"><li>(c) if l_{k+1} > l_k, a subheading of its predecessor, then
|
|
i_{k+1} = i_k + 1, a single tab step outward.
|
|
</li></ul>
|
|
<p class="inwebparagraph">That establishes the other properties we wanted, and shows that i_n is
|
|
indeed the number of tab steps we should be determining.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Note that to calculate i_n we do not need the whole of (l_1, ..., l_n):
|
|
we only need to remember the values of
|
|
i_{m(K)}, where m(K) = max { j | 0<= j < n, l_j < K }
|
|
for each possible heading level K=0, 1, ..., 9. This requires much less
|
|
storage: we call it the "last indentation above level K".
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This leads to the following algorithm when looking at the headings in any
|
|
individual file of source text: at the top of file,
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">for (i=0; i<NO_HEADING_LEVELS; i++) last_indentation_above_level[i] = -1;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">Then parse for headings (they have an easily recognised lexical form); each
|
|
time one is found, work out its <code class="display"><span class="extract">level</span></code> as 1, ..., 5 for Volume down to Section,
|
|
and call:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">int find_indentation(int level) {</span>
|
|
<span class="plain"> int i, ind = last_indentation_above_level[level] + 1;</span>
|
|
<span class="plain"> for (i=level+1; i<NO_HEADING_LEVELS; i++)</span>
|
|
<span class="plain"> last_indentation_above_level[i] = ind;</span>
|
|
<span class="plain"> return ind;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">While this algorithm is trivially equivalent to finding the depth of a
|
|
heading in the tree which we are going to build anyway, it is worth noting
|
|
here for the benefit of anyone writing a tool to (let's say) typeset an
|
|
Inform source text with a table of contents, or provide a navigation
|
|
gadget in the user interface.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. </b>The primary source text, and indeed the source text in the extensions,
|
|
can make whatever headings they like: no sequence is illegal. It is not
|
|
for Inform to decide on behalf of the author that it is eccentric to place
|
|
Section C before Section B, for instance. The author might be doing so
|
|
deliberately, to put the Chariot-race before the Baths, say; and the
|
|
indexing means that it will be very apparent to the author what the heading
|
|
structure currently is, so mistakes are unlikely to last long. This is a
|
|
classic case where Inform trying to be too clever would annoy more often
|
|
than assist.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. </b></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">name_resolution_data</span><span class="plain"> {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">heading_count</span><span class="plain">; </span> <span class="comment">used when tallying up objects under their headings</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">next_under_heading</span><span class="plain">; </span> <span class="comment">next in the list under that</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">search_score</span><span class="plain">; </span> <span class="comment">used when searching nametags to parse names</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">next_to_search</span><span class="plain">; </span> <span class="comment">similarly</span>
|
|
<span class="plain">} </span><span class="reserved">name_resolution_data</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure name_resolution_data is private to this section.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP8"></a><b>§8. </b></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">contents_entry</span><span class="plain"> {</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">heading_entered</span><span class="plain">;</span>
|
|
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">contents_entry</span><span class="plain"> *</span><span class="identifier">next</span><span class="plain">;</span>
|
|
<span class="identifier">MEMORY_MANAGEMENT</span>
|
|
<span class="plain">} </span><span class="reserved">contents_entry</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The structure contents_entry is accessed in 3/pd, 5/lp, 5/ut, 5/un, 5/ins, 6/rlt, 6/nv, 7/ss, 7/ns, 7/oaf, 7/rs, 8/ie, 8/ec, 8/ed, 9/tfa, 9/tbath, 9/rpt, 9/tc, 9/ma, 9/rk, 9/ass, 9/imp, 9/pd, 10/teav, 10/cap, 11/ap, 11/pr, 11/bas, 11/tc, 11/sm, 12/dtd, 12/cdp, 14/rv, 14/lv, 14/cn, 14/ds, 14/ds2, 15/cp, 16/is, 16/in, 19/tb, 19/rsft, 19/tod, 20/eq, 21/rl, 21/rl2, 21/fao, 21/rps, 21/sv, 21/ac, 22/ph, 22/tp, 22/tp2, 23/ad, 24/lv, 24/sf, 25/in, 25/pi, 25/cii, 25/cp, 26/uo, 26/tti, 26/pc, 26/ts, 27/cm and here.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP9"></a><b>§9. Declarations. </b>The heading tree is constructed all at once, after most of the sentence-breaking
|
|
is done, but since a few sentences can in principle be added later, we watch
|
|
for the remote chance of further headings being added, by keeping the following
|
|
flag:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">heading_tree_made_at_least_once</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10"></a><b>§10. </b>Now, then, the routine <code class="display"><span class="extract">Sentences::Headings::declare</span></code> is called by the sentence-breaker
|
|
each time it constructs a new HEADING node. (Note that it is not called to
|
|
create the pseudo-heading, which does not come from a node.)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">A level 0 heading has text (the first sentence which happens to be in the
|
|
new source file), but this has no significance other than its location,
|
|
and cannot contain information about releasing or about virtual machines.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">last_indentation_above_level</span><span class="plain">[</span><span class="constant">NO_HEADING_LEVELS</span><span class="plain">], </span><span class="identifier">lial_made</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">grammar_eid</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="functiontext">Sentences::Headings::declare</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">PN</span><span class="plain">) {</span>
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">heading</span><span class="plain">);</span>
|
|
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>parent_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>child_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>list_of_contents</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>last_in_list_of_contents</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>for_release</span><span class="plain"> = </span><span class="identifier">NOT_APPLICABLE</span><span class="plain">; </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>omit_material</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>index_definitions_made_under_this</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>use_with_or_without</span><span class="plain"> = </span><span class="identifier">NOT_APPLICABLE</span><span class="plain">;</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>in_place_of_text</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</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">Wordings::empty</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">))))</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"heading at textless node"</span><span class="plain">);</span>
|
|
<span class="identifier">internal_error_if_node_type_wrong</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">, </span><span class="identifier">HEADING_NT</span><span class="plain">);</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain"> = </span><span class="identifier">PN</span><span class="plain">;</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain"> = </span><span class="identifier">Wordings::location</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">));</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> = </span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">, </span><span class="identifier">heading_level_ANNOT</span><span class="plain">);</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>heading_text</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> > 0) </span><<span class="cwebmacro">Parse heading text for release or other stipulations</span> <span class="cwebmacronumber">10.2</span>><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> < 0) || (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> >= </span><span class="constant">NO_HEADING_LEVELS</span><span class="plain">)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"impossible level"</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Determine the indentation from the level</span> <span class="cwebmacronumber">10.1</span>><span class="plain">;</span>
|
|
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">HEADINGS</span><span class="plain">, </span><span class="string">"Created heading $H\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">heading_tree_made_at_least_once</span><span class="plain">) </span><span class="functiontext">Sentences::Headings::make_tree</span><span class="plain">();</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::declare is used in 7/ss (<a href="7-ss.html#SP3">§3</a>, <a href="7-ss.html#SP8">§8</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_1"></a><b>§10.1. </b>This implements the indentation algorithm described above.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Determine the indentation from the level</span> <span class="cwebmacronumber">10.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lial_made</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="constant">NO_HEADING_LEVELS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">last_indentation_above_level</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = -1;</span>
|
|
<span class="identifier">lial_made</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>indentation</span><span class="plain"> = </span><span class="identifier">last_indentation_above_level</span><span class="plain">[</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain">] + 1;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain">+1; </span><span class="identifier">i</span><span class="plain"><</span><span class="constant">NO_HEADING_LEVELS</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="identifier">last_indentation_above_level</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>indentation</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP10">§10</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP10_2"></a><b>§10.2. Parsing heading qualifiers. </b></p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="constant">PLATFORM_UNMET_HQ</span><span class="plain"> 0</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">PLATFORM_MET_HQ</span><span class="plain"> 1</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">NOT_FOR_RELEASE_HQ</span><span class="plain"> 2</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">FOR_RELEASE_ONLY_HQ</span><span class="plain"> 3</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">UNINDEXED_HQ</span><span class="plain"> 4</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">USE_WITH_HQ</span><span class="plain"> 5</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">USE_WITHOUT_HQ</span><span class="plain"> 6</span>
|
|
<span class="definitionkeyword">define</span> <span class="constant">IN_PLACE_OF_HQ</span><span class="plain"> 7</span>
|
|
</pre>
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Parse heading text for release or other stipulations</span> <span class="cwebmacronumber">10.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">grammar_eid</span><span class="plain"> = &(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>for_use_with</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="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">PN</span><span class="plain">);</span>
|
|
<span class="reserved">while</span><span class="plain"> (<</span><span class="reserved">heading</span><span class="plain">-</span><span class="identifier">qualifier</span><span class="plain">>(</span><span class="identifier">W</span><span class="plain">)) {</span>
|
|
<span class="reserved">switch</span><span class="plain"> (<<</span><span class="identifier">r</span><span class="plain">>>) {</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">PLATFORM_UNMET_HQ</span><span class="plain">: </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>omit_material</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">NOT_FOR_RELEASE_HQ</span><span class="plain">: </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>for_release</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">FOR_RELEASE_ONLY_HQ</span><span class="plain">: </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>for_release</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">UNINDEXED_HQ</span><span class="plain">: </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>index_definitions_made_under_this</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">USE_WITH_HQ</span><span class="plain">: </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>use_with_or_without</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">USE_WITHOUT_HQ</span><span class="plain">: </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>use_with_or_without</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">IN_PLACE_OF_HQ</span><span class="plain">:</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>use_with_or_without</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>in_place_of_text</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(<</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">qualifier</span><span class="plain">>, 1);</span>
|
|
<span class="functiontext">CoreMain::disable_importation</span><span class="plain">();</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">W</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(<</span><span class="reserved">heading</span><span class="plain">-</span><span class="identifier">qualifier</span><span class="plain">>, 1);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>heading_text</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP10">§10</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11"></a><b>§11. </b>When a heading has been found, we repeatedly try to match it against
|
|
<heading-qualifier> to see if it ends with text telling us what to do with
|
|
the source text it governs. For example,
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Section 21 - Frogs (unindexed) (not for Glulx)</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">would match twice, first registering the VM requirement, then the unindexedness.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">It's an unfortunate historical quirk that the unbracketed qualifiers are
|
|
allowed; they should probably be withdrawn.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain"><</span><span class="reserved">heading</span><span class="plain">-</span><span class="identifier">qualifier</span><span class="plain">> ::=</span>
|
|
<span class="plain">... ( <</span><span class="identifier">bracketed</span><span class="plain">-</span><span class="reserved">heading</span><span class="plain">-</span><span class="identifier">qualifier</span><span class="plain">> ) | ==> </span><span class="identifier">R</span><span class="plain">[1]</span>
|
|
<span class="plain">... </span><span class="identifier">not</span><span class="plain"> </span><span class="reserved">for</span><span class="plain"> </span><span class="identifier">release</span><span class="plain"> | ==> </span><span class="constant">NOT_FOR_RELEASE_HQ</span>
|
|
<span class="plain">... </span><span class="reserved">for</span><span class="plain"> </span><span class="identifier">release</span><span class="plain"> </span><span class="identifier">only</span><span class="plain"> | ==> </span><span class="constant">FOR_RELEASE_ONLY_HQ</span>
|
|
<span class="plain">... </span><span class="identifier">unindexed</span><span class="plain"> ==> </span><span class="constant">UNINDEXED_HQ</span>
|
|
|
|
<span class="plain"><</span><span class="identifier">bracketed</span><span class="plain">-</span><span class="reserved">heading</span><span class="plain">-</span><span class="identifier">qualifier</span><span class="plain">> ::=</span>
|
|
<span class="identifier">not</span><span class="plain"> </span><span class="reserved">for</span><span class="plain"> </span><span class="identifier">release</span><span class="plain"> | ==> </span><span class="constant">NOT_FOR_RELEASE_HQ</span>
|
|
<span class="reserved">for</span><span class="plain"> </span><span class="identifier">release</span><span class="plain"> </span><span class="identifier">only</span><span class="plain"> | ==> </span><span class="constant">FOR_RELEASE_ONLY_HQ</span>
|
|
<span class="identifier">unindexed</span><span class="plain"> | ==> </span><span class="constant">UNINDEXED_HQ</span>
|
|
<span class="plain"><</span><span class="identifier">platform</span><span class="plain">-</span><span class="identifier">qualifier</span><span class="plain">> | ==> </span><span class="identifier">R</span><span class="plain">[1]</span>
|
|
<span class="plain"><</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">qualifier</span><span class="plain">> ==> </span><span class="identifier">R</span><span class="plain">[1]</span>
|
|
|
|
<span class="plain"><</span><span class="identifier">platform</span><span class="plain">-</span><span class="identifier">qualifier</span><span class="plain">> ::=</span>
|
|
<span class="reserved">for</span><span class="plain"> <</span><span class="identifier">platform</span><span class="plain">-</span><span class="identifier">identifier</span><span class="plain">> </span><span class="identifier">only</span><span class="plain"> | ==> (</span><span class="identifier">R</span><span class="plain">[1])?</span><span class="constant">PLATFORM_MET_HQ</span><span class="plain">:</span><span class="constant">PLATFORM_UNMET_HQ</span>
|
|
<span class="identifier">not</span><span class="plain"> </span><span class="reserved">for</span><span class="plain"> <</span><span class="identifier">platform</span><span class="plain">-</span><span class="identifier">identifier</span><span class="plain">> ==> (</span><span class="identifier">R</span><span class="plain">[1])?</span><span class="constant">PLATFORM_UNMET_HQ</span><span class="plain">:</span><span class="constant">PLATFORM_MET_HQ</span>
|
|
|
|
<span class="plain"><</span><span class="identifier">platform</span><span class="plain">-</span><span class="identifier">identifier</span><span class="plain">> ::=</span>
|
|
<span class="plain"><</span><span class="identifier">language</span><span class="plain">-</span><span class="identifier">element</span><span class="plain">> </span><span class="identifier">language</span><span class="plain"> </span><span class="identifier">element</span><span class="plain"> | ==> </span><span class="identifier">R</span><span class="plain">[1]</span>
|
|
<span class="plain">...... </span><span class="identifier">language</span><span class="plain"> </span><span class="identifier">element</span><span class="plain"> | ==> </span><<span class="cwebmacro">Issue PM_UnknownLanguageElement problem</span> <span class="cwebmacronumber">11.1</span>>
|
|
<span class="plain"><</span><span class="identifier">virtual</span><span class="plain">-</span><span class="identifier">machine</span><span class="plain">> | ==> </span><span class="identifier">R</span><span class="plain">[1]</span>
|
|
<span class="plain">...... ==> </span><<span class="cwebmacro">Issue PM_UnknownVirtualMachine problem</span> <span class="cwebmacronumber">11.2</span>>
|
|
|
|
<span class="plain"><</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">qualifier</span><span class="plain">> ::=</span>
|
|
<span class="reserved">for</span><span class="plain"> </span><span class="identifier">use</span><span class="plain"> </span><span class="identifier">with</span><span class="plain"> <</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">identifier</span><span class="plain">> | ==> </span><span class="constant">USE_WITH_HQ</span>
|
|
<span class="reserved">for</span><span class="plain"> </span><span class="identifier">use</span><span class="plain"> </span><span class="identifier">without</span><span class="plain"> <</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">identifier</span><span class="plain">> | ==> </span><span class="constant">USE_WITHOUT_HQ</span>
|
|
<span class="identifier">not</span><span class="plain"> </span><span class="reserved">for</span><span class="plain"> </span><span class="identifier">use</span><span class="plain"> </span><span class="identifier">with</span><span class="plain"> <</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">identifier</span><span class="plain">> | ==> </span><span class="constant">USE_WITHOUT_HQ</span>
|
|
<span class="identifier">in</span><span class="plain"> </span><span class="identifier">place</span><span class="plain"> </span><span class="identifier">of</span><span class="plain"> (<</span><span class="identifier">quoted</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">>) </span><span class="identifier">in</span><span class="plain"> <</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">identifier</span><span class="plain">> | ==> </span><span class="constant">IN_PLACE_OF_HQ</span>
|
|
<span class="identifier">in</span><span class="plain"> </span><span class="identifier">place</span><span class="plain"> </span><span class="identifier">of</span><span class="plain"> ...... </span><span class="identifier">in</span><span class="plain"> <</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">identifier</span><span class="plain">> ==> </span><span class="constant">IN_PLACE_OF_HQ</span>
|
|
|
|
<span class="plain"><</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">identifier</span><span class="plain">> ::=</span>
|
|
<span class="plain">...... </span><span class="identifier">by</span><span class="plain"> ...... ==> </span><<span class="cwebmacro">Set for-use-with extension identifier</span> <span class="cwebmacronumber">11.3</span>>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_1"></a><b>§11.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_UnknownLanguageElement problem</span> <span class="cwebmacronumber">11.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_UnknownLanguageElement</span><span class="plain">),</span>
|
|
<span class="string">"this heading contains a stipulation about the current "</span>
|
|
<span class="string">"Inform language definition which I can't understand"</span><span class="plain">,</span>
|
|
<span class="string">"and should be something like '(for Glulx external files "</span>
|
|
<span class="string">"language element only)'."</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP11">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_2"></a><b>§11.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue PM_UnknownVirtualMachine problem</span> <span class="cwebmacronumber">11.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_UnknownVirtualMachine</span><span class="plain">),</span>
|
|
<span class="string">"this heading contains a stipulation about the Setting "</span>
|
|
<span class="string">"for story file format which I can't understand"</span><span class="plain">,</span>
|
|
<span class="string">"and should be something like '(for Z-machine version 5 "</span>
|
|
<span class="string">"or 8 only)' or '(for Glulx only)'."</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP11">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP11_3"></a><b>§11.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Set for-use-with extension identifier</span> <span class="cwebmacronumber">11.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="plain">*</span><span class="identifier">X</span><span class="plain"> = </span><span class="identifier">R</span><span class="plain">[0] + 4;</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">exft</span><span class="plain">);</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">exfa</span><span class="plain">);</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">TW</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(<</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">identifier</span><span class="plain">>, 1);</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">AW</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(<</span><span class="identifier">extension</span><span class="plain">-</span><span class="identifier">identifier</span><span class="plain">>, 2);</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">exft</span><span class="plain">, </span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">TW</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">exfa</span><span class="plain">, </span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">AW</span><span class="plain">);</span>
|
|
<span class="functiontext">Extensions::IDs::new</span><span class="plain">(</span><span class="identifier">grammar_eid</span><span class="plain">, </span><span class="identifier">exfa</span><span class="plain">, </span><span class="identifier">exft</span><span class="plain">, </span><span class="constant">USEWITH_EIDBC</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">exft</span><span class="plain">);</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">exfa</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP11">§11</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12"></a><b>§12. The heading tree. </b>The headings were constructed above as freestanding nodes (except that the
|
|
pseudo-heading already existed): here, we assemble them into a tree
|
|
structure. Because we want to be able to call this more than once, perhaps
|
|
to make revisions if late news comes in of a new heading (see above), we
|
|
begin by removing any existing relationships between the heading nodes.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::make_tree</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Reduce the whole heading tree to a pile of twigs</span> <span class="cwebmacronumber">12.1</span>><span class="plain">;</span>
|
|
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="reserved">heading</span><span class="plain">) {</span>
|
|
<<span class="cwebmacro">If h is outside the tree, make it a child of the pseudo-heading</span> <span class="cwebmacronumber">12.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Run through subsequent equal or subordinate headings to move them downward</span> <span class="cwebmacronumber">12.3</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">heading_tree_made_at_least_once</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="functiontext">Sentences::Headings::verify_heading_tree</span><span class="plain">();</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::make_tree is used in <a href="#SP10">§10</a>, <a href="#SP27_3">§27.3</a>, 1/mr (<a href="1-mr.html#SP4_9">§4.9</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12_1"></a><b>§12.1. </b>Note that the loop over headings below loops through all those which were
|
|
created by the memory manager: which is to say, all of them except for the
|
|
pseudo-heading, which was explicitly placed in static memory above.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Reduce the whole heading tree to a pile of twigs</span> <span class="cwebmacronumber">12.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="identifier">pseudo_heading</span><span class="element">.child_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">pseudo_heading</span><span class="element">.parent_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">pseudo_heading</span><span class="element">.next_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="reserved">heading</span><span class="plain">) {</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>parent_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>child_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>next_heading</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">This code is used in <a href="#SP12">§12</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12_2"></a><b>§12.2. </b>The idea of the heading loop is that when we place a heading, we also place
|
|
subsequent headings of lesser or equal status until we cannot do so any longer.
|
|
That means that if we reach h and find that it has no parent, it must be
|
|
subordinate to no earlier heading: thus, it must be attached to the pseudo-heading
|
|
at the top of the tree.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">If h is outside the tree, make it a child of the pseudo-heading</span> <span class="cwebmacronumber">12.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>parent_heading</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
|
|
<span class="functiontext">Sentences::Headings::make_child_heading</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, &</span><span class="identifier">pseudo_heading</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP12">§12</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP12_3"></a><b>§12.3. </b>Note that the following could be summed up as "move subsequent headings as
|
|
deep in the tree as we can see they need to be from h's perspective alone".
|
|
This isn't always the final position. For instance, given the sequence
|
|
Volume 1, Chapter I, Section A, Chapter II, the tree is adjusted twice:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">when h = Volume 1: then when h = Chapter I:</span>
|
|
<span class="plain">Volume 1 Volume 1</span>
|
|
<span class="plain"> Chapter I Chapter I</span>
|
|
<span class="plain"> Section A Section A</span>
|
|
<span class="plain"> Chapter II Chapter II</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">since Section A is demoted twice, once by Volume 1, then by Chapter I.
|
|
(This algorithm would in principle be quadratic in the number of headings if
|
|
the possible depth of the tree were unbounded — every heading might have to
|
|
demote every one of its successors — but in fact because the depth is at
|
|
most 9, it runs in linear time.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Run through subsequent equal or subordinate headings to move them downward</span> <span class="cwebmacronumber">12.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">subseq</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">subseq</span><span class="plain"> = </span><span class="identifier">NEXT_OBJECT</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="reserved">heading</span><span class="plain">); </span> <span class="comment">start from the next heading in source</span>
|
|
<span class="plain">(</span><span class="identifier">subseq</span><span class="plain">) && (</span><span class="identifier">subseq</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> >= </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain">); </span> <span class="comment">for a run with level below or equal h</span>
|
|
<span class="identifier">subseq</span><span class="plain"> = </span><span class="identifier">NEXT_OBJECT</span><span class="plain">(</span><span class="identifier">subseq</span><span class="plain">, </span><span class="reserved">heading</span><span class="plain">)) { </span> <span class="comment">in source declaration order</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">subseq</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> == </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain">) { </span> <span class="comment">a heading of equal status ends the run...</span>
|
|
<span class="functiontext">Sentences::Headings::make_child_heading</span><span class="plain">(</span><span class="identifier">subseq</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>parent_heading</span><span class="plain">); </span><span class="reserved">break</span><span class="plain">; </span> <span class="comment">...and becomes h's sibling</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">Sentences::Headings::make_child_heading</span><span class="plain">(</span><span class="identifier">subseq</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">); </span> <span class="comment">all lesser headings in the run become h's children</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP12">§12</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13"></a><b>§13. </b>The above routine, then, calls <code class="display"><span class="extract">Sentences::Headings::make_child_heading</span></code> to attach a heading
|
|
to the tree as a child of a given parent:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::make_child_heading</span><span class="plain">(</span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">ch</span><span class="plain">, </span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">pa</span><span class="plain">) {</span>
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">former_pa</span><span class="plain"> = </span><span class="identifier">ch</span><span class="plain">-</span><span class="element">>parent_heading</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">former_pa</span><span class="plain"> == </span><span class="identifier">pa</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Detach ch from the heading tree if it is already there</span> <span class="cwebmacronumber">13.1</span>><span class="plain">;</span>
|
|
<span class="identifier">ch</span><span class="plain">-</span><span class="element">>parent_heading</span><span class="plain"> = </span><span class="identifier">pa</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Add ch to the end of the list of children of pa</span> <span class="cwebmacronumber">13.2</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::make_child_heading is used in <a href="#SP12_2">§12.2</a>, <a href="#SP12_3">§12.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13_1"></a><b>§13.1. </b>If ch is present in the tree, it must have a parent, unless it is the
|
|
pseudo-heading: but the latter can never be moved, so it isn't. Therefore
|
|
we can remove ch by striking it out from the children list of the parent.
|
|
(Any children which ch has, grandchildren so to speak, come with it.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Detach ch from the heading tree if it is already there</span> <span class="cwebmacronumber">13.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">former_pa</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">former_pa</span><span class="plain">-</span><span class="element">>child_heading</span><span class="plain"> == </span><span class="identifier">ch</span><span class="plain">)</span>
|
|
<span class="identifier">former_pa</span><span class="plain">-</span><span class="element">>child_heading</span><span class="plain"> = </span><span class="identifier">ch</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain">;</span>
|
|
<span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">sibling</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">sibling</span><span class="plain"> = </span><span class="identifier">former_pa</span><span class="plain">-</span><span class="element">>child_heading</span><span class="plain">; </span><span class="identifier">sibling</span><span class="plain">; </span><span class="identifier">sibling</span><span class="plain"> = </span><span class="identifier">sibling</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sibling</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain"> == </span><span class="identifier">ch</span><span class="plain">) {</span>
|
|
<span class="identifier">sibling</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain"> = </span><span class="identifier">ch</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain">;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">ch</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP13">§13</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP13_2"></a><b>§13.2. </b>Two cases: the new parent is initially childless, or it isn't.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Add ch to the end of the list of children of pa</span> <span class="cwebmacronumber">13.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">sibling</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pa</span><span class="plain">-</span><span class="element">>child_heading</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">pa</span><span class="plain">-</span><span class="element">>child_heading</span><span class="plain"> = </span><span class="identifier">ch</span><span class="plain">;</span>
|
|
<span class="reserved">else</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">sibling</span><span class="plain"> = </span><span class="identifier">pa</span><span class="plain">-</span><span class="element">>child_heading</span><span class="plain">; </span><span class="identifier">sibling</span><span class="plain">; </span><span class="identifier">sibling</span><span class="plain"> = </span><span class="identifier">sibling</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sibling</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="identifier">sibling</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain"> = </span><span class="identifier">ch</span><span class="plain">;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP13">§13</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP14"></a><b>§14. Verifying the heading tree. </b>We have now, in effect, computed the indentation value of each heading twice,
|
|
by two entirely different methods: first by the mathematical argument above,
|
|
then by observing that it is the depth in the heading tree. Seeing if
|
|
these two methods have given the same answer provides a convenient check on
|
|
our working.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">heading_tree_damaged</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">Sentences::Headings::verify_heading_tree</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="functiontext">Sentences::Headings::verify_heading_tree_recursively</span><span class="plain">(&</span><span class="identifier">pseudo_heading</span><span class="plain">, -1);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">heading_tree_damaged</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"heading tree failed to verify"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::verify_heading_tree_recursively</span><span class="plain">(</span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</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">if</span><span class="plain"> (</span><span class="identifier">h</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="reserved">if</span><span class="plain"> ((</span><span class="identifier">h</span><span class="plain"> != &</span><span class="identifier">pseudo_heading</span><span class="plain">) && (</span><span class="identifier">depth</span><span class="plain"> != </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>indentation</span><span class="plain">)) {</span>
|
|
<span class="identifier">heading_tree_damaged</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$H\</span><span class="plain">n</span><span class="string">*** indentation should be %d ***\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">Sentences::Headings::verify_heading_tree_recursively</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>child_heading</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">+1);</span>
|
|
<span class="functiontext">Sentences::Headings::verify_heading_tree_recursively</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::verify_heading_tree is used in <a href="#SP12">§12</a>.</p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::verify_heading_tree_recursively appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP15"></a><b>§15. Miscellaneous heading services. </b>The first of these we have already seen in use: the sentence-breaker calls
|
|
it to ask whether sentences falling under the current heading should be
|
|
included in the active source text. (For instance, sentences under a
|
|
heading with the disclaimer "(for Glulx only)" will not be included
|
|
if the target virtual machine on this run of Inform is the Z-machine.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::include_material</span><span class="plain">(</span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>for_release</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">) && (</span><span class="identifier">this_is_a_release_compile</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">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>for_release</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) && (</span><span class="identifier">this_is_a_release_compile</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="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>omit_material</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">Sentences::Headings::indexed</span><span class="plain">(</span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</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">TRUE</span><span class="plain">; </span> <span class="comment">definitions made nowhere are normally indexed</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>index_definitions_made_under_this</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::include_material is used in 7/ss (<a href="7-ss.html#SP3">§3</a>).</p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::indexed is used in 5/nv (<a href="5-nv.html#SP27_2">§27.2</a>), 8/ed2 (<a href="8-ed2.html#SP3_2_1_7_3">§3.2.1.7.3</a>), 22/pi (<a href="22-pi.html#SP1">§1</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP16"></a><b>§16. </b>A utility to do with the file of origin:
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">extension_file</span><span class="plain"> *</span><span class="functiontext">Sentences::Headings::get_extension_containing</span><span class="plain">(</span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">h</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</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">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">SourceFiles::get_extension_corresponding</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::get_extension_containing is used in <a href="#SP20">§20</a>, 19/tb (<a href="19-tb.html#SP31">§31</a>), 22/pi (<a href="22-pi.html#SP1">§1</a>), 25/cp (<a href="25-cp.html#SP3_1">§3.1</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP17"></a><b>§17. </b>Although File (0) headings do have text, contrary to the implication of
|
|
the routine here, this text is only what happens to be first in the file:
|
|
it isn't a heading actually typed by the user, which is all that we are
|
|
interested in for this purpose. So we send back a null word range.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::get_text</span><span class="plain">(</span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">h</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> == 0)) </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">h</span><span class="plain">-</span><span class="element">>heading_text</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::get_text is used in 5/nv (<a href="5-nv.html#SP27_2">§27.2</a>), 22/pi (<a href="22-pi.html#SP1_2">§1.2</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP18"></a><b>§18. </b>This routine determines the (closest) heading to which a scrap of text
|
|
belongs, and is important since the parsing of noun phrases is affected by
|
|
that choice of heading (as we shall see): to Inform, headings provide something
|
|
analogous to the scope of local variables in a conventional programming
|
|
language.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Because every file has a File (0) heading registered at line 1, the loop
|
|
in the following routine is guaranteed to return a valid heading provided
|
|
the original source location is well formed (i.e., has a non-null source
|
|
file and a line number of at least 1).
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="functiontext">Sentences::Headings::heading_of</span><span class="plain">(</span><span class="identifier">source_location</span><span class="plain"> </span><span class="identifier">sl</span><span class="plain">) {</span>
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sl</span><span class="plain">.</span><span class="identifier">file_of_origin</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">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_BACKWARDS_OVER</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="reserved">heading</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">sl</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain"> == </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">sl</span><span class="plain">.</span><span class="identifier">line_number</span><span class="plain"> >= </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain">.</span><span class="identifier">line_number</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"unable to determine the heading level of source material"</span><span class="plain">);</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="functiontext">Sentences::Headings::of_wording</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">return</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::heading_of</span><span class="plain">(</span><span class="identifier">Wordings::location</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 Sentences::Headings::heading_of is used in <a href="#SP27_1">§27.1</a>.</p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::of_wording is used in <a href="#SP22">§22</a>, 5/nv (<a href="5-nv.html#SP27_2">§27.2</a>), 8/ed2 (<a href="8-ed2.html#SP3_2_1_7_3">§3.2.1.7.3</a>), 19/tb (<a href="19-tb.html#SP31">§31</a>), 22/pi (<a href="22-pi.html#SP1">§1</a>), 25/cp (<a href="25-cp.html#SP3_1">§3.1</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP19"></a><b>§19. Headings with extension dependencies. </b>If the content under a heading depended on the VM not in use, or was marked
|
|
not for release in a release run, we were able to exclude it just by
|
|
skipping. The same cannot be done when a heading says that it should be
|
|
used only if a given extension is, or is not, being used, because when
|
|
the heading is created we don't yet know which extensions are included.
|
|
But when the following is called, we do know that.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::satisfy_dependencies</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="reserved">heading</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>use_with_or_without</span><span class="plain"> != </span><span class="identifier">NOT_APPLICABLE</span><span class="plain">)</span>
|
|
<span class="functiontext">Sentences::Headings::satisfy_individual_heading_dependency</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::satisfy_dependencies is used in 1/mr (<a href="1-mr.html#SP4_9">§4.9</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20"></a><b>§20. </b>And now the code to check an individual heading's usage. This whole
|
|
thing is carefully timed so that we can still afford to cut up and rearrange
|
|
the parse tree on quite a large scale, and that's just what we do.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::satisfy_individual_heading_dependency</span><span class="plain">(</span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> < 1) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="reserved">extension_identifier</span><span class="plain"> *</span><span class="identifier">eid</span><span class="plain"> = &(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>for_use_with</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">loaded</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::no_times_used_in_context</span><span class="plain">(</span><span class="identifier">eid</span><span class="plain">, </span><span class="constant">LOADED_EIDBC</span><span class="plain">) != 0) </span><span class="identifier">loaded</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">HEADINGS</span><span class="plain">, </span><span class="string">"SIHD on $H: loaded %d: annotation %d: %W: %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">, </span><span class="identifier">loaded</span><span class="plain">,</span>
|
|
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">,</span>
|
|
<span class="constant">suppress_heading_dependencies_ANNOT</span><span class="plain">),</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>in_place_of_text</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>use_with_or_without</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>in_place_of_text</span><span class="plain">)) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">S</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>in_place_of_text</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">,</span>
|
|
<span class="constant">suppress_heading_dependencies_ANNOT</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (<</span><span class="identifier">quoted</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">>(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>in_place_of_text</span><span class="plain">)) {</span>
|
|
<span class="identifier">Word::dequote</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">));</span>
|
|
<span class="identifier">wchar_t</span><span class="plain"> *</span><span class="identifier">text</span><span class="plain"> = </span><span class="identifier">Lexer::word_text</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">));</span>
|
|
<span class="identifier">S</span><span class="plain"> = </span><span class="identifier">Feeds::feed_text</span><span class="plain">(</span><span class="identifier">text</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h2</span><span class="plain">; </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">found</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">loaded</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span><<span class="cwebmacro">Can't replace heading in an unincluded extension</span> <span class="cwebmacronumber">20.1</span>>
|
|
<span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">h2</span><span class="plain">, </span><span class="reserved">heading</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">h2</span><span class="plain">-</span><span class="element">>heading_text</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="identifier">Wordings::match_perhaps_quoted</span><span class="plain">(</span><span class="identifier">S</span><span class="plain">, </span><span class="identifier">h2</span><span class="plain">-</span><span class="element">>heading_text</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(</span>
|
|
<span class="functiontext">Extensions::Files::get_eid</span><span class="plain">(</span>
|
|
<span class="functiontext">Sentences::Headings::get_extension_containing</span><span class="plain">(</span><span class="identifier">h2</span><span class="plain">)), </span><span class="identifier">eid</span><span class="plain">))) {</span>
|
|
<span class="identifier">found</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> != </span><span class="identifier">h2</span><span class="plain">-</span><span class="element">>level</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Can't replace heading unless level matches</span> <span class="cwebmacronumber">20.3</span>><span class="character">;</span>
|
|
<span class="functiontext">Sentences::Headings::excise_material_under</span><span class="plain">(</span><span class="identifier">h2</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
<span class="functiontext">Sentences::Headings::excise_material_under</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="identifier">h2</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">);</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">found</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span><<span class="cwebmacro">Can't find heading in the given extension</span> <span class="cwebmacronumber">20.2</span>><span class="character">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">} </span><span class="reserved">else</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>use_with_or_without</span><span class="plain"> != </span><span class="identifier">loaded</span><span class="plain">) </span><span class="functiontext">Sentences::Headings::excise_material_under</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::satisfy_individual_heading_dependency is used in <a href="#SP19">§19</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20_1"></a><b>§20.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Can't replace heading in an unincluded extension</span> <span class="cwebmacronumber">20.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">;</span>
|
|
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
|
|
<span class="functiontext">Problems::quote_extension_id</span><span class="plain">(2, &(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>for_use_with</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_HeadingInPlaceOfUnincluded</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
|
|
<span class="string">"In the sentence %1, it looks as if you intend to replace a section "</span>
|
|
<span class="string">"of source text from the extension '%2', but no extension of that "</span>
|
|
<span class="string">"name has been included - so it is not possible to replace any of its "</span>
|
|
<span class="string">"headings."</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP20">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21"></a><b>§21. </b>To excise, we simply prune the heading's contents from the parse tree,
|
|
though optionally grafting them to another node rather than discarding them
|
|
altogether.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Any heading which is excised is marked so that it won't have its own
|
|
dependencies checked. This clarifies several cases, and in particular ensures
|
|
that if Chapter X is excised then a subordinate Section Y cannot live on by
|
|
replacing something elsewhere (which would effectively delete the content
|
|
elsewhere).
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::excise_material_under</span><span class="plain">(</span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">transfer_to</span><span class="plain">) {</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">HEADINGS</span><span class="plain">, </span><span class="string">"Excision under $H\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">);</span>
|
|
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">hpn</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>sentence_declaring</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">"stipulations on a non-sentence heading"</span><span class="plain">);</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>in_place_of_text</span><span class="plain">)) {</span>
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h2</span><span class="plain"> = </span><span class="functiontext">Sentences::Headings::find_dependent_heading</span><span class="plain">(</span><span class="identifier">hpn</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">h2</span><span class="plain">) </span><<span class="cwebmacro">Can't replace heading subordinate to another replaced heading</span> <span class="cwebmacronumber">21.1</span>><span class="character">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="functiontext">Sentences::Headings::suppress_dependencies</span><span class="plain">(</span><span class="identifier">hpn</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">transfer_to</span><span class="plain">) </span><span class="identifier">ParseTree::graft</span><span class="plain">(</span><span class="identifier">hpn</span><span class="plain">-</span><span class="element">>down</span><span class="plain">, </span><span class="identifier">transfer_to</span><span class="plain">);</span>
|
|
<span class="identifier">hpn</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="plain">}</span>
|
|
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="functiontext">Sentences::Headings::find_dependent_heading</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">) == </span><span class="identifier">HEADING_NT</span><span class="plain">) {</span>
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain"> = </span><span class="identifier">ParseTree::get_embodying_heading</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">h</span><span class="plain">) && (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>in_place_of_text</span><span class="plain">))) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">pn</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="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="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain"> = </span><span class="identifier">ParseTree::get_embodying_heading</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">h</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>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::suppress_dependencies</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">) == </span><span class="identifier">HEADING_NT</span><span class="plain">)</span>
|
|
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="constant">suppress_heading_dependencies_ANNOT</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">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="element">>down</span><span class="plain">; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-</span><span class="element">>next</span><span class="plain">)</span>
|
|
<span class="functiontext">Sentences::Headings::suppress_dependencies</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::excise_material_under is used in <a href="#SP20">§20</a>.</p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::find_dependent_heading appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::suppress_dependencies appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP21_1"></a><b>§21.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Can't replace heading subordinate to another replaced heading</span> <span class="cwebmacronumber">21.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">h2</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">;</span>
|
|
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
|
|
<span class="functiontext">Problems::quote_extension_id</span><span class="plain">(2, &(</span><span class="identifier">h2</span><span class="plain">-</span><span class="element">>for_use_with</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::quote_source</span><span class="plain">(3, </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">);</span>
|
|
<span class="functiontext">Problems::quote_extension_id</span><span class="plain">(4, &(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>for_use_with</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_HeadingInPlaceOfSubordinate</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
|
|
<span class="string">"In the sentence %1, it looks as if you intend to replace a section "</span>
|
|
<span class="string">"of source text from the extension '%2', but that doesn't really make "</span>
|
|
<span class="string">"sense because this new piece of source text is part of a superior "</span>
|
|
<span class="string">"heading ('%3') which is already being replaced spliced into '%4'."</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP21">§21</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20_2"></a><b>§20.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Can't find heading in the given extension</span> <span class="cwebmacronumber">20.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">;</span>
|
|
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
|
|
<span class="functiontext">Problems::quote_extension_id</span><span class="plain">(2, &(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>for_use_with</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::quote_wording</span><span class="plain">(3, </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>in_place_of_text</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::quote_text</span><span class="plain">(4,</span>
|
|
<span class="string">"unspecified, that is, the extension didn't have a version number"</span><span class="plain">);</span>
|
|
<span class="reserved">extension_file</span><span class="plain"> *</span><span class="identifier">ef</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">, </span><span class="reserved">extension_file</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Extensions::IDs::match</span><span class="plain">(&(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>for_use_with</span><span class="plain">), </span><span class="functiontext">Extensions::Files::get_eid</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">)))</span>
|
|
<span class="identifier">Problems::quote_wording</span><span class="plain">(4,</span>
|
|
<span class="identifier">Wordings::one_word</span><span class="plain">(</span><span class="functiontext">Extensions::Files::get_version_wn</span><span class="plain">(</span><span class="identifier">ef</span><span class="plain">)));</span>
|
|
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_HeadingInPlaceOfUnknown</span><span class="plain">));</span>
|
|
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
|
|
<span class="string">"In the sentence %1, it looks as if you intend to replace a section "</span>
|
|
<span class="string">"of source text from the extension '%2', but that extension does "</span>
|
|
<span class="string">"not seem to have any heading called '%3'. (The version I loaded "</span>
|
|
<span class="string">"was %4.)"</span><span class="plain">);</span>
|
|
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP20">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP20_3"></a><b>§20.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Can't replace heading unless level matches</span> <span class="cwebmacronumber">20.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">;</span>
|
|
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_UnequalHeadingInPlaceOf</span><span class="plain">),</span>
|
|
<span class="string">"these headings are not of the same level"</span><span class="plain">,</span>
|
|
<span class="string">"so it is not possible to make the replacement. (Level here means "</span>
|
|
<span class="string">"being a Volume, Book, Part, Chapter or Section: for instance, "</span>
|
|
<span class="string">"only a Chapter heading can be used 'in place of' a Chapter.)"</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP20">§20</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP22"></a><b>§22. World objects under each heading. </b>Every heading must carry with it a linked list of the nametags created in
|
|
sentences which belong to it. So when any noun is created, the following
|
|
is called to let the current sentence's heading know that it has a new
|
|
friend.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_NOUNS_UNDER</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">nt</span><span class="plain">=</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>list_of_contents</span><span class="plain">; </span><span class="identifier">nt</span><span class="plain">; </span><span class="identifier">nt</span><span class="plain">=</span><span class="functiontext">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-</span><span class="element">>next_under_heading</span><span class="plain">)</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="reserved">name_resolution_data</span><span class="plain"> *</span><span class="functiontext">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">noun</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="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to fetch resolution data for null tag"</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="identifier">name_resolution</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_tags_attached</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::attach_noun</span><span class="plain">(</span><span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">new_tag</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">current_sentence</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="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain"> = </span><span class="functiontext">Sentences::Headings::of_wording</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">));</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</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">no_tags_attached</span><span class="plain">++;</span>
|
|
<span class="reserved">name_resolution_data</span><span class="plain"> *</span><span class="identifier">nrd</span><span class="plain"> = </span><span class="functiontext">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">new_tag</span><span class="plain">);</span>
|
|
<span class="identifier">nrd</span><span class="plain">-</span><span class="element">>next_to_search</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">h</span><span class="plain">-</span><span class="element">>last_in_list_of_contents</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>list_of_contents</span><span class="plain"> = </span><span class="identifier">new_tag</span><span class="plain">;</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>last_in_list_of_contents</span><span class="plain">)-</span><span class="element">>next_under_heading</span><span class="plain"> = </span><span class="identifier">new_tag</span><span class="plain">;</span>
|
|
<span class="identifier">nrd</span><span class="plain">-</span><span class="element">>next_under_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>last_in_list_of_contents</span><span class="plain"> = </span><span class="identifier">new_tag</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::name_resolution_data is used in <a href="#SP23">§23</a>, <a href="#SP25">§25</a>, <a href="#SP28_1">§28.1</a>, <a href="#SP29">§29</a>.</p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::attach_noun appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP23"></a><b>§23. </b>The following verification checks that every noun is listed
|
|
in the list for exactly one heading. The point of the check is not so much
|
|
to make sure the tag lists are properly formed, as the code making those
|
|
is pretty elementary: it's really a test that the source text is well-formed
|
|
with everything placed under a heading, and no sentence having fallen
|
|
through a crack.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::verify_divisions</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">; </span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">total</span><span class="plain"> = 0, </span><span class="identifier">disaster</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">noun</span><span class="plain">)</span>
|
|
<span class="functiontext">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-</span><span class="element">>heading_count</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="reserved">heading</span><span class="plain">)</span>
|
|
<span class="identifier">LOOP_OVER_NOUNS_UNDER</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">)</span>
|
|
<span class="functiontext">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-</span><span class="element">>heading_count</span><span class="plain">++, </span><span class="identifier">total</span><span class="plain">++;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">noun</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-</span><span class="element">>heading_count</span><span class="plain"> > 1) {</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$z occurs under %d headings\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">nt</span><span class="plain">, </span><span class="functiontext">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-</span><span class="element">>heading_count</span><span class="plain">);</span>
|
|
<span class="identifier">disaster</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">total</span><span class="plain"> != </span><span class="identifier">no_tags_attached</span><span class="plain">) {</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%d tags != %d attached\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">total</span><span class="plain">, </span><span class="identifier">no_tags_attached</span><span class="plain">);</span>
|
|
<span class="identifier">disaster</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">disaster</span><span class="plain">) </span><span class="identifier">internal_error_tree_unsafe</span><span class="plain">(</span><span class="string">"heading contents list failed verification"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::verify_divisions appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP24"></a><b>§24. The noun search list. </b>Identifying noun phrases is tricky. Many plausible phrases could refer in
|
|
principle to several different instances: "east", for instance, might
|
|
mean the direction or, say, "east garden". And what if the source
|
|
mentions many chairs, and now refers simply to "the chair"? This problem
|
|
is not so acute for nouns referring to abstractions, where we can simply
|
|
forbid duplicate definitions and require an exact wording when talking
|
|
about them. But for names of IF objects — which represent the solid and often
|
|
repetitive items and places of a simulated world — it cannot be ducked.
|
|
We can hardly tell an Inform author to create at most one item whose
|
|
name contains the word "jar", for instance.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">All programming languages face similar problems. In C, for instance, a local
|
|
variable named <code class="display"><span class="extract">east</span></code> will be recognised in preference to a global one of the
|
|
same name (to some extent external linking provides a third level again).
|
|
The way this is done is usually explained in terms of the "scope" of a
|
|
definition, the part of the source for which it is valid: the winner, in
|
|
cases of ambiguity, being the definition of narrowest scope which is valid
|
|
at the position in question. In our terms, a stand-alone C program has a
|
|
heading tree like so, with two semantically meaningful heading levels,
|
|
File (0) and Routine (1), and then sublevels provided by braced blocks:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">File</span>
|
|
<span class="plain"> main()</span>
|
|
<span class="plain"> routine1()</span>
|
|
<span class="plain"> interior block of a loop</span>
|
|
<span class="plain"> ...</span>
|
|
<span class="plain"> routine2()</span>
|
|
<span class="plain"> ...</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">The resolution of a name at a given position P is unambiguous: find the
|
|
heading H to which P belongs; if the name is defined there, accept that;
|
|
if not move H upwards and try again; if it is not defined even at File (0)
|
|
level, issue an error: the term is undefined.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Inform is different in two respects, one trivial, the other not. The trivial
|
|
difference is that an Inform name can be defined midway through the matter
|
|
(though as a result of the PM_ revision, ANSI C now also allows variables
|
|
to be created mid-block, in fact: and some C compilers even implement this).
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The big difference is that in Inform, names are always visible across
|
|
headings. They can be used before being defined; Section 2 of Part II is
|
|
free to mention the elephant defined in Section 7 of Part VIII, say.
|
|
English text is like this: a typical essay has one great big namespace.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We resolve this by searching backwards through recent noun creations in
|
|
the current heading, then in the current heading level above that, and so
|
|
on up to the top conceptual level of the source. Thus a "chair" in the
|
|
current chapter will always have priority over any in previous chapters,
|
|
and so on. However, kinds are always given priority over mere instances,
|
|
in order that "door" will retain its generic meaning even if, say,
|
|
"an oak door" is created.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP25"></a><b>§25. </b>This means that, under every heading, the search sequence is different.
|
|
So for the sake of efficiency we construct a linked list of world
|
|
objects in priority order the first time we search under a new heading,
|
|
then simply use that thereafter: we also keep track of the tail of this
|
|
list. Sections other than this one cannot read the list itself, and
|
|
use the following definition to iterate through it.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">define</span> <span class="identifier">LOOP_OVER_NT_SEARCH_LIST</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">nt</span><span class="plain"> = </span><span class="identifier">nt_search_start</span><span class="plain">; </span><span class="identifier">nt</span><span class="plain">; </span><span class="identifier">nt</span><span class="plain"> = </span><span class="functiontext">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-</span><span class="element">>next_to_search</span><span class="plain">)</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt_search_start</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">nt_search_finish</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP26"></a><b>§26. </b>The search sequence is, in effect, a cache storing a former computation,
|
|
and like all caches it can fall out of date if the circumstances change so
|
|
that the same computation would now produce a different outcome. That can
|
|
only happen here if a new noun is to be created: the assertion-maker
|
|
calls the following routine to let us know.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">noun_search_list_valid_for_this_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">initially it's unbuilt</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::disturb</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">noun_search_list_valid_for_this_heading</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::disturb appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP27"></a><b>§27. </b>Leaving aside the cache, then, we build a list as initially empty, then
|
|
all nametags of priority 1 as found by recursively searching headings, then all
|
|
nametags of priority 2, and so on.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::construct_noun_search_list</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
|
|
<<span class="cwebmacro">Work out the heading from which we wish to search</span> <span class="cwebmacronumber">27.1</span>><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">h</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">h</span><span class="plain"> == </span><span class="identifier">noun_search_list_valid_for_this_heading</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain">; </span> <span class="comment">rely on the cache</span>
|
|
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">HEADINGS</span><span class="plain">, </span><span class="string">"Rebuilding noun search list from: $H\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">);</span>
|
|
|
|
<<span class="cwebmacro">Start the search list empty</span> <span class="cwebmacronumber">27.2</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="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=1; </span><span class="identifier">i</span><span class="plain"><=</span><span class="identifier">MAX_NOUN_PRIORITY</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="functiontext">Sentences::Headings::build_search_list_from</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">);</span>
|
|
|
|
<<span class="cwebmacro">Verify that the search list indeed contains every noun just once</span> <span class="cwebmacronumber">27.3</span>><span class="plain">;</span>
|
|
|
|
<span class="identifier">noun_search_list_valid_for_this_heading</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::construct_noun_search_list appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP27_1"></a><b>§27.1. </b>Basically, we calculate the search list from the point of view of the
|
|
current sentence:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Work out the heading from which we wish to search</span> <span class="cwebmacronumber">27.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">current_sentence</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">Wordings::empty</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">))))</span>
|
|
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"cannot establish position P: there is no current sentence"</span><span class="plain">);</span>
|
|
<span class="identifier">source_location</span><span class="plain"> </span><span class="identifier">position_P</span><span class="plain"> = </span><span class="identifier">Wordings::location</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">));</span>
|
|
<span class="identifier">h</span><span class="plain"> = </span><span class="functiontext">Sentences::Headings::heading_of</span><span class="plain">(</span><span class="identifier">position_P</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP27">§27</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP27_2"></a><b>§27.2. </b>The pseudo-heading has no list of contents because all objects are created in
|
|
source files, each certainly underneath a File (0) heading, so nothing should
|
|
ever get that far.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Start the search list empty</span> <span class="cwebmacronumber">27.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">nt_search_start</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">nt_search_finish</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">pseudo_heading</span><span class="element">.list_of_contents</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">should always be true, but just in case</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP27">§27</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP27_3"></a><b>§27.3. </b>The potential for disaster if this algorithm should be incorrect is high,
|
|
so we perform a quick count to see if everything made it onto the list
|
|
and produce an internal error if not.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Verify that the search list indeed contains every noun just once</span> <span class="cwebmacronumber">27.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = 0; </span><span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER_NT_SEARCH_LIST</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">) </span><span class="identifier">c</span><span class="plain">++;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> != </span><span class="identifier">no_tags_attached</span><span class="plain">) {</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Reordering failed from $H\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%d tags created, %d in ordering\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">no_tags_attached</span><span class="plain">, </span><span class="identifier">c</span><span class="plain">);</span>
|
|
<span class="functiontext">Sentences::Headings::log_all_headings</span><span class="plain">();</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Making fresh tree:\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="functiontext">Sentences::Headings::make_tree</span><span class="plain">();</span>
|
|
<span class="functiontext">Sentences::Headings::log_all_headings</span><span class="plain">();</span>
|
|
<span class="identifier">internal_error_tree_unsafe</span><span class="plain">(</span><span class="string">"reordering of nametags failed"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP27">§27</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP28"></a><b>§28. </b>The following adds all nametags under heading H to the search list, using
|
|
its own list of contents, and then recurses to add all objects under
|
|
subheadings of H other than the one which has just recursed up to H. With
|
|
that done, we recurse up to the superheading of H.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">To prove that <code class="display"><span class="extract">Sentences::Headings::build_search_list_from</span></code> is called exactly once for each
|
|
heading in the tree, forget about the up/down orientation and consider it
|
|
as a graph instead. At each node we try going to every possible other node,
|
|
except the way we came (at the start of the traverse, the "way we came"
|
|
being null): clearly this ensures that all of our neighbours have been
|
|
visited. Since every heading ultimately depends from the pseudo-heading,
|
|
the graph is connected, and therefore every heading must eventually be
|
|
visited. No heading can be visited twice, because that would mean that a
|
|
cycle of nodes H_1, H_2, ..., H_i, H_1 must exist: since we have a tree
|
|
structure, there are no loops, and so H_i = H_2, H_{i-1} = H_3, and so
|
|
on — we must be walking a path and then retracing our steps in reverse.
|
|
That being so, there is a point where we turned back: we went from H_j to
|
|
H_{j+1} to H_j again. And this violates the principle that at each node
|
|
we move outwards in every direction except the way we came, a
|
|
contradiction.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The routine looks as if it may have a large recursion depth — maybe as
|
|
deep as the number of headings — but because we go downwards and then
|
|
upwards, the maximum recursion depth of the routine is less than 2L+1, where
|
|
L is the number of levels in the tree other than the pseudo-heading. This
|
|
provides an upper bound of about 21, regardless of the size of the source
|
|
text. The running time is linear in both the number of headings and the
|
|
number of nametags in the source text.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::build_search_list_from</span><span class="plain">(</span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">within</span><span class="plain">, </span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">way_we_came</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">p</span><span class="plain">) {</span>
|
|
<span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">; </span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">subhead</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">within</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">LOOP_OVER_NOUNS_UNDER</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">within</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Nouns::priority</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">) == </span><span class="identifier">p</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Add tag to the end of the search list</span> <span class="cwebmacronumber">28.1</span>><span class="plain">;</span>
|
|
|
|
<span class="comment">recurse downwards through subordinate headings, other than the way we came up</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">subhead</span><span class="plain"> = </span><span class="identifier">within</span><span class="plain">-</span><span class="element">>child_heading</span><span class="plain">; </span><span class="identifier">subhead</span><span class="plain">; </span><span class="identifier">subhead</span><span class="plain"> = </span><span class="identifier">subhead</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">subhead</span><span class="plain"> != </span><span class="identifier">way_we_came</span><span class="plain">)</span>
|
|
<span class="functiontext">Sentences::Headings::build_search_list_from</span><span class="plain">(</span><span class="identifier">subhead</span><span class="plain">, </span><span class="identifier">within</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
|
|
|
|
<span class="comment">recurse upwards to superior headings, unless we came here through a downward recursion</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">within</span><span class="plain">-</span><span class="element">>parent_heading</span><span class="plain"> != </span><span class="identifier">way_we_came</span><span class="plain">)</span>
|
|
<span class="functiontext">Sentences::Headings::build_search_list_from</span><span class="plain">(</span><span class="identifier">within</span><span class="plain">-</span><span class="element">>parent_heading</span><span class="plain">, </span><span class="identifier">within</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::build_search_list_from is used in <a href="#SP27">§27</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP28_1"></a><b>§28.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Add tag to the end of the search list</span> <span class="cwebmacronumber">28.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nt_search_finish</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
|
|
<span class="identifier">nt_search_start</span><span class="plain"> = </span><span class="identifier">nt</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">nt_search_finish</span><span class="plain">)-</span><span class="element">>next_to_search</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">"end of tag search list has frayed somehow"</span><span class="plain">);</span>
|
|
<span class="functiontext">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">nt_search_finish</span><span class="plain">)-</span><span class="element">>next_to_search</span><span class="plain"> = </span><span class="identifier">nt</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="functiontext">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-</span><span class="element">>next_to_search</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">nt_search_finish</span><span class="plain"> = </span><span class="identifier">nt</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP28">§28</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP29"></a><b>§29. </b>The search list is used for finding best matches in a particular order, the
|
|
order being used to break tie-breaks. Note that we return <code class="display"><span class="extract">NULL</span></code> if no noun
|
|
in the search list has a positive score.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::set_noun_search_score</span><span class="plain">(</span><span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</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="functiontext">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-</span><span class="element">>search_score</span><span class="plain"> = </span><span class="identifier">v</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="identifier">noun</span><span class="plain"> *</span><span class="functiontext">Sentences::Headings::highest_scoring_noun_searched</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">, *</span><span class="identifier">best_nt</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">best_score</span><span class="plain"> = 0;</span>
|
|
<span class="identifier">LOOP_OVER_NT_SEARCH_LIST</span><span class="plain">(</span><span class="identifier">nt</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">Sentences::Headings::name_resolution_data</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">)-</span><span class="element">>search_score</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">x</span><span class="plain"> > </span><span class="identifier">best_score</span><span class="plain">) { </span><span class="identifier">best_nt</span><span class="plain"> = </span><span class="identifier">nt</span><span class="plain">; </span><span class="identifier">best_score</span><span class="plain"> = </span><span class="identifier">x</span><span class="plain">; }</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">best_nt</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::set_noun_search_score appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::highest_scoring_noun_searched appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP30"></a><b>§30. Handling headings during the main traverses. </b>Here's what we do when we run into a heading, as we look through the
|
|
assertions in the source text: nothing, except to wipe out any meanings of
|
|
words like "it" left over from previous sentences. Headings are for
|
|
organisation, and are not directly functional in themselves.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">sentence_handler</span><span class="plain"> </span><span class="identifier">HEADING_SH_handler</span><span class="plain"> =</span>
|
|
<span class="plain">{ </span><span class="identifier">HEADING_NT</span><span class="plain">, -1, 0, </span><span class="functiontext">Sentences::Headings::handle_heading</span><span class="plain"> };</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::handle_heading</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">PN</span><span class="plain">) {</span>
|
|
<span class="functiontext">Assertions::Traverse::new_discussion</span><span class="plain">();</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::handle_heading appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP31"></a><b>§31. Describing the heading structure, 1: to the debugging log. </b>Finally, three ways to describe the run of headings: to the debugging log,
|
|
to the index of the project, and to a freestanding XML file.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::log</span><span class="plain">(</span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">==</span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"<null heading>\</span><span class="plain">n</span><span class="string">"</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">h</span><span class="plain">==&</span><span class="identifier">pseudo_heading</span><span class="plain">) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"<pseudo_heading>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">; }</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"H%d "</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">)</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"<%f, line %d>"</span><span class="plain">,</span>
|
|
<span class="identifier">TextFromFiles::get_filename</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">),</span>
|
|
<span class="identifier">h</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain">.</span><span class="identifier">line_number</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">"<nowhere>"</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">" level:%d indentation:%d"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>indentation</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::log is used in 1/cm (<a href="1-cm.html#SP5">§5</a>, <a href="1-cm.html#SP6_6">§6.6</a>).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP32"></a><b>§32. </b>And here we log the whole heading tree by recursing through it, and
|
|
surreptitiously check that it is correctly formed at the same time.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::log_all_headings</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="reserved">heading</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$H\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="functiontext">Sentences::Headings::log_headings_recursively</span><span class="plain">(&</span><span class="identifier">pseudo_heading</span><span class="plain">, 0);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::log_headings_recursively</span><span class="plain">(</span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</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">i</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</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="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain"><</span><span class="identifier">depth</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">" "</span><span class="plain">);</span>
|
|
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"$H\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">depth</span><span class="plain">-1 != </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>indentation</span><span class="plain">) </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"*** indentation should be %d ***\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">-1);</span>
|
|
<span class="functiontext">Sentences::Headings::log_headings_recursively</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>child_heading</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">+1);</span>
|
|
<span class="functiontext">Sentences::Headings::log_headings_recursively</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::log_all_headings is used in <a href="#SP27_3">§27.3</a>.</p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::log_headings_recursively appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP33"></a><b>§33. Describing the heading structure, 2: to the index. </b></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">headings_indexed</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::index</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<b>"</span><span class="plain">); </span><span class="identifier">PL::Bibliographic::contents_heading</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">); </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"</b>"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"CONTENTS"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="functiontext">Sentences::Headings::index_heading_recursively</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">pseudo_heading</span><span class="element">.child_heading</span><span class="plain">);</span>
|
|
<span class="reserved">contents_entry</span><span class="plain"> *</span><span class="identifier">ce</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">min_positive_level</span><span class="plain"> = 10;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ce</span><span class="plain">, </span><span class="reserved">contents_entry</span><span class="plain">)</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ce</span><span class="plain">-</span><span class="element">>heading_entered</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> > 0) &&</span>
|
|
<span class="plain">(</span><span class="identifier">ce</span><span class="plain">-</span><span class="element">>heading_entered</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> < </span><span class="identifier">min_positive_level</span><span class="plain">))</span>
|
|
<span class="identifier">min_positive_level</span><span class="plain"> = </span><span class="identifier">ce</span><span class="plain">-</span><span class="element">>heading_entered</span><span class="plain">-</span><span class="element">>level</span><span class="plain">;</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">ce</span><span class="plain">, </span><span class="reserved">contents_entry</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Index this entry in the contents</span> <span class="cwebmacronumber">33.1</span>><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">NUMBER_CREATED</span><span class="plain">(</span><span class="reserved">contents_entry</span><span class="plain">) == 1) {</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">); </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"(This would look more like a contents page if the source text "</span>
|
|
<span class="string">"were divided up into headings."</span><span class="plain">);</span>
|
|
<span class="identifier">Index::DocReferences::link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"HEADINGS"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">")"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::index appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP33_1"></a><b>§33.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Index this entry in the contents</span> <span class="cwebmacronumber">33.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain"> = </span><span class="identifier">ce</span><span class="plain">-</span><span class="element">>heading_entered</span><span class="plain">;</span>
|
|
<span class="comment">indent to correct tab position</span>
|
|
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"ul"</span><span class="plain">, </span><span class="string">"class=\</span><span class="plain">"</span><span class="string">leaders\</span><span class="plain">"</span><span class="string">"</span><span class="plain">); </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">ind_used</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>indentation</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> == 0) </span><span class="identifier">ind_used</span><span class="plain"> = 1;</span>
|
|
<span class="identifier">HTML_OPEN_WITH</span><span class="plain">(</span><span class="string">"li"</span><span class="plain">, </span><span class="string">"class=\</span><span class="plain">"</span><span class="string">leaded indent%d\</span><span class="plain">"</span><span class="string">"</span><span class="plain">, </span><span class="identifier">ind_used</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"span"</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> == 0) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">NUMBER_CREATED</span><span class="plain">(</span><span class="reserved">contents_entry</span><span class="plain">) == 1)</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Source text"</span><span class="plain">);</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"Preamble"</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="comment">write the text of the heading title</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">));</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"span"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_OPEN</span><span class="plain">(</span><span class="string">"span"</span><span class="plain">);</span>
|
|
<span class="reserved">contents_entry</span><span class="plain"> *</span><span class="identifier">next_ce</span><span class="plain"> = </span><span class="identifier">NEXT_OBJECT</span><span class="plain">(</span><span class="identifier">ce</span><span class="plain">, </span><span class="reserved">contents_entry</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> != 0)</span>
|
|
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">next_ce</span><span class="plain">) && (</span><span class="identifier">next_ce</span><span class="plain">-</span><span class="element">>heading_entered</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> > </span><span class="identifier">ce</span><span class="plain">-</span><span class="element">>heading_entered</span><span class="plain">-</span><span class="element">>level</span><span class="plain">))</span>
|
|
<span class="identifier">next_ce</span><span class="plain"> = </span><span class="identifier">NEXT_OBJECT</span><span class="plain">(</span><span class="identifier">next_ce</span><span class="plain">, </span><span class="reserved">contents_entry</span><span class="plain">);</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">start_word</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">ce</span><span class="plain">-</span><span class="element">>heading_entered</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">));</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">end_word</span><span class="plain"> = (</span><span class="identifier">next_ce</span><span class="plain">)?(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">next_ce</span><span class="plain">-</span><span class="element">>heading_entered</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">)))</span>
|
|
<span class="plain">: (</span><span class="identifier">TextFromFiles::last_lexed_word</span><span class="plain">(</span><span class="identifier">FIRST_OBJECT</span><span class="plain">(</span><span class="identifier">source_file</span><span class="plain">)));</span>
|
|
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = 0;</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">start_word</span><span class="plain">; </span><span class="identifier">i</span><span class="plain"> < </span><span class="identifier">end_word</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
|
|
<span class="identifier">N</span><span class="plain"> += </span><span class="identifier">TextFromFiles::word_count</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> > </span><span class="identifier">min_positive_level</span><span class="plain">) </span><span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"808080"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%d words"</span><span class="plain">, </span><span class="identifier">N</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> > </span><span class="identifier">min_positive_level</span><span class="plain">) </span><span class="identifier">HTML::end_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
|
|
<span class="comment">place a link to the relevant line of the primary source text</span>
|
|
<span class="identifier">Index::link_location</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"span"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"li"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"ul"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">List all the objects and kinds created under the given heading, one tap stop deeper</span> <span class="cwebmacronumber">33.1.2</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP33">§33</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP33_1_1"></a><b>§33.1.1. </b>We index only headings of level 1 and up — so, not the pseudo-heading or the
|
|
File (0) ones — and which are not within any extensions — so, are in the
|
|
primary source text written by the user.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::index_heading_recursively</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</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="reserved">int</span><span class="plain"> </span><span class="identifier">show_heading</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">next</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>child_heading</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">next</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">next</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">next</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">SourceFiles::get_extension_corresponding</span><span class="plain">(</span><span class="identifier">next</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">)))</span>
|
|
<span class="identifier">next</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain"> == 0) {</span>
|
|
<span class="identifier">show_heading</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">headings_indexed</span><span class="plain"> == 0) &&</span>
|
|
<span class="plain">((</span><span class="identifier">next</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) ||</span>
|
|
<span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">next</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">)) !=</span>
|
|
<span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>sentence_declaring</span><span class="plain">)))))</span>
|
|
<span class="identifier">show_heading</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">SourceFiles::get_extension_corresponding</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">))</span>
|
|
<span class="identifier">show_heading</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">show_heading</span><span class="plain">) {</span>
|
|
<span class="reserved">contents_entry</span><span class="plain"> *</span><span class="identifier">ce</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">contents_entry</span><span class="plain">);</span>
|
|
<span class="identifier">ce</span><span class="plain">-</span><span class="element">>heading_entered</span><span class="plain"> = </span><span class="identifier">h</span><span class="plain">;</span>
|
|
<span class="identifier">headings_indexed</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="functiontext">Sentences::Headings::index_heading_recursively</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>child_heading</span><span class="plain">);</span>
|
|
<span class="functiontext">Sentences::Headings::index_heading_recursively</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>next_heading</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::index_heading_recursively is used in <a href="#SP33">§33</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP33_1_2"></a><b>§33.1.2. </b>We skip any objects or kinds without names (i.e., whose <code class="display"><span class="extract">creator</span></code> is null).
|
|
The rest appear in italic type, and without links to source text since this
|
|
in practice strews distractingly many orange berries across the page.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">List all the objects and kinds created under the given heading, one tap stop deeper</span> <span class="cwebmacronumber">33.1.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">noun</span><span class="plain"> *</span><span class="identifier">nt</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="identifier">LOOP_OVER_NOUNS_UNDER</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Nouns::get_name</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</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">c</span><span class="plain">++ == 0) {</span>
|
|
<span class="identifier">HTMLFiles::open_para</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">ind_used</span><span class="plain">+1, </span><span class="string">"hanging"</span><span class="plain">);</span>
|
|
<span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"808080"</span><span class="plain">);</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">", "</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<i>%+W</i>"</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> > 0) { </span><span class="identifier">HTML::end_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">); </span><span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">); }</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP33_1">§33.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP34"></a><b>§34. Describing the heading structure, 3: to a freestanding XML file. </b>This is provided as a convenience to the application using Inform, which may want
|
|
to have a pull-down menu or similar gadget allowing the user to jump to a given
|
|
heading. This tells the interface where every heading is, thus saving it from
|
|
having to parse the source.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The property list contains a single dictionary, whose keys are the numbers
|
|
0, 1, 2, ..., n-1, where there are n headings in all. (The pseudo-heading
|
|
is not included.) A special key, the only non-numerical one, called "Application
|
|
Version", contains the Inform build number in its usual form: "4Q34", for instance.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::write_as_xml</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
|
|
<span class="identifier">text_stream</span><span class="plain"> </span><span class="identifier">xf_struct</span><span class="plain">; </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">xf</span><span class="plain"> = &</span><span class="identifier">xf_struct</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">xf</span><span class="plain">, </span><span class="identifier">filename_of_headings</span><span class="plain">, </span><span class="identifier">UTF8_ENC</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="identifier">Problems::Fatal::filename_related</span><span class="plain">(</span><span class="string">"Can't open headings file"</span><span class="plain">, </span><span class="identifier">filename_of_headings</span><span class="plain">);</span>
|
|
<span class="functiontext">Sentences::Headings::write_headings_as_xml_inner</span><span class="plain">(</span><span class="identifier">xf</span><span class="plain">);</span>
|
|
<span class="identifier">STREAM_CLOSE</span><span class="plain">(</span><span class="identifier">xf</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::Headings::write_headings_as_xml_inner</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">) {</span>
|
|
<span class="reserved">heading</span><span class="plain"> *</span><span class="identifier">h</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Write DTD indication for XML headings file</span> <span class="cwebmacronumber">34.1</span>><span class="plain">;</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<plist version=\</span><span class="plain">"</span><span class="string">1.0\</span><span class="plain">"</span><span class="string">><dict>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="identifier">INDENT</span><span class="plain">;</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<key>Application Version</key><string>%B (build %B)</string>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
|
|
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">, </span><span class="reserved">heading</span><span class="plain">) {</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<key>%d</key><dict>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-></span><span class="identifier">allocation_id</span><span class="plain">);</span>
|
|
<span class="identifier">INDENT</span><span class="plain">;</span>
|
|
<<span class="cwebmacro">Write the dictionary of properties for a single heading</span> <span class="cwebmacronumber">34.2</span>><span class="plain">;</span>
|
|
<span class="identifier">OUTDENT</span><span class="plain">;</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"</dict>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">OUTDENT</span><span class="plain">;</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"</dict></plist>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::write_as_xml is used in 1/mr (<a href="1-mr.html#SP4_9">§4.9</a>).</p>
|
|
|
|
<p class="endnote">The function Sentences::Headings::write_headings_as_xml_inner appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP34_1"></a><b>§34.1. </b>We use a convenient Apple DTD:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Write DTD indication for XML headings file</span> <span class="cwebmacronumber">34.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<?xml version=\</span><span class="plain">"</span><span class="string">1.0\</span><span class="plain">"</span><span class="string"> encoding=\</span><span class="plain">"</span><span class="string">UTF-8\</span><span class="plain">"</span><span class="string">?>\</span><span class="plain">n</span><span class="string">"</span>
|
|
<span class="string">"<!DOCTYPE plist PUBLIC \</span><span class="plain">"</span><span class="string">-//Apple Computer//DTD PLIST 1.0//EN\</span><span class="plain">"</span><span class="string"> "</span>
|
|
<span class="string">"\</span><span class="plain">"</span><span class="string">http://www.apple.com/DTDs/PropertyList-1.0.dtd\</span><span class="plain">"</span><span class="string">>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP34">§34</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP34_2"></a><b>§34.2. </b>Note that a level of 0, and a title of <code class="display"><span class="extract">--</span></code>, signifies a File (0) level
|
|
heading: external tools can probably ignore such records. Similarly, it is
|
|
unlikely that they will ever see a record without a "Filename" key —
|
|
this would mean a heading arising from text created internally within Inform,
|
|
which will only happen if someone has done something funny with <code class="display"><span class="extract">.i6t</span></code> files —
|
|
but should this arise then the best recourse is to ignore the heading.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Write the dictionary of properties for a single heading</span> <span class="cwebmacronumber">34.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">)</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<key>Filename</key><string>%f</string>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">TextFromFiles::get_filename</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain">.</span><span class="identifier">file_of_origin</span><span class="plain">));</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<key>Line</key><integer>%d</integer>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>start_location</span><span class="plain">.</span><span class="identifier">line_number</span><span class="plain">);</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">h</span><span class="plain">-</span><span class="element">>heading_text</span><span class="plain">))</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<key>Title</key><string>%+W</string>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>heading_text</span><span class="plain">);</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<key>Title</key><string>--</string>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<key>Level</key><integer>%d</integer>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>level</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"<key>Indentation</key><integer>%d</integer>\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">h</span><span class="plain">-</span><span class="element">>indentation</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP34">§34</a>.</p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="7-ss.html">Back to 'Structural Sentences'</a></li><li><a href="7-ns.html">Continue with 'Nonstructural Sentences'</a></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</body>
|
|
</html>
|
|
|