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

571 lines
63 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>10/varc</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 '10/cap' 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">core</a></li><li><a href="index.html#10">Chapter 10: The S-Parser</a></li><li><b>Conditions and Phrases</b></li></ul><p class="purpose">To parse the text of To... phrases, say phrases and conditions.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Conditions</a></li><li><a href="#SP9">&#167;9. Command phrases</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Conditions. </b>A condition is an excerpt of text which measures the truth of something.
We will call a condition "pure" if it is self-sufficient, rather than
referring anaphorically to some implied subject. For instance,
</p>
<blockquote>
<p>if the bucket is an open container, ...</p>
</blockquote>
<p class="inwebparagraph">contains a pure condition, but
</p>
<blockquote>
<p>if an open container, ...</p>
</blockquote>
<p class="inwebparagraph">is impure. We are very wary of impure conditions, and don't allow the
logical operations or chronological restrictions to apply to them. So the
only valid impure conditions are description noun phrases.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">uncached</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">pure</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">descriptive</span><span class="plain">-</span><span class="identifier">np</span><span class="plain">&gt; ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>Now for pure conditions. Note that logical "and" and "or" are implemented
directly right here, rather than being phrases defined in the Standard Rules,
and that they aren't the same as the "and" and "or" used a list dividers.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">pure</span><span class="plain">&gt; ::=</span>
<span class="plain">( &lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">pure</span><span class="plain">&gt; ) | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">pure</span><span class="plain">&gt; , </span><span class="identifier">and</span><span class="plain"> &lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">pure</span><span class="plain">&gt; | ==&gt; </span><span class="functiontext">Conditions::new_LOGICAL_AND</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1], </span><span class="identifier">RP</span><span class="plain">[2])</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">pure</span><span class="plain">&gt; </span><span class="identifier">and</span><span class="plain"> &lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">pure</span><span class="plain">&gt; | ==&gt; </span><span class="functiontext">Conditions::new_LOGICAL_AND</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1], </span><span class="identifier">RP</span><span class="plain">[2])</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">pure</span><span class="plain">&gt; , </span><span class="identifier">or</span><span class="plain"> &lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">pure</span><span class="plain">&gt; | ==&gt; </span><span class="functiontext">Conditions::new_LOGICAL_OR</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1], </span><span class="identifier">RP</span><span class="plain">[2])</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">pure</span><span class="plain">&gt; </span><span class="identifier">or</span><span class="plain"> &lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">pure</span><span class="plain">&gt; | ==&gt; </span><span class="functiontext">Conditions::new_LOGICAL_OR</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1], </span><span class="identifier">RP</span><span class="plain">[2])</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">with</span><span class="plain">-</span><span class="identifier">chronology</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">atomic</span><span class="plain">&gt; ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Chronological restrictions include, for instance,
</p>
<blockquote>
<p>if the gate is open for the first time, ...</p>
</blockquote>
<p class="inwebparagraph">where the condition is divided as
</p>
<blockquote>
<p>if the gate is open / for the first time</p>
</blockquote>
<p class="inwebparagraph">and &lt;s-condition-atomic&gt; is used to parse the first half. While it's possible
to express this in Preform grammar, the result doesn't run quickly, so I've
implemented this as a hand-coded nonterminal instead.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">with</span><span class="plain">-</span><span class="identifier">chronology</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
<span class="identifier">time_period</span><span class="plain"> </span><span class="identifier">tp</span><span class="plain"> = </span><span class="identifier">Occurrence::parse</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">end_of_non_time_part</span><span class="plain"> = </span><span class="identifier">Occurrence::is_valid</span><span class="plain">(&amp;</span><span class="identifier">tp</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">end_of_non_time_part</span><span class="plain"> &gt;= </span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">atomic</span><span class="plain">&gt;(</span><span class="identifier">Wordings::up_to</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">end_of_non_time_part</span><span class="plain">)))) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">atomic_cnd</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">atomic_cnd</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="constant">CONSTANT_NT</span><span class="plain">)) {</span>
<span class="identifier">action_pattern</span><span class="plain"> *</span><span class="identifier">ap</span><span class="plain"> = </span><span class="functiontext">Rvalues::to_action_pattern</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="identifier">spec</span><span class="plain"> = </span><span class="functiontext">Conditions::new_TEST_ACTION</span><span class="plain">(</span><span class="identifier">ap</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">*</span><span class="identifier">XP</span><span class="plain"> = </span><span class="functiontext">Conditions::attach_historic_requirement</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">,</span>
<span class="identifier">Occurrence::store</span><span class="plain">(</span><span class="identifier">tp</span><span class="plain">));</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</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="SP4"></a><b>&#167;4. </b>The syntax for the logical operation "not" is more complicated, because
it only sometimes work by simply preceding the text with "not". Consider
this, for instance:
</p>
<blockquote>
<p>if not we are carrying the torch, ...</p>
</blockquote>
<p class="inwebparagraph">As a result, we can't handle negation in &lt;s-condition-pure&gt;, and have to
work into the grammar below on a case by case basis. And where we do allow
"not", we always check the positive sense first &mdash; people do sometimes
create phrase options like "not printing anything", for example, which
begin with the word "not".
</p>
<p class="inwebparagraph">As a condition, an action pattern is implicitly considered as a test of
what the current action is:
</p>
<blockquote>
<p>if examining an open door, ...</p>
</blockquote>
<p class="inwebparagraph">This wouldn't work so well for the past tense form:
</p>
<blockquote>
<p>if examined an open door, ...</p>
</blockquote>
<p class="inwebparagraph">because it seems too clunky as neither quite active nor passive. Who examined
the open door? So Inform uses the following version instead:
</p>
<blockquote>
<p>if we have examined an open door, ...</p>
</blockquote>
<p class="inwebparagraph">thus adopting the "science we". Not very elegant, but the alternatives were
difficult to parse. "We are" is allowed for consistency's sake, but does
nothing, i.e., "we are taking" and "taking" are synonymous. Translators
to other languages may want to find more elegant solutions.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">-</span><span class="identifier">atomic</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">in</span><span class="plain">-</span><span class="identifier">use</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="identifier">not</span><span class="plain"> &lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">in</span><span class="plain">-</span><span class="identifier">use</span><span class="plain">&gt; | ==&gt; </span><span class="functiontext">Conditions::negate</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1])</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">nonexistential</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">to</span><span class="plain">-</span><span class="identifier">decide</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">past</span><span class="plain">-</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</span><span class="plain">-</span><span class="identifier">as</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">past</span><span class="plain">-</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</span><span class="plain">-</span><span class="identifier">as</span><span class="plain">-</span><span class="identifier">negated</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt; | ==&gt; </span><span class="functiontext">Conditions::negate</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1])</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</span><span class="plain">-</span><span class="identifier">as</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</span><span class="plain">-</span><span class="identifier">as</span><span class="plain">-</span><span class="identifier">negated</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt; | ==&gt; </span><span class="functiontext">Conditions::negate</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1])</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">sentence</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">existential</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">to</span><span class="plain">-</span><span class="identifier">decide</span><span class="plain">&gt; ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>As before, we try to get better sensitivity to ambiguities by dividing the
test for a phrase-to-decide into two, so that the following is used at a
different point if the excerpt begins "there is" than if it doesn't. The
point of this is that some phrases to decide have wording which coincides
with a description, and in general the phrase should win, but in the case
of "there is" we make the presumption that the author intends a sentence
testing the existence of something.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">nonexistential</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">to</span><span class="plain">-</span><span class="identifier">decide</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">existential</span><span class="plain">-</span><span class="identifier">verb</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">NULL</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FAIL_NONTERMINAL</span><span class="plain">;</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">to</span><span class="plain">-</span><span class="identifier">decide</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="identifier">not</span><span class="plain"> &lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">to</span><span class="plain">-</span><span class="identifier">decide</span><span class="plain">&gt; ==&gt; </span><span class="functiontext">Conditions::negate</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1])</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">existential</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">to</span><span class="plain">-</span><span class="identifier">decide</span><span class="plain">&gt; ::=</span>
<span class="plain">^&lt;</span><span class="identifier">existential</span><span class="plain">-</span><span class="identifier">verb</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">NULL</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FAIL_NONTERMINAL</span><span class="plain">;</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">to</span><span class="plain">-</span><span class="identifier">decide</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="identifier">not</span><span class="plain"> &lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">to</span><span class="plain">-</span><span class="identifier">decide</span><span class="plain">&gt; ==&gt; </span><span class="functiontext">Conditions::negate</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1])</span>
<span class="plain">&lt;</span><span class="identifier">existential</span><span class="plain">-</span><span class="identifier">verb</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">existential</span><span class="plain">-</span><span class="identifier">np</span><span class="plain">&gt; </span><span class="identifier">is</span><span class="plain">/</span><span class="identifier">are</span><span class="plain"> ...</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">to</span><span class="plain">-</span><span class="identifier">decide</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">ExParser::parse_excerpt</span><span class="plain">(</span><span class="constant">COND_PHRASE_MC</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">p</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">ParseTree::new_with_words</span><span class="plain">(</span><span class="constant">PHRASE_TO_DECIDE_VALUE_NT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">ExParser::add_ilist</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">tval</span><span class="plain"> = </span><span class="identifier">ParseTree::new_with_words</span><span class="plain">(</span><span class="constant">TEST_VALUE_NT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">tval</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="identifier">spec</span><span class="plain">;</span>
<span class="plain">*</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">tval</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">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"></a><b>&#167;6. </b>The following only matches the phrase option names for the phrase currently
being compiled; all others are out of scope.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">in</span><span class="plain">-</span><span class="identifier">use</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phrase_being_compiled</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="functiontext">Routines::ToPhrases::parse_phrase_option_used</span><span class="plain">(</span><span class="identifier">phrase_being_compiled</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">i</span><span class="plain"> &gt;= </span><span class="constant">0</span><span class="plain">) {</span>
<span class="plain">*</span><span class="identifier">XP</span><span class="plain"> = </span><span class="functiontext">Conditions::new_TEST_PHRASE_OPTION</span><span class="plain">(</span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">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="SP7"></a><b>&#167;7. </b>We have already seen action patterns used as nouns; here they are used as
conditions, so this is where the condition in
</p>
<blockquote>
<p>if taking the box, ...</p>
</blockquote>
<p class="inwebparagraph">is handled. The following nonterminal exists to enter the AP to the meaning list.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</span><span class="plain">-</span><span class="identifier">as</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">we</span><span class="plain">-</span><span class="identifier">are</span><span class="plain">-</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</span><span class="plain">&gt; ==&gt; </span><span class="functiontext">Conditions::new_TEST_ACTION</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1], </span><span class="identifier">W</span><span class="plain">);</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</span><span class="plain">-</span><span class="identifier">as</span><span class="plain">-</span><span class="identifier">negated</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</span><span class="plain">-</span><span class="identifier">negated</span><span class="plain">&gt; ==&gt; </span><span class="functiontext">Conditions::new_TEST_ACTION</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1], </span><span class="identifier">W</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>And similarly:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">past</span><span class="plain">-</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</span><span class="plain">-</span><span class="identifier">as</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</span><span class="plain">-</span><span class="identifier">past</span><span class="plain">&gt; ==&gt; </span>&lt;<span class="cwebmacro">Convert stored past action pattern to condition node</span> <span class="cwebmacronumber">8.1</span>&gt;
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">past</span><span class="plain">-</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</span><span class="plain">-</span><span class="identifier">as</span><span class="plain">-</span><span class="identifier">negated</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">pattern</span><span class="plain">-</span><span class="identifier">past</span><span class="plain">-</span><span class="identifier">negated</span><span class="plain">&gt; ==&gt; </span>&lt;<span class="cwebmacro">Convert stored past action pattern to condition node</span> <span class="cwebmacronumber">8.1</span>&gt;
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP8_1"></a><b>&#167;8.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Convert stored past action pattern to condition node</span> <span class="cwebmacronumber">8.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
<span class="identifier">action_pattern</span><span class="plain"> *</span><span class="identifier">ap</span><span class="plain"> = </span><span class="identifier">RP</span><span class="plain">[1];</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">PL::Actions::Patterns::makes_callings</span><span class="plain">(</span><span class="identifier">ap</span><span class="plain">)) {</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_PastActionCalled</span><span class="plain">),</span>
<span class="string">"a description of an action cannot both refer to past "</span>
<span class="string">"history and also use '(called ...)'"</span><span class="plain">,</span>
<span class="string">"because that would require Inform in general to remember "</span>
<span class="string">"too much information about past events."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">*</span><span class="identifier">XP</span><span class="plain"> = </span><span class="functiontext">Conditions::new_TEST_ACTION</span><span class="plain">(</span><span class="identifier">ap</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="plain">*</span><span class="identifier">XP</span><span class="plain"> = </span><span class="functiontext">Conditions::attach_tense</span><span class="plain">(*</span><span class="identifier">XP</span><span class="plain">, </span><span class="identifier">HASBEEN_TENSE</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">IF_MODULE</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">#</span><span class="identifier">endif</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a> (twice).</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Command phrases. </b>The final clutch of nonterminals in the S-grammar handles individual commands,
written in their semicolon-divided list in the body of a rule or "To..."
definition. For instance, in the not very sensible rule:
</p>
<blockquote>
<p>Instead of jumping: now the score is 10; say "Greetings!" instead.</p>
</blockquote>
<p class="inwebparagraph">Inform will use &lt;s-command&gt; to parse the text of the two commands in the rule
body. &lt;s-command&gt; parses the text with little attempt to judge whether the
parameters of the phrase match; it simply records possibilities for
typechecking to choose between much later on.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">command</span><span class="plain">&gt; ::=</span>
<span class="plain">( &lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">command</span><span class="plain">&gt; ) | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">to</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt; ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">say</span><span class="plain">-</span><span class="identifier">command</span><span class="plain">&gt; ::=</span>
<span class="plain">( &lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">say</span><span class="plain">-</span><span class="identifier">command</span><span class="plain">&gt; ) | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">adaptive</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">substitution</span><span class="plain">&gt; ==&gt; </span><span class="identifier">RP</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">adaptive</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">local</span><span class="plain">-</span><span class="identifier">variable</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">NULL</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FAIL_NONTERMINAL</span>
<span class="plain">&lt;</span><span class="identifier">adaptive</span><span class="plain">-</span><span class="identifier">verb</span><span class="plain">&gt; </span><span class="identifier">verb</span><span class="plain"> | ==&gt; </span><span class="functiontext">ExParser::say_verb</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1], </span><span class="identifier">R</span><span class="plain">[1], </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">)</span>
<span class="plain">&lt;</span><span class="identifier">adaptive</span><span class="plain">-</span><span class="identifier">adjective</span><span class="plain">&gt; </span><span class="identifier">adjective</span><span class="plain"> | ==&gt; </span><span class="functiontext">ExParser::say_adjective</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1], </span><span class="identifier">W</span><span class="plain">)</span>
<span class="plain">&lt;</span><span class="identifier">adaptive</span><span class="plain">-</span><span class="identifier">verb</span><span class="plain">&gt; | ==&gt; </span><span class="functiontext">ExParser::say_verb</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1], </span><span class="identifier">R</span><span class="plain">[1], </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">)</span>
<span class="plain">&lt;</span><span class="identifier">modal</span><span class="plain">-</span><span class="identifier">verb</span><span class="plain">&gt; &lt;</span><span class="identifier">adaptive</span><span class="plain">-</span><span class="identifier">verb</span><span class="plain">-</span><span class="identifier">infinitive</span><span class="plain">&gt; </span><span class="identifier">verb</span><span class="plain"> | ==&gt; </span>&lt;<span class="cwebmacro">Annotate the verb with a modal</span> <span class="cwebmacronumber">9.3</span>&gt;
<span class="plain">&lt;</span><span class="identifier">modal</span><span class="plain">-</span><span class="identifier">verb</span><span class="plain">&gt; &lt;</span><span class="identifier">adaptive</span><span class="plain">-</span><span class="identifier">verb</span><span class="plain">-</span><span class="identifier">infinitive</span><span class="plain">&gt; | ==&gt; </span>&lt;<span class="cwebmacro">Annotate the verb with a modal</span> <span class="cwebmacronumber">9.3</span>&gt;
<span class="plain">&lt;</span><span class="identifier">adaptive</span><span class="plain">-</span><span class="identifier">adjective</span><span class="plain">&gt; ==&gt; </span><span class="functiontext">ExParser::say_adjective</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[1], </span><span class="identifier">W</span><span class="plain">)</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP9_1"></a><b>&#167;9.1. </b>"To..." phrases are easy, or at least, easy to delegate:
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">to</span><span class="plain">-</span><span class="reserved">phrase</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">ExParser::parse_excerpt</span><span class="plain">(</span><span class="constant">VOID_PHRASE_MC</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">p</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">ParseTree::new_with_words</span><span class="plain">(</span><span class="constant">PHRASE_TO_DECIDE_VALUE_NT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">ExParser::add_ilist</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">*</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">spec</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">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="SP9_2"></a><b>&#167;9.2. </b></p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">text</span><span class="plain">-</span><span class="identifier">substitution</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">ExParser::parse_excerpt</span><span class="plain">(</span><span class="constant">SAY_PHRASE_MC</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">p</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">ParseTree::new_with_words</span><span class="plain">(</span><span class="constant">PHRASE_TO_DECIDE_VALUE_NT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">ExParser::add_ilist</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="plain">*</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">spec</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">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="SP9_3"></a><b>&#167;9.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Annotate the verb with a modal</span> <span class="cwebmacronumber">9.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">neg</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">R</span><span class="plain">[1]) || (</span><span class="identifier">R</span><span class="plain">[2])) </span><span class="identifier">neg</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">*</span><span class="identifier">XP</span><span class="plain"> = </span><span class="functiontext">ExParser::say_verb</span><span class="plain">(</span><span class="identifier">RP</span><span class="plain">[2], </span><span class="identifier">neg</span><span class="plain">, </span><span class="identifier">RP</span><span class="plain">[1], </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="#SP9">&#167;9</a> (twice).</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. </b>Invocation nodes for adaptive-text adjectives hold references to their masculine
singulars.
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">ExParser::say_adjective</span><span class="plain">(</span><span class="identifier">adjectival_phrase</span><span class="plain"> *</span><span class="identifier">aph</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">ParseTree::new_with_words</span><span class="plain">(</span><span class="constant">PHRASE_TO_DECIDE_VALUE_NT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain"> = </span><span class="functiontext">Invocations::new</span><span class="plain">();</span>
<span class="functiontext">Invocations::set_word_range</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">Invocations::set_adjectival_phrase</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">aph</span><span class="plain">);</span>
<span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="identifier">INVOCATION_LIST_NT</span><span class="plain">);</span>
<span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="functiontext">Invocations::add_to_list</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">spec</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ExParser::say_adjective is used in <a href="#SP9">&#167;9</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>Invocation nodes for adaptive-text verbs hold references to their first
person plurals.
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">ExParser::say_verb</span><span class="plain">(</span><span class="identifier">verb_conjugation</span><span class="plain"> *</span><span class="identifier">vc</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">neg</span><span class="plain">, </span><span class="identifier">verb_conjugation</span><span class="plain"> *</span><span class="identifier">mvc</span><span class="plain">, </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">W</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">ParseTree::new_with_words</span><span class="plain">(</span><span class="constant">PHRASE_TO_DECIDE_VALUE_NT</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain"> = </span><span class="functiontext">Invocations::new</span><span class="plain">();</span>
<span class="functiontext">Invocations::set_word_range</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">Invocations::set_verb_conjugation</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">vc</span><span class="plain">, </span><span class="identifier">mvc</span><span class="plain">, </span><span class="identifier">neg</span><span class="plain">);</span>
<span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="identifier">INVOCATION_LIST_NT</span><span class="plain">);</span>
<span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="functiontext">Invocations::add_to_list</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">spec</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ExParser::say_verb is used in <a href="#SP9">&#167;9</a>, <a href="#SP9_3">&#167;9.3</a>.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>There are three basic kinds of phrase: those used as commands
(i.e., void procedures in C terms), those used as values (returning values
other than true/false) and those used as conditions (returning true or false).
These are stored in a way making basically the same use of a specification's
references, so all three are handled by the following code.
</p>
<p class="inwebparagraph">The usage of a phrase is called an "invocation" of it, and sometimes more than
one invocation appears, for two reasons: a "say" phrase can contain a sequence
of invocations to follow, one after another; and sometimes it will only be clear
at run-time which of several possible definitions is to apply, so the
possibilities will all be invoked.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">ExParser::add_ilist</span><span class="plain">(</span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">p</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Build the invocation list</span> <span class="cwebmacronumber">12.1</span>&gt;<span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">len</span><span class="plain"> = </span><span class="functiontext">Invocations::length_of_list</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">len</span><span class="plain"> &gt;= </span><span class="constant">MAX_INVOCATIONS_PER_PHRASE</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Issue overcomplicated phrase problem message</span> <span class="cwebmacronumber">12.2</span>&gt;
<span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">len</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">)</span>
<span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="functiontext">Invocations::sort_list</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function ExParser::add_ilist is used in <a href="#SP5">&#167;5</a>, <a href="#SP9_1">&#167;9.1</a>, <a href="#SP9_2">&#167;9.2</a>, 10/teav (<a href="10-teav.html#SP20">&#167;20</a>).</p>
<p class="inwebparagraph"><a id="SP12_1"></a><b>&#167;12.1. </b>There are multiple invocations, each produced from another node in the
S-tree as we run sideways through the alternative readings.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Build the invocation list</span> <span class="cwebmacronumber">12.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">p</span><span class="plain">; </span><span class="identifier">p</span><span class="plain"> = </span><span class="identifier">p</span><span class="plain">-&gt;</span><span class="identifier">next_alternative</span><span class="plain">) {</span>
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph</span><span class="plain"> = </span><span class="identifier">RETRIEVE_POINTER_phrase</span><span class="plain">(</span>
<span class="identifier">ExcerptMeanings::data</span><span class="plain">(</span><span class="identifier">ParseTree::get_meaning</span><span class="plain">(</span><span class="identifier">p</span><span class="plain">)));</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">inv</span><span class="plain"> = </span><span class="functiontext">Phrases::Parser::parse_against</span><span class="plain">(</span><span class="identifier">ph</span><span class="plain">, </span><span class="identifier">p</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">Phrases::TypeData::is_the_primordial_say</span><span class="plain">(&amp;(</span><span class="identifier">ph</span><span class="plain">-&gt;</span><span class="element">type_data</span><span class="plain">)) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">Rvalues::is_CONSTANT_of_kind</span><span class="plain">(</span>
<span class="functiontext">Invocations::get_token_as_parsed</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="constant">0</span><span class="plain">), </span><span class="identifier">K_text</span><span class="plain">)))</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spec</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="identifier">ParseTree::new</span><span class="plain">(</span><span class="identifier">INVOCATION_LIST_NT</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain"> = </span><span class="functiontext">Invocations::add_to_list</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">, </span><span class="identifier">inv</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP12_2"></a><b>&#167;12.2. </b>This problem used to be experienced for long say phrases in a situation
where many kinds of value have been created, so that "say V" for a value V
was heavily ambiguous &mdash; pumping up the number of invocations generated. In
2010, the introduction of generics into Inform made it possible to define
"say V" just once, and after that it became so difficult to reach this
limit that we were unable to construct a test case for it.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Issue overcomplicated phrase problem message</span> <span class="cwebmacronumber">12.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">spec</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">down</span><span class="plain">-&gt;</span><span class="element">next</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="comment">truncate to just one</span>
<span class="identifier">ParseTree::set_text</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">current_sentence</span><span class="plain">));</span>
<span class="identifier">Problems::quote_source</span><span class="plain">(1, </span><span class="identifier">current_sentence</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="functiontext">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">BelievedImpossible</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"In %1, the phrase being constructed is just too "</span>
<span class="string">"long and complicated, and will need to be simplified. (This "</span>
<span class="string">"sometimes happens with a 'say', or a piece of text, containing "</span>
<span class="string">"many text substitutions in succession: if so, it may be worth "</span>
<span class="string">"defining some more powerful text substitutions - for instance "</span>
<span class="string">"writing 'To say super-duper: ...', giving the gory details, "</span>
<span class="string">"and then using the single substitution '[super-duper]' in the "</span>
<span class="string">"original phrase."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP12">&#167;12</a>.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="10-varc.html">Back to 'Verbal and Relative Clauses'</a></li><li><i>(This section ends Chapter 10: The S-Parser.)</i></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>