mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 10:04:21 +03:00
1235 lines
106 KiB
HTML
1235 lines
106 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<title>2/pt</title>
|
|
<meta name="viewport" content="width=device-width initial-scale=1">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<meta http-equiv="Content-Language" content="en-gb">
|
|
<link href="../inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
|
|
</head>
|
|
<body>
|
|
<nav role="navigation">
|
|
<h1><a href="../webs.html">Sources</a></h1>
|
|
<ul>
|
|
<li><a href="../compiler.html"><b>compiler tools</b></a></li>
|
|
<li><a href="../other.html">other tools</a></li>
|
|
<li><a href="../extensions.html">extensions and kits</a></li>
|
|
<li><a href="../units.html">unit test tools</a></li>
|
|
</ul>
|
|
<h2>Compiler Webs</h2>
|
|
<ul>
|
|
<li><a href="../inbuild/index.html">inbuild</a></li>
|
|
<li><a href="../inform7/index.html">inform7</a></li>
|
|
<li><a href="../inter/index.html">inter</a></li>
|
|
</ul>
|
|
<h2>Inbuild Modules</h2>
|
|
<ul>
|
|
<li><a href="../inbuild-module/index.html">inbuild</a></li>
|
|
<li><a href="../arch-module/index.html">arch</a></li>
|
|
<li><a href="../words-module/index.html">words</a></li>
|
|
<li><a href="../syntax-module/index.html">syntax</a></li>
|
|
<li><a href="../html-module/index.html">html</a></li>
|
|
</ul>
|
|
<h2>Inform7 Modules</h2>
|
|
<ul>
|
|
<li><a href="../core-module/index.html">core</a></li>
|
|
<li><a href="../problems-module/index.html">problems</a></li>
|
|
<li><a href="../inflections-module/index.html">inflections</a></li>
|
|
<li><a href="../linguistics-module/index.html">linguistics</a></li>
|
|
<li><a href="../kinds-module/index.html">kinds</a></li>
|
|
<li><a href="../if-module/index.html">if</a></li>
|
|
<li><a href="../multimedia-module/index.html">multimedia</a></li>
|
|
<li><a href="../index-module/index.html">index</a></li>
|
|
</ul>
|
|
<h2>Inter Modules</h2>
|
|
<ul>
|
|
<li><a href="../inter-module/index.html">inter</a></li>
|
|
<li><a href="../building-module/index.html">building</a></li>
|
|
<li><a href="../codegen-module/index.html">codegen</a></li>
|
|
</ul>
|
|
<h2>Foundation</h2>
|
|
<ul>
|
|
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
|
|
</ul>
|
|
|
|
|
|
</nav>
|
|
<main role="main">
|
|
|
|
<!--Weave of '2/snt' generated by 7-->
|
|
<ul class="crumbs"><li><a href="../webs.html">Source</a></li><li><a href="../compiler.html">Compiler Modules</a></li><li><a href="index.html">syntax</a></li><li><a href="index.html#2">Chapter 2: The Parse Tree</a></li><li><b>Sentences</b></li></ul><p class="purpose">To break up the stream of words produced by the lexer into English sentences, and join each to the parse tree.</p>
|
|
|
|
<ul class="toc"><li><a href="#SP1">§1. Definitions</a></li><li><a href="#SP4">§4. Sentence breaking</a></li><li><a href="#SP6">§6. Making sentence nodes</a></li><li><a href="#SP6_7">§6.7. Unskipped material which is not a heading</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>The following need to be available so that we can parse the source text
|
|
position.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">sfsm_extension_position</span><span class="plain"> = 0; </span> <span class="comment">0: not an extension; 1: before "begins here"; 2: before "ends here"; 3: after</span>
|
|
<span class="constant">node_type_t</span><span class="plain"> </span><span class="identifier">ssnt</span><span class="plain"> = 0;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP3"></a><b>§3. </b></p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="definitionkeyword">enum</span> <span class="constant">UnexpectedSemicolon_SYNERROR</span><span class="definitionkeyword"> from </span><span class="constant">1</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">ParaEndsInColon_SYNERROR</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">SentenceEndsInColon_SYNERROR</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">SentenceEndsInSemicolon_SYNERROR</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">SemicolonAfterColon_SYNERROR</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">SemicolonAfterStop_SYNERROR</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">ExtSpuriouslyContinues_SYNERROR</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">ExtNoBeginsHere_SYNERROR</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">ExtNoEndsHere_SYNERROR</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">HeadingOverLine_SYNERROR</span>
|
|
<span class="definitionkeyword">enum</span> <span class="constant">HeadingStopsBeforeEndOfLine_SYNERROR</span>
|
|
</pre>
|
|
<p class="inwebparagraph"><a id="SP4"></a><b>§4. Sentence breaking. </b>What breaks a sentence? In ordinary English, question marks, exclamation
|
|
marks, in some cases ellipses, but mainly full stops. In Inform source text,
|
|
only full stops are used outside quoted text; but we do have to recognise the
|
|
other cases when they occur at the end of quoted matter. Moreover, we
|
|
actually subdivide a little further, because we also want to break up
|
|
rule "sentences" into their subordinate clauses. Thus, going on
|
|
punctuation, we recognise rules as having the following model:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Preamble: phrase 1; phrase 2; ...; phrase N.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">It is even, in certain limited circumstances, possible that a comma can
|
|
divide a sentence:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Instead of eating, say "You really aren't hungry just now."</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">This means that context is important even here, where it might have been
|
|
expected that all we needed to do was to spot the punctuation marks.
|
|
So we carry out the sentence breaking with a simple finite state machine —
|
|
the last sentence having been a rule preamble tells us that the current one
|
|
is probably a phrase, and so on — and the following is its state.
|
|
</p>
|
|
|
|
|
|
<pre class="definitions">
|
|
<span class="plain">@</span><span class="reserved">default</span><span class="plain"> </span><span class="constant">COPY_FILE_TYPE</span><span class="plain"> </span><span class="reserved">void</span>
|
|
</pre>
|
|
|
|
<pre class="display">
|
|
<span class="identifier">source_file</span><span class="plain"> *</span><span class="identifier">sfsm_source_file</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">sfsm_inside_rule_mode</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">sfsm_skipping_material_at_level</span><span class="plain"> = -1;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">sfsm_in_tabbed_mode</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">sfsm_main_source_start_wn</span><span class="plain"> = -1;</span>
|
|
<span class="constant">COPY_FILE_TYPE</span><span class="plain"> *</span><span class="identifier">sfsm_copy</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::set_start_of_source</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">wn</span><span class="plain">) {</span>
|
|
<span class="identifier">sfsm_main_source_start_wn</span><span class="plain"> = </span><span class="identifier">wn</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::set_start_of_source appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5"></a><b>§5. </b>Now for the routine itself. We break into bite-sized chunks, each of which is
|
|
despatched to the <code class="display"><span class="extract">Sentences::make_node</span></code> routine with a note of the punctuation
|
|
which was used to end it. Each call to this routine represents one cycle of our
|
|
finite state machine.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::break</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
|
|
<span class="functiontext">Sentences::break_inner</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">FALSE</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::break_into_project_copy</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">, </span><span class="constant">COPY_FILE_TYPE</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">) {</span>
|
|
<span class="functiontext">Sentences::break_inner</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::break_into_extension_copy</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">, </span><span class="constant">COPY_FILE_TYPE</span><span class="plain"> *</span><span class="identifier">C</span><span class="plain">) {</span>
|
|
<span class="functiontext">Sentences::break_inner</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">, </span><span class="identifier">C</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::break_inner</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">is_extension</span><span class="plain">, </span><span class="constant">COPY_FILE_TYPE</span><span class="plain"> *</span><span class="identifier">from_copy</span><span class="plain">) {</span>
|
|
<span class="reserved">while</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="identifier">compare_word</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">), </span><span class="identifier">PARBREAK_V</span><span class="plain">)))</span>
|
|
<span class="identifier">W</span><span class="plain"> = </span><span class="identifier">Wordings::trim_first_word</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">Wordings::empty</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="reserved">int</span><span class="plain"> </span><span class="identifier">sentence_start</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::enable_last_sentence_cacheing</span><span class="plain">();</span>
|
|
|
|
<<span class="cwebmacro">Reset the sentence finite state machine</span> <span class="cwebmacronumber">5.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Go into table sentence mode if necessary</span> <span class="cwebmacronumber">5.2</span>><span class="plain">;</span>
|
|
|
|
<span class="identifier">LOOP_THROUGH_WORDING</span><span class="plain">(</span><span class="identifier">position</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">sentence_start</span><span class="plain"> < </span><span class="identifier">position</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_stop_words</span><span class="plain">, </span><span class="identifier">back_up_one_word</span><span class="plain">;</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">stop_character</span><span class="plain">;</span>
|
|
|
|
<<span class="cwebmacro">Look for a sentence break, finding the number of stop words and the stop character</span> <span class="cwebmacronumber">5.4</span>><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">no_stop_words</span><span class="plain"> > 0) {</span>
|
|
<span class="functiontext">Sentences::make_node</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">Wordings::new</span><span class="plain">(</span><span class="identifier">sentence_start</span><span class="plain">, </span><span class="identifier">position</span><span class="plain">-1), </span><span class="identifier">stop_character</span><span class="plain">);</span>
|
|
<span class="identifier">position</span><span class="plain"> = </span><span class="identifier">position</span><span class="plain"> + </span><span class="identifier">no_stop_words</span><span class="plain"> - 1;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">back_up_one_word</span><span class="plain">) </span><span class="identifier">sentence_start</span><span class="plain"> = </span><span class="identifier">position</span><span class="plain">;</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">sentence_start</span><span class="plain"> = </span><span class="identifier">position</span><span class="plain"> + 1;</span>
|
|
|
|
<<span class="cwebmacro">Go into table sentence mode if necessary</span> <span class="cwebmacronumber">5.2</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">sentence_start</span><span class="plain"> < </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) ||</span>
|
|
<span class="plain">((</span><span class="identifier">sentence_start</span><span class="plain"> == </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) && (!(</span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) == </span><span class="identifier">PARBREAK_V</span><span class="plain">)))) {</span>
|
|
<span class="functiontext">Sentences::make_node</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">Wordings::from</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">sentence_start</span><span class="plain">), </span><span class="character">'.'</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="functiontext">ParseTree::disable_last_sentence_cacheing</span><span class="plain">();</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">is_extension</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Issue a problem message if we are missing the begin and end here sentences</span> <span class="cwebmacronumber">5.5</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Reset the sentence finite state machine</span> <span class="cwebmacronumber">5.1</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::break appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Sentences::break_into_project_copy appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Sentences::break_into_extension_copy appears nowhere else.</p>
|
|
|
|
<p class="endnote">The function Sentences::break_inner appears nowhere else.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_1"></a><b>§5.1. </b>Each call to <code class="display"><span class="extract">Sentences::break</span></code> starts afresh, with no residual state
|
|
left over from previous calls. (The same cannot be said for <code class="display"><span class="extract">Sentences::make_node</span></code>,
|
|
which constructs individual sentences and is repeatedly called by us, and
|
|
that is why these are global variables rather than locals in <code class="display"><span class="extract">Sentences::break</span></code>.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Reset the sentence finite state machine</span> <span class="cwebmacronumber">5.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">sfsm_source_file</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
|
|
<span class="identifier">sfsm_inside_rule_mode</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="identifier">sfsm_skipping_material_at_level</span><span class="plain"> = -1;</span>
|
|
<span class="identifier">sfsm_copy</span><span class="plain"> = </span><span class="identifier">from_copy</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">is_extension</span><span class="plain">) </span><span class="identifier">sfsm_extension_position</span><span class="plain"> = 1;</span>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">sfsm_extension_position</span><span class="plain"> = 0;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5">§5</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_2"></a><b>§5.2. </b>A table is any sentence beginning with the word "Table". (Bad news for
|
|
anyone writing "Table Mountain is a room.", of course, but there are other
|
|
ways to do that, and it seems wise to keep the syntax for tables clear,
|
|
since their entries are governed by different lexical and semantic rules.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Go into table sentence mode if necessary</span> <span class="cwebmacronumber">5.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((<</span><span class="identifier">structural</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">>(</span><span class="identifier">Wordings::from</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">sentence_start</span><span class="plain">))) &&</span>
|
|
<span class="plain">(</span><span class="functiontext">ParseTree::test_flag</span><span class="plain">(</span><span class="identifier">ssnt</span><span class="plain">, </span><span class="constant">TABBED_CONTENT_NFLAG</span><span class="plain">)))</span>
|
|
<span class="identifier">sfsm_in_tabbed_mode</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">else</span>
|
|
<span class="identifier">sfsm_in_tabbed_mode</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5">§5</a> (twice).</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_3"></a><b>§5.3. </b>We now come to the definition of a sentence break, which is more complicated
|
|
than might have been expected.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">For one thing, a run of sentence divisions is treated as a single division,
|
|
only the last of which is the one which counts. This looks odd at first sight,
|
|
because it means that Inform considers
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>The cat is on the table;.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">to be a valid sentence, equivalent to
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>The cat is on the table.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">But it has the advantage that it enables us to avoid being pointlessly strict
|
|
over the punctuation which precedes a paragraph break. Some people like to
|
|
write paragraphs like this:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">Before going north:</span>
|
|
<span class="plain"> say "Northward ho!";</span>
|
|
<span class="plain"> now the compass points north;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">And properly speaking that ends with a semicolon then a paragraph break,
|
|
which is a doubled sentence division. But we forgive it as harmless, and
|
|
that forgiveness is provided by the loop arrangement below.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">We also avoid the need for empty sentences, because it is not possible
|
|
for the code below to detect them: thus
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>say "Look behind you!";;;;; now the Wug is in the Cave</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">is broken as two sentences, not six sentences of which four are empty.
|
|
Perhaps we ought to be stricter, and reject more of these dubious forms,
|
|
but at this point we have too little understanding of the semantics of
|
|
the text to risk annoying the user with problem messages.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_4"></a><b>§5.4. </b>Full stops, semicolons and paragraph breaks (all rendered by the lexer as
|
|
individual words: the stroke word in the case of the latter) are always
|
|
sentence divisions. The other cases are more complicated: see below.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Look for a sentence break, finding the number of stop words and the stop character</span> <span class="cwebmacronumber">5.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">at</span><span class="plain"> = </span><span class="identifier">position</span><span class="plain">;</span>
|
|
<span class="identifier">no_stop_words</span><span class="plain"> = 0; </span><span class="identifier">stop_character</span><span class="plain"> = </span><span class="character">'?'</span><span class="plain">; </span><span class="identifier">back_up_one_word</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">at</span><span class="plain"> < </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">stopped</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">Lexer::word</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">) == </span><span class="identifier">PARBREAK_V</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stop_character</span><span class="plain"> == </span><span class="character">':'</span><span class="plain">) </span><<span class="cwebmacro">Issue problem for colon at end of paragraph</span> <span class="cwebmacronumber">5.4.1</span>><span class="plain">;</span>
|
|
<span class="identifier">stop_character</span><span class="plain"> = </span><span class="character">'|'</span><span class="plain">; </span><span class="identifier">stopped</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">Lexer::word</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">) == </span><span class="identifier">FULLSTOP_V</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stop_character</span><span class="plain"> == </span><span class="character">':'</span><span class="plain">) </span><<span class="cwebmacro">Issue problem for colon at end of sentence</span> <span class="cwebmacronumber">5.4.2</span>><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stop_character</span><span class="plain"> == </span><span class="character">';'</span><span class="plain">) </span><<span class="cwebmacro">Issue problem for semicolon at end of sentence</span> <span class="cwebmacronumber">5.4.3</span>><span class="plain">;</span>
|
|
<span class="identifier">stop_character</span><span class="plain"> = </span><span class="character">'.'</span><span class="plain">; </span><span class="identifier">stopped</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">Lexer::word</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">) == </span><span class="identifier">SEMICOLON_V</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stop_character</span><span class="plain"> == </span><span class="character">':'</span><span class="plain">) </span><<span class="cwebmacro">Issue problem for semicolon after colon</span> <span class="cwebmacronumber">5.4.4</span>><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stop_character</span><span class="plain"> == </span><span class="character">'.'</span><span class="plain">) </span><<span class="cwebmacro">Issue problem for semicolon after full stop</span> <span class="cwebmacronumber">5.4.5</span>><span class="plain">;</span>
|
|
<span class="identifier">stop_character</span><span class="plain"> = </span><span class="character">';'</span><span class="plain">; </span><span class="identifier">stopped</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<<span class="cwebmacro">Consider if a colon divides a sentence</span> <span class="cwebmacronumber">5.4.6</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Consider if punctuation within a preceding quoted text divides a sentence, making an X break</span> <span class="cwebmacronumber">5.4.7</span>><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stopped</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="identifier">no_stop_words</span><span class="plain">++; </span><span class="identifier">at</span><span class="plain">++;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stop_character</span><span class="plain"> == </span><span class="character">'X'</span><span class="plain">) { </span> <span class="comment">X breaks are like full stops, but there is no stop word to skip over</span>
|
|
<span class="identifier">stop_character</span><span class="plain"> = </span><span class="character">'.'</span><span class="plain">; </span><span class="identifier">back_up_one_word</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">no_stop_words</span><span class="plain"> > 0)</span>
|
|
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">LEXICAL_OUTPUT</span><span class="plain">, </span><span class="string">"Stop character '%c', no_stop_words %d, sentence_break %d, position %d\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
|
|
<span class="identifier">stop_character</span><span class="plain">, </span><span class="identifier">no_stop_words</span><span class="plain">, </span><span class="identifier">sentence_start</span><span class="plain">, </span><span class="identifier">position</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5">§5</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_4_1"></a><b>§5.4.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue problem for colon at end of paragraph</span> <span class="cwebmacronumber">5.4.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="functiontext">Sentences::syntax_problem</span><span class="plain">(</span><span class="constant">ParaEndsInColon_SYNERROR</span><span class="plain">, </span><span class="identifier">Wordings::new</span><span class="plain">(</span><span class="identifier">sentence_start</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">-1), </span><span class="identifier">sfsm_copy</span><span class="plain">, 0);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5_4">§5.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_4_2"></a><b>§5.4.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue problem for colon at end of sentence</span> <span class="cwebmacronumber">5.4.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="functiontext">Sentences::syntax_problem</span><span class="plain">(</span><span class="constant">SentenceEndsInColon_SYNERROR</span><span class="plain">, </span><span class="identifier">Wordings::new</span><span class="plain">(</span><span class="identifier">sentence_start</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">), </span><span class="identifier">sfsm_copy</span><span class="plain">, 0);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5_4">§5.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_4_3"></a><b>§5.4.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue problem for semicolon at end of sentence</span> <span class="cwebmacronumber">5.4.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="functiontext">Sentences::syntax_problem</span><span class="plain">(</span><span class="constant">SentenceEndsInSemicolon_SYNERROR</span><span class="plain">, </span><span class="identifier">Wordings::new</span><span class="plain">(</span><span class="identifier">sentence_start</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">), </span><span class="identifier">sfsm_copy</span><span class="plain">, 0);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5_4">§5.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_4_4"></a><b>§5.4.4. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue problem for semicolon after colon</span> <span class="cwebmacronumber">5.4.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="functiontext">Sentences::syntax_problem</span><span class="plain">(</span><span class="constant">SemicolonAfterColon_SYNERROR</span><span class="plain">, </span><span class="identifier">Wordings::new</span><span class="plain">(</span><span class="identifier">sentence_start</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">), </span><span class="identifier">sfsm_copy</span><span class="plain">, 0);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5_4">§5.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_4_5"></a><b>§5.4.5. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Issue problem for semicolon after full stop</span> <span class="cwebmacronumber">5.4.5</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="functiontext">Sentences::syntax_problem</span><span class="plain">(</span><span class="constant">SemicolonAfterStop_SYNERROR</span><span class="plain">, </span><span class="identifier">Wordings::new</span><span class="plain">(</span><span class="identifier">sentence_start</span><span class="plain">, </span><span class="identifier">at</span><span class="plain">), </span><span class="identifier">sfsm_copy</span><span class="plain">, 0);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5_4">§5.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_4_6"></a><b>§5.4.6. </b>Colons are normally dividers, too, but an exception is made if they come
|
|
between two apparently numerical constructions, because this suggests that
|
|
the colon is being used not as punctuation but within a literal pattern.
|
|
(For instance, "He went out at 1:34 PM." is a sentence with just one
|
|
clause, not two clauses divided by the colon; but "He went out at 1 PM:
|
|
the snow was still falling." is indeed divided. Our rule here correctly
|
|
distinguishes these cases, and although it can be fooled by really contrived
|
|
sentences — "He went out at 1: 22 Company, the Parachute Regiment, was
|
|
marching." — it's robust enough in practice. The exception is forbidden
|
|
if a line break occurs between the colon and the succeeding numeral, as
|
|
then we might be looking at switch cases in an "if".)
|
|
</p>
|
|
|
|
<p class="inwebparagraph">Note that here we are at a word position which is strictly within the word
|
|
range being sentence-broken, so that it is safe to examine both the word
|
|
before and the word after the current position.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Consider if a colon divides a sentence</span> <span class="cwebmacronumber">5.4.6</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">) == </span><span class="identifier">COLON_V</span><span class="plain">) &&</span>
|
|
<span class="plain">(</span><span class="identifier">Lexer::file_of_origin</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">-1) == </span><span class="identifier">Lexer::file_of_origin</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">)) &&</span>
|
|
<span class="plain">(</span><span class="identifier">no_stop_words</span><span class="plain"> == 0) &&</span>
|
|
<span class="plain">((</span><span class="identifier">Characters::isdigit</span><span class="plain">(*(</span><span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">-1))) == </span><span class="identifier">FALSE</span><span class="plain">) ||</span>
|
|
<span class="plain">(</span><span class="identifier">Characters::isdigit</span><span class="plain">(*(</span><span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">+1))) == </span><span class="identifier">FALSE</span><span class="plain">) ||</span>
|
|
<span class="plain">(</span><span class="identifier">Lexer::indentation_level</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">+1) > 0))) {</span>
|
|
<span class="identifier">stop_character</span><span class="plain"> = </span><span class="character">':'</span><span class="plain">; </span><span class="identifier">stopped</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5_4">§5.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_4_7"></a><b>§5.4.7. </b>Inform authors habitually use the punctuation in quoted text to end
|
|
sentences, just as other writers of English do. The text
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>"Look out!" The explosion shattered the calm of the hillside.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">is certainly intended as two sentences, not one.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">An exception is made for table declarations, because a table needs to be formed as
|
|
one long sentence, and it clearly does not abide by the ordinary punctuation
|
|
rules of English. The point is that in the random line of table entries...
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>"Of cabbages and kings."\qquad Walrus\qquad "Carroll"</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">...the full stop after "kings" has no significance: the semantics of the
|
|
table would be no different if it were not there.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Consider if punctuation within a preceding quoted text divides a sentence, making an X break</span> <span class="cwebmacronumber">5.4.7</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">stopped</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) && </span> <span class="comment">only look if we are not already at a division</span>
|
|
<span class="plain">(</span><span class="identifier">no_stop_words</span><span class="plain"> == 0) && </span> <span class="comment">be sure not to elide two such texts in a row</span>
|
|
<span class="plain">(</span><span class="identifier">sfsm_in_tabbed_mode</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) && </span> <span class="comment">check that we are not scanning the body of a table</span>
|
|
<span class="plain">(</span><span class="identifier">isupper</span><span class="plain">(*(</span><span class="identifier">Lexer::word_raw_text</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">)))) && </span> <span class="comment">and the current word begins with a capital letter</span>
|
|
<span class="plain">(</span><span class="identifier">Word::text_ending_sentence</span><span class="plain">(</span><span class="identifier">at</span><span class="plain">-1))) { </span> <span class="comment">and the preceding one was quoted text ending in punctuation</span>
|
|
<span class="identifier">stop_character</span><span class="plain"> = </span><span class="character">'X'</span><span class="plain">; </span><span class="identifier">stopped</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP5_4">§5.4</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6"></a><b>§6. Making sentence nodes. </b>At this point we have established that <code class="display"><span class="extract">Sentences::make_node</span></code> is called
|
|
sequentially for every divided-off sentence in the original source text.
|
|
But we need a little machinery to skip past sentences which are being
|
|
excluded for one reason or another.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The design of Inform deliberately excludes conditional compilation in the
|
|
traditional C sense of <code class="display"><span class="extract">#ifdef</span></code> and <code class="display"><span class="extract">#endif</span></code>. This takes us too far from
|
|
what natural language would do, faced with the same basic issue. A book, or
|
|
a government form, would more naturally have a heading making clear that
|
|
the section beneath it is not universal in application. This is what Inform
|
|
does, too: it parses a heading to decide whether to skip the material,
|
|
and if so, the state <code class="display"><span class="extract">sfsm_skipping_material_at_level</span></code> is set to the
|
|
level of the heading in question. We then skip all subsequent sentences
|
|
until reaching the next heading of the same or higher status, or until
|
|
reaching the "... ends here." sentence (if we are reading an extension),
|
|
or until reaching the end of the text: whichever comes first.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::make_node</span><span class="plain">(</span><span class="reserved">parse_node_tree</span><span class="plain"> *</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">stop_character</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">heading_level</span><span class="plain"> = 0, </span><span class="identifier">begins_or_ends</span><span class="plain"> = 0;</span>
|
|
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">new</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::empty</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"empty sentence generated"</span><span class="plain">);</span>
|
|
|
|
<span class="identifier">Vocabulary::identify_word_range</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">); </span> <span class="comment">a precaution to catch any late unidentified text</span>
|
|
|
|
<<span class="cwebmacro">Detect a change of source file, and declare it as an implicit heading</span> <span class="cwebmacronumber">6.1</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Detect a dividing sentence</span> <span class="cwebmacronumber">6.3</span>><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">begins_or_ends</span><span class="plain"> == -1) ||</span>
|
|
<span class="plain">((</span><span class="identifier">heading_level</span><span class="plain"> > 0) && (</span><span class="identifier">heading_level</span><span class="plain"> <= </span><span class="identifier">sfsm_skipping_material_at_level</span><span class="plain">)))</span>
|
|
<span class="identifier">sfsm_skipping_material_at_level</span><span class="plain"> = -1;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sfsm_skipping_material_at_level</span><span class="plain"> >= 0) </span><span class="reserved">return</span><span class="plain">;</span>
|
|
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">heading_level</span><span class="plain"> > 0) {</span>
|
|
<<span class="cwebmacro">Issue a problem message if the heading incorporates a line break</span> <span class="cwebmacronumber">6.4</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Issue a problem message if the heading does not end with a line break</span> <span class="cwebmacronumber">6.5</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Make a new HEADING node, possibly beginning to skip material</span> <span class="cwebmacronumber">6.6</span>><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<<span class="cwebmacro">Reject if we have run on past the end of an extension</span> <span class="cwebmacronumber">6.2</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Accept the new sentence as one or more nodes in the parse tree</span> <span class="cwebmacronumber">6.9</span>><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::make_node is used in <a href="#SP5">§5</a>, <a href="#SP6_9_3_1">§6.9.3.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_1"></a><b>§6.1. </b>For reasons gone into in the section on Headings below, a change of
|
|
source file (e.g., when one extension has been read in and another begins)
|
|
is declared as if it were a super-heading in the text.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Detect a change of source file, and declare it as an implicit heading</span> <span class="cwebmacronumber">6.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Lexer::file_of_origin</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) != </span><span class="identifier">sfsm_source_file</span><span class="plain">) {</span>
|
|
<span class="reserved">parse_node</span><span class="plain"> *</span><span class="identifier">implicit_heading</span><span class="plain"> = </span><span class="functiontext">ParseTree::new</span><span class="plain">(</span><span class="constant">HEADING_NT</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">implicit_heading</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">implicit_heading</span><span class="plain">, </span><span class="constant">sentence_unparsed_ANNOT</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">implicit_heading</span><span class="plain">, </span><span class="constant">heading_level_ANNOT</span><span class="plain">, 0);</span>
|
|
<span class="functiontext">ParseTree::insert_sentence</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">implicit_heading</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">NEW_HEADING_HANDLER</span>
|
|
<span class="identifier">NEW_HEADING_HANDLER</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">implicit_heading</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="identifier">sfsm_skipping_material_at_level</span><span class="plain"> = -1;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">sfsm_source_file</span><span class="plain"> = </span><span class="identifier">Lexer::file_of_origin</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">));</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6">§6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_2"></a><b>§6.2. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Reject if we have run on past the end of an extension</span> <span class="cwebmacronumber">6.2</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">sfsm_extension_position</span><span class="plain"> == 3) && (</span><span class="identifier">begins_or_ends</span><span class="plain"> == 0)) {</span>
|
|
<span class="functiontext">Sentences::syntax_problem</span><span class="plain">(</span><span class="constant">ExtSpuriouslyContinues_SYNERROR</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">sfsm_copy</span><span class="plain">, 0);</span>
|
|
<span class="identifier">sfsm_extension_position</span><span class="plain"> = 4; </span> <span class="comment">to avoid multiply issuing this</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6">§6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_3"></a><b>§6.3. </b>The client must define a Preform nonterminal called <code class="display"><span class="extract"><dividing-sentence></span></code>
|
|
which returns either a heading level number (1 to 10, with 1 the most
|
|
important), or <code class="display"><span class="extract">-1</span></code> to mean that the sentence begins an extension, or
|
|
<code class="display"><span class="extract">-2</span></code> that it ends one.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Detect a dividing sentence</span> <span class="cwebmacronumber">6.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (<</span><span class="identifier">dividing</span><span class="plain">-</span><span class="identifier">sentence</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"> -1: </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sfsm_extension_position</span><span class="plain"> > 0) </span><span class="identifier">begins_or_ends</span><span class="plain"> = 1;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> -2:</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sfsm_extension_position</span><span class="plain"> > 0) </span><span class="identifier">begins_or_ends</span><span class="plain"> = -1;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">default</span><span class="plain">:</span>
|
|
<span class="identifier">heading_level</span><span class="plain"> = <<</span><span class="identifier">r</span><span class="plain">>>;</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6">§6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_4"></a><b>§6.4. </b>We have already looked to see if the sentence could be a heading, and set
|
|
the variable <code class="display"><span class="extract">heading_level</span></code> to be its ranking in the hierarchy (with 1,
|
|
for "volume", the highest). But we also want to check that the heading
|
|
does not have a line break in, because this is almost certainly a mistake
|
|
by the designer, and likely to be a difficult one to understand: so we
|
|
should help out if we can. Such a problem is best recovered from by
|
|
continuing regardless.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Issue a problem message if the heading incorporates a line break</span> <span class="cwebmacronumber">6.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">LOOP_THROUGH_WORDING</span><span class="plain">(</span><span class="identifier">k</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">k</span><span class="plain"> > </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">))</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Lexer::break_before</span><span class="plain">(</span><span class="identifier">k</span><span class="plain">) == </span><span class="character">'\</span><span class="plain">n</span><span class="character">'</span><span class="plain">) || (</span><span class="identifier">Lexer::indentation_level</span><span class="plain">(</span><span class="identifier">k</span><span class="plain">) > 0)) {</span>
|
|
<span class="functiontext">Sentences::syntax_problem</span><span class="plain">(</span><span class="constant">HeadingOverLine_SYNERROR</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">sfsm_copy</span><span class="plain">, </span><span class="identifier">k</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="#SP6">§6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_5"></a><b>§6.5. </b>And similarly... Here we take the liberty of looking a little ahead of
|
|
the current word range in order to make the problem message more helpful:
|
|
we check that we are still looking at valid words in the lexer, just to be
|
|
on the safe side, but in fact we cannot run on past the end of the lexer
|
|
feed which fed the malformed heading, because of all of the run-off
|
|
newlines automatically added at the end of the feed of any source file.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Issue a problem message if the heading does not end with a line break</span> <span class="cwebmacronumber">6.5</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Lexer::break_before</span><span class="plain">(</span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)+1) != </span><span class="character">'\</span><span class="plain">n</span><span class="character">'</span><span class="plain">) {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain">;</span>
|
|
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain"> = </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)+1;</span>
|
|
<span class="plain">(</span><span class="identifier">k</span><span class="plain"><=</span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)+8) && (</span><span class="identifier">k</span><span class="plain"><</span><span class="identifier">lexer_wordcount</span><span class="plain">) && (</span><span class="identifier">Lexer::break_before</span><span class="plain">(</span><span class="identifier">k</span><span class="plain">) != </span><span class="character">'\</span><span class="plain">n</span><span class="character">'</span><span class="plain">);</span>
|
|
<span class="identifier">k</span><span class="plain">++) ;</span>
|
|
<span class="functiontext">Sentences::syntax_problem</span><span class="plain">(</span><span class="constant">HeadingStopsBeforeEndOfLine_SYNERROR</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">sfsm_copy</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6">§6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_6"></a><b>§6.6. </b>We now have a genuine heading, and can declare it, calling a routine
|
|
in Headings to determine whether we should include the material.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Make a new HEADING node, possibly beginning to skip material</span> <span class="cwebmacronumber">6.6</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">new</span><span class="plain"> = </span><span class="functiontext">ParseTree::new</span><span class="plain">(</span><span class="constant">HEADING_NT</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="constant">sentence_unparsed_ANNOT</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="constant">heading_level_ANNOT</span><span class="plain">, </span><span class="identifier">heading_level</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::insert_sentence</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">new</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">NEW_HEADING_HANDLER</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">NEW_HEADING_HANDLER</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">new</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="identifier">sfsm_skipping_material_at_level</span><span class="plain"> = </span><span class="identifier">heading_level</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6">§6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP5_5"></a><b>§5.5. </b>When we finish scanning all the sentences in a given batch, and if they came
|
|
from an extension, we need to make sure we saw both beginning and end:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Issue a problem message if we are missing the begin and end here sentences</span> <span class="cwebmacronumber">5.5</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">sfsm_extension_position</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> 1: </span><span class="functiontext">Sentences::syntax_problem</span><span class="plain">(</span><span class="constant">ExtNoBeginsHere_SYNERROR</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">sfsm_copy</span><span class="plain">, 0); </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 2: </span><span class="functiontext">Sentences::syntax_problem</span><span class="plain">(</span><span class="constant">ExtNoEndsHere_SYNERROR</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">sfsm_copy</span><span class="plain">, 0); </span><span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="reserved">case</span><span class="plain"> 3: </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="#SP5">§5</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_7"></a><b>§6.7. Unskipped material which is not a heading. </b>Each of the sentences which are to be included is given its own node on the
|
|
parse tree, which for the time being is a direct child of the root.
|
|
Sentences are classified by their node types, the main identification
|
|
attached to each unit in the tree.
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<ul class="items"><li>(a) "Nonstructural sentences", which will be subject to further parsing
|
|
work, have node type <code class="display"><span class="extract">SENTENCE_NT</span></code> (and so will "regular sentences").
|
|
Anything we cannot place into categories (b) or (c) below will go here.
|
|
</li></ul>
|
|
<ul class="items"><li>(b) "Sentences making up rules". These are sequences of sentences in which
|
|
a preamble (ending with a colon, or in certain cases a comma) of node type
|
|
<code class="display"><span class="extract">ROUTINE_NT</span></code> is followed by a sequence of phrases (ending with semicolons until
|
|
the last, which ends with a full stop or paragraph break), each of node type
|
|
<code class="display"><span class="extract">INVOCATION_LIST_NT</span></code>. For instance, the following produces three nodes:
|
|
</li></ul>
|
|
<blockquote>
|
|
<p>To look upwards: say "Look out!"; something else.</p>
|
|
|
|
</blockquote>
|
|
|
|
<ul class="items"><li>(c) "Structural sentences". These demarcate the text, call for other text
|
|
or unusual matter to be included, etc.: the types in question are <code class="display"><span class="extract">TRACE_NT</span></code>,
|
|
<code class="display"><span class="extract">HEADING_NT</span></code>, <code class="display"><span class="extract">INCLUDE_NT</span></code>, <code class="display"><span class="extract">INFORM6CODE_NT</span></code>, <code class="display"><span class="extract">BEGINHERE_NT</span></code>, <code class="display"><span class="extract">ENDHERE_NT</span></code>,
|
|
<code class="display"><span class="extract">TABLE_NT</span></code>, <code class="display"><span class="extract">EQUATION_NT</span></code> and <code class="display"><span class="extract">BIBLIOGRAPHIC_NT</span></code>.
|
|
</li></ul>
|
|
<p class="inwebparagraph"><a id="SP6_8"></a><b>§6.8. </b>The second sentence in the source text is construed as containing
|
|
bibliographic data if it begins with a quoted piece of text, perhaps with
|
|
substitutions. For instance,
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>"A Dream of Fair to Middling Women" by Samuel Beckett</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">This sentence is at the position matched by <if-start-of-source-text>.
|
|
(It may not be the first sentence read, because implied extension inclusion
|
|
sentences and options-file sentences may have been read already.)
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain"><</span><span class="reserved">if</span><span class="plain">-</span><span class="identifier">start</span><span class="plain">-</span><span class="identifier">of</span><span class="plain">-</span><span class="identifier">source</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">> </span><span class="identifier">internal</span><span class="plain"> 0 {</span>
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">w1</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">w1</span><span class="plain"> >= 0) {</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">w1</span><span class="plain"> == </span><span class="identifier">sfsm_main_source_start_wn</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">compare_word</span><span class="plain">(</span><span class="identifier">w1</span><span class="plain">-1, </span><span class="identifier">PARBREAK_V</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="identifier">w1</span><span class="plain">--;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_9"></a><b>§6.9. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Accept the new sentence as one or more nodes in the parse tree</span> <span class="cwebmacronumber">6.9</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<<span class="cwebmacro">Convert comma-divided rule into two sentences, if this is allowed</span> <span class="cwebmacronumber">6.9.3</span>><span class="plain">;</span>
|
|
<<span class="cwebmacro">Otherwise, make a SENTENCE node</span> <span class="cwebmacronumber">6.9.4</span>><span class="plain">;</span>
|
|
|
|
<<span class="cwebmacro">Convert a rule preamble to a ROUTINE node and enter rule mode</span> <span class="cwebmacronumber">6.9.5</span>><span class="plain">;</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sfsm_inside_rule_mode</span><span class="plain">)</span>
|
|
<<span class="cwebmacro">Convert to a COMMAND node and exit rule mode unless a semicolon implies further commands</span> <span class="cwebmacronumber">6.9.6</span>>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stop_character</span><span class="plain"> == </span><span class="character">';'</span><span class="plain">) {</span>
|
|
<span class="functiontext">Sentences::syntax_problem</span><span class="plain">(</span><span class="constant">UnexpectedSemicolon_SYNERROR</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">sfsm_copy</span><span class="plain">, 0);</span>
|
|
<span class="identifier">stop_character</span><span class="plain"> = </span><span class="character">'.'</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
|
|
<span class="comment">at this point we are certainly in assertion mode, not rule mode</span>
|
|
<span class="reserved">if</span><span class="plain"> (<</span><span class="identifier">structural</span><span class="plain">-</span><span class="identifier">sentence</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">r</span><span class="plain">>> == -1)</span>
|
|
<<span class="cwebmacro">Detect a language definition sentence and sneakily act upon it</span> <span class="cwebmacronumber">6.9.8</span>>
|
|
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (<<</span><span class="identifier">r</span><span class="plain">>> == -2) {</span>
|
|
<<span class="cwebmacro">Detect a Preform grammar inclusion and sneakily act upon it</span> <span class="cwebmacronumber">6.9.9</span>>
|
|
<span class="functiontext">ParseTree::set_type</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="identifier">ssnt</span><span class="plain">); </span><span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="functiontext">ParseTree::set_type</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="identifier">ssnt</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">INBUILD_MODULE</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ssnt</span><span class="plain"> == </span><span class="identifier">BIBLIOGRAPHIC_NT</span><span class="plain">)</span>
|
|
<span class="identifier">Projects::notify_of_bibliographic_sentence</span><span class="plain">(</span><span class="identifier">Inbuild::project</span><span class="plain">(), </span><span class="identifier">new</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">}</span>
|
|
|
|
<<span class="cwebmacro">Convert a begins here or ends here sentence to a BEGINHERE or ENDHERE node and return</span> <span class="cwebmacronumber">6.9.7</span>><span class="plain">;</span>
|
|
|
|
<span class="comment">none of that happened, so we have a SENTENCE node for certain</span>
|
|
<span class="functiontext">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="constant">sentence_unparsed_ANNOT</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">SENTENCE_ANNOTATION_FUNCTION</span>
|
|
<span class="identifier">SENTENCE_ANNOTATION_FUNCTION</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6">§6</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_9_1"></a><b>§6.9.1. </b>Rules are ordinarily detected by their colon, which divides the header from the
|
|
rest: colons are not otherwise legal in Inform. But there's an exception. If the
|
|
sentence consists of text matching the following grammar, followed by comma,
|
|
followed by more text, then the comma is read as if it's a colon and the
|
|
sentence becomes a rule. For example:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Instead of going north, try entering the cage</p>
|
|
|
|
</blockquote>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain"><</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">divisible</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">> ::=</span>
|
|
<span class="identifier">instead</span><span class="plain"> </span><span class="identifier">of</span><span class="plain"> ... |</span>
|
|
<span class="identifier">every</span><span class="plain"> </span><span class="identifier">turn</span><span class="plain"> *** |</span>
|
|
<span class="identifier">before</span><span class="plain"> ... |</span>
|
|
<span class="identifier">after</span><span class="plain"> ... |</span>
|
|
<span class="identifier">when</span><span class="plain"> ...</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_9_2"></a><b>§6.9.2. </b>We make an exception to the exception for the serial comma used in a list of
|
|
alternatives: thus the comma in "Aeschylus, Sophocles, or Euripides" does
|
|
not trigger this rule. We need this exception because such lists of
|
|
alternatives often occur in rule preambles, where it's the third comma
|
|
which divides rule from preamble:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Instead of pushing, dropping, or taking the talisman, say "It is cursed."</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">The following is used to detect "or" in such lists.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain"><</span><span class="identifier">list</span><span class="plain">-</span><span class="identifier">or</span><span class="plain">-</span><span class="identifier">division</span><span class="plain">> ::=</span>
|
|
<span class="plain">...... , </span><span class="identifier">_or</span><span class="plain"> ...... |</span>
|
|
<span class="plain">...... </span><span class="identifier">_or</span><span class="plain"> ......</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_9_3"></a><b>§6.9.3. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Convert comma-divided rule into two sentences, if this is allowed</span> <span class="cwebmacronumber">6.9.3</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">sfsm_inside_rule_mode</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)</span>
|
|
<span class="plain">&& ((</span><span class="identifier">stop_character</span><span class="plain"> == </span><span class="character">'.'</span><span class="plain">) || (</span><span class="identifier">stop_character</span><span class="plain"> == </span><span class="character">'|'</span><span class="plain">))</span>
|
|
<span class="plain">&& (<</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">divisible</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">>(</span><span class="identifier">W</span><span class="plain">)))</span>
|
|
<<span class="cwebmacro">Look for a comma and split the sentence at it, unless in serial list</span> <span class="cwebmacronumber">6.9.3.1</span>><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6_9">§6.9</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_9_3_1"></a><b>§6.9.3.1. </b>In such sentences a comma is read as if it were a colon. (The text up to the
|
|
comma will then be given a <code class="display"><span class="extract">ROUTINE_NT</span></code> node and the text beyond the comma
|
|
will make a <code class="display"><span class="extract">INVOCATION_LIST_NT</span></code> node.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Look for a comma and split the sentence at it, unless in serial list</span> <span class="cwebmacronumber">6.9.3.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">earliest_comma_position</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">);</span>
|
|
<<span class="cwebmacro">Set earliest comma to position after the or, if there is one</span> <span class="cwebmacronumber">6.9.3.1.1</span>><span class="plain">;</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">AW</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">, </span><span class="identifier">BW</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">list</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">division</span><span class="plain">>(</span><span class="identifier">Wordings::from</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">earliest_comma_position</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">list</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">division</span><span class="plain">>, 1);</span>
|
|
<span class="identifier">BW</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(<</span><span class="identifier">list</span><span class="plain">-</span><span class="identifier">comma</span><span class="plain">-</span><span class="identifier">division</span><span class="plain">>, 2);</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">AW</span><span class="plain">)) {</span>
|
|
<span class="functiontext">Sentences::make_node</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">Wordings::up_to</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">AW</span><span class="plain">)), </span><span class="character">':'</span><span class="plain">); </span> <span class="comment">rule preamble stopped with a colon</span>
|
|
<span class="functiontext">Sentences::make_node</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">BW</span><span class="plain">, </span><span class="character">'.'</span><span class="plain">); </span> <span class="comment">rule body with one sentence, stopped with a stop</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6_9_3">§6.9.3</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_9_3_1_1"></a><b>§6.9.3.1.1. </b><code class="display">
|
|
<<span class="cwebmacrodefn">Set earliest comma to position after the or, if there is one</span> <span class="cwebmacronumber">6.9.3.1.1</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (<</span><span class="identifier">list</span><span class="plain">-</span><span class="identifier">or</span><span class="plain">-</span><span class="identifier">division</span><span class="plain">>(</span><span class="identifier">W</span><span class="plain">)) {</span>
|
|
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">BW</span><span class="plain"> = </span><span class="identifier">GET_RW</span><span class="plain">(<</span><span class="identifier">list</span><span class="plain">-</span><span class="identifier">or</span><span class="plain">-</span><span class="identifier">division</span><span class="plain">>, 2);</span>
|
|
<span class="identifier">earliest_comma_position</span><span class="plain"> = </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">BW</span><span class="plain">);</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6_9_3_1">§6.9.3.1</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_9_4"></a><b>§6.9.4. </b>At this point we know that the text <code class="display"><span class="extract">W</span></code> will make one and only
|
|
one sentence node in the parse tree, so we may as well create and ParseTree::graft it
|
|
now. There are a number of special cases with variant node types, but the
|
|
commonest outcome is a SENTENCE node, so that's what we shall assume for now.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Otherwise, make a SENTENCE node</span> <span class="cwebmacronumber">6.9.4</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">new</span><span class="plain"> = </span><span class="functiontext">ParseTree::new</span><span class="plain">(</span><span class="constant">SENTENCE_NT</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="constant">sentence_unparsed_ANNOT</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::insert_sentence</span><span class="plain">(</span><span class="identifier">T</span><span class="plain">, </span><span class="identifier">new</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6_9">§6.9</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_9_5"></a><b>§6.9.5. </b>Rules are sequences of phrases with a preamble in front, which we detect by
|
|
its terminating colon. For instance:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>To look upwards: say "Look out!"; something else.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">(which arrives at this routine as three separate "sentences") will produce
|
|
nodes with type <code class="display"><span class="extract">ROUTINE_NT</span></code>, <code class="display"><span class="extract">INVOCATION_LIST_NT</span></code> and <code class="display"><span class="extract">INVOCATION_LIST_NT</span></code> respectively.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">This paragraph of code might look as if it should only be used in assertion
|
|
mode, not in rule mode, because how can a rule preamble legally occur in
|
|
the middle of another rule? But in fact it can, in two ways. One is the
|
|
officially sanctioned way to make a definition with a complex phrase:
|
|
</p>
|
|
|
|
<blockquote>
|
|
<p>Definition: a supporter is wobbly: if the player is on it, decide yes; decide no.</p>
|
|
|
|
</blockquote>
|
|
|
|
<p class="inwebparagraph">This produces four nodes: <code class="display"><span class="extract">ROUTINE_NT</span></code>, <code class="display"><span class="extract">ROUTINE_NT</span></code>, <code class="display"><span class="extract">INVOCATION_LIST_NT</span></code> and
|
|
<code class="display"><span class="extract">INVOCATION_LIST_NT</span></code> respectively.
|
|
</p>
|
|
|
|
<p class="inwebparagraph">The other arises somewhat less officially when people treat phrases as
|
|
if they were C (or Inform 6) statements, always to be terminated with
|
|
semicolons, and also run two rules together with no skipped paragraph
|
|
between:
|
|
</p>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="plain">To do one thing: something here;</span>
|
|
<span class="plain">To do another thing: something else here;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph">A strict reading of our rules would oblige us to consider "To do another
|
|
thing:" as a phrase within the definition of "To do one thing", and
|
|
we would then have to issue a problem message. But this would be pettifogging.
|
|
(People who habitually shuffle phrases about in their editors tend not to
|
|
want to fuss about changing the punctuation of the last to a full stop
|
|
instead of a semicolon. We may lament this, but it is so.)
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Convert a rule preamble to a ROUTINE node and enter rule mode</span> <span class="cwebmacronumber">6.9.5</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">list_node_type</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stop_character</span><span class="plain"> == </span><span class="character">':'</span><span class="plain">) {</span>
|
|
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">sfsm_inside_rule_mode</span><span class="plain">) && (</span><span class="identifier">ControlStructures::detect</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">))) {</span>
|
|
<span class="functiontext">ParseTree::set_type</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="identifier">list_entry_node_type</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
|
|
<span class="functiontext">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="identifier">colon_block_command_ANNOT</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="identifier">sfsm_inside_rule_mode</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="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
|
|
<span class="functiontext">ParseTree::set_type</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="identifier">list_node_type</span><span class="plain">);</span>
|
|
<span class="identifier">sfsm_inside_rule_mode</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="plain">}</span>
|
|
<span class="plain">}</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6_9">§6.9</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_9_6"></a><b>§6.9.6. </b>Subsequent commands are divided by semicolons, and any failure of a
|
|
semicolon to appear indicates an end of the rule.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Convert to a COMMAND node and exit rule mode unless a semicolon implies further commands</span> <span class="cwebmacronumber">6.9.6</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">list_node_type</span>
|
|
<span class="functiontext">ParseTree::set_type</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="identifier">list_entry_node_type</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">stop_character</span><span class="plain"> != </span><span class="character">';'</span><span class="plain">) </span><span class="identifier">sfsm_inside_rule_mode</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6_9">§6.9</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_9_7"></a><b>§6.9.7. </b>Finally, we must tidy away the previously detected "begins here" and
|
|
"ends here" sentences into nodes on the tree.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Convert a begins here or ends here sentence to a BEGINHERE or ENDHERE node and return</span> <span class="cwebmacronumber">6.9.7</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">begins_or_ends</span><span class="plain"> == 1) {</span>
|
|
<span class="functiontext">ParseTree::set_type</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="constant">BEGINHERE_NT</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="identifier">Wordings::trim_last_word</span><span class="plain">(</span><span class="identifier">Wordings::trim_last_word</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)));</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">NEW_BEGINEND_HANDLER</span>
|
|
<span class="identifier">NEW_BEGINEND_HANDLER</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="identifier">sfsm_copy</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">begins_or_ends</span><span class="plain"> == -1) {</span>
|
|
<span class="functiontext">ParseTree::set_type</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="constant">ENDHERE_NT</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="identifier">Wordings::trim_last_word</span><span class="plain">(</span><span class="identifier">Wordings::trim_last_word</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)));</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">NEW_BEGINEND_HANDLER</span>
|
|
<span class="identifier">NEW_BEGINEND_HANDLER</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="identifier">sfsm_copy</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="reserved">return</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6_9">§6.9</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_9_8"></a><b>§6.9.8. </b>Why are we taking a sneak look at this sentence now? Because it affects
|
|
which headings we read the contents of. If we waited until sentence traverses,
|
|
it would be too late.
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Detect a language definition sentence and sneakily act upon it</span> <span class="cwebmacronumber">6.9.8</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">new</span><span class="plain">;</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">NEW_LANGUAGE_HANDLER</span>
|
|
<span class="identifier">NEW_LANGUAGE_HANDLER</span><span class="plain">(</span><span class="identifier">GET_RW</span><span class="plain">(<</span><span class="identifier">language</span><span class="plain">-</span><span class="identifier">modifying</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">>, 1));</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="functiontext">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="constant">language_element_ANNOT</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="constant">sentence_unparsed_ANNOT</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6_9">§6.9</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP6_9_9"></a><b>§6.9.9. </b>And for similar reasons:
|
|
</p>
|
|
|
|
|
|
<p class="macrodefinition"><code class="display">
|
|
<<span class="cwebmacrodefn">Detect a Preform grammar inclusion and sneakily act upon it</span> <span class="cwebmacronumber">6.9.9</span>> =
|
|
</code></p>
|
|
|
|
|
|
<pre class="displaydefn">
|
|
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">new</span><span class="plain">;</span>
|
|
<span class="identifier">Preform::parse_preform</span><span class="plain">(</span><span class="identifier">GET_RW</span><span class="plain">(<</span><span class="identifier">language</span><span class="plain">-</span><span class="identifier">modifying</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">>, 1), </span><span class="identifier">TRUE</span><span class="plain">);</span>
|
|
<span class="functiontext">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">new</span><span class="plain">, </span><span class="constant">sentence_unparsed_ANNOT</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">This code is used in <a href="#SP6_9">§6.9</a>.</p>
|
|
|
|
<p class="inwebparagraph"><a id="SP7"></a><b>§7. </b>Some tools using this module will want to push simple error messages out to
|
|
the command line; others will want to translate them into elaborate problem
|
|
texts in HTML. So the client is allowed to define <code class="display"><span class="extract">SYNTAX_PROBLEM_HANDLER</span></code>
|
|
to some routine of her own, gazumping this one.
|
|
</p>
|
|
|
|
|
|
<pre class="display">
|
|
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Sentences::syntax_problem</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">err_no</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">void</span><span class="plain"> *</span><span class="identifier">ref</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain">) {</span>
|
|
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">SYNTAX_PROBLEM_HANDLER</span>
|
|
<span class="identifier">SYNTAX_PROBLEM_HANDLER</span><span class="plain">(</span><span class="identifier">err_no</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">ref</span><span class="plain">, </span><span class="identifier">k</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="plain">#</span><span class="identifier">ifndef</span><span class="plain"> </span><span class="identifier">SYNTAX_PROBLEM_HANDLER</span>
|
|
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">text</span><span class="plain">);</span>
|
|
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">text</span><span class="plain">, </span><span class="string">"%+W"</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">err_no</span><span class="plain">) {</span>
|
|
<span class="reserved">case</span><span class="plain"> </span><span class="constant">UnexpectedSemicolon_SYNERROR</span><span class="plain">:</span>
|
|
<span class="identifier">Errors::with_text</span><span class="plain">(</span><span class="string">"unexpected semicolon in sentence: %S"</span><span class="plain">, </span><span class="identifier">text</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">ParaEndsInColon_SYNERROR</span><span class="plain">:</span>
|
|
<span class="identifier">Errors::with_text</span><span class="plain">(</span><span class="string">"paragraph ends with a colon: %S"</span><span class="plain">, </span><span class="identifier">text</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">SentenceEndsInColon_SYNERROR</span><span class="plain">:</span>
|
|
<span class="identifier">Errors::with_text</span><span class="plain">(</span><span class="string">"paragraph ends with a colon and full stop: %S"</span><span class="plain">, </span><span class="identifier">text</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">SentenceEndsInSemicolon_SYNERROR</span><span class="plain">:</span>
|
|
<span class="identifier">Errors::with_text</span><span class="plain">(</span><span class="string">"paragraph ends with a semicolon and full stop: %S"</span><span class="plain">, </span><span class="identifier">text</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">SemicolonAfterColon_SYNERROR</span><span class="plain">:</span>
|
|
<span class="identifier">Errors::with_text</span><span class="plain">(</span><span class="string">"paragraph ends with a colon and semicolon: %S"</span><span class="plain">, </span><span class="identifier">text</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">SemicolonAfterStop_SYNERROR</span><span class="plain">:</span>
|
|
<span class="identifier">Errors::with_text</span><span class="plain">(</span><span class="string">"paragraph ends with a full stop and semicolon: %S"</span><span class="plain">, </span><span class="identifier">text</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">ExtNoBeginsHere_SYNERROR</span><span class="plain">:</span>
|
|
<span class="identifier">Errors::nowhere</span><span class="plain">(</span><span class="string">"extension has no beginning"</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">ExtNoEndsHere_SYNERROR</span><span class="plain">:</span>
|
|
<span class="identifier">Errors::nowhere</span><span class="plain">(</span><span class="string">"extension has no end"</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">ExtSpuriouslyContinues_SYNERROR</span><span class="plain">:</span>
|
|
<span class="identifier">Errors::with_text</span><span class="plain">(</span><span class="string">"extension continues after end: %S"</span><span class="plain">, </span><span class="identifier">text</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">HeadingOverLine_SYNERROR</span><span class="plain">:</span>
|
|
<span class="identifier">Errors::with_text</span><span class="plain">(</span><span class="string">"heading contains a line break: %S"</span><span class="plain">, </span><span class="identifier">text</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">HeadingStopsBeforeEndOfLine_SYNERROR</span><span class="plain">:</span>
|
|
<span class="identifier">Errors::with_text</span><span class="plain">(</span><span class="string">"heading stops before end of line: %S"</span><span class="plain">, </span><span class="identifier">text</span><span class="plain">);</span>
|
|
<span class="reserved">break</span><span class="plain">;</span>
|
|
<span class="plain">}</span>
|
|
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">text</span><span class="plain">);</span>
|
|
<span class="plain">#</span><span class="identifier">endif</span>
|
|
<span class="plain">}</span>
|
|
</pre>
|
|
|
|
<p class="inwebparagraph"></p>
|
|
|
|
<p class="endnote">The function Sentences::syntax_problem is used in <a href="#SP5_4_1">§5.4.1</a>, <a href="#SP5_4_2">§5.4.2</a>, <a href="#SP5_4_3">§5.4.3</a>, <a href="#SP5_4_4">§5.4.4</a>, <a href="#SP5_4_5">§5.4.5</a>, <a href="#SP6_2">§6.2</a>, <a href="#SP6_4">§6.4</a>, <a href="#SP6_5">§6.5</a>, <a href="#SP5_5">§5.5</a>, <a href="#SP6_9">§6.9</a>.</p>
|
|
|
|
<hr class="tocbar">
|
|
<ul class="toc"><li><a href="2-pt.html">Back to 'Parse Tree'</a></li><li><i>(This section ends Chapter 2: The Parse Tree.)</i></li></ul><hr class="tocbar">
|
|
<!--End of weave-->
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|