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/22-po.html
2020-04-07 01:06:09 +01:00

467 lines
46 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>22/dptd</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 '22/po' 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#22">Chapter 22: Phrases</a></li><li><b>Phrase Options</b></li></ul><p class="purpose">To create and subsequently parse against the list of phrase options with which the user can choose to invoke a To phrase.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP4">&#167;4. Creation</a></li><li><a href="#SP5">&#167;5. Parsing</a></li><li><a href="#SP6">&#167;6. Indexing</a></li><li><a href="#SP7">&#167;7. Parsing phrase options in a declaration</a></li><li><a href="#SP10">&#167;10. Parsing phrase options in an invocation</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Definitions. </b></p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. </b>A "phrase option" is a sort of modifier tacked on to the instruction to
do something, changing how it works but not enough to merit an entirely new
phrase. It's like an argument passed to a routine which specifies optional
behaviour, and indeed that will be how it is compiled.
</p>
<p class="inwebparagraph">Like the token names, phrase option names have local scope (which is why
they are here and not in the excerpts database). Unlike them, they are not
valid as values, since a condition is not also a value in Inform 7.
</p>
<p class="inwebparagraph">The packet of these associated with a phrase is stored in the PHOD structure.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_OPTIONS_PER_PHRASE</span><span class="plain"> </span><span class="constant">16</span><span class="plain"> </span><span class="comment">because held in a 16-bit Z-machine bitmap</span>
</pre>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">ph_options_data</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">phrase_option</span><span class="plain"> *</span><span class="identifier">options_permitted</span><span class="plain">[</span><span class="constant">MAX_OPTIONS_PER_PHRASE</span><span class="plain">]; </span><span class="comment">see below</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">no_options_permitted</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">options_declaration</span><span class="plain">; </span><span class="comment">the text declaring the whole set of options</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">multiple_options_permitted</span><span class="plain">; </span><span class="comment">can be combined, or mutually exclusive?</span>
<span class="plain">} </span><span class="reserved">ph_options_data</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure ph_options_data is private to this section.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>There's nothing to a phrase option, really:
</p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">phrase_option</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">name</span><span class="plain">; </span><span class="comment">text of name</span>
<span class="plain">} </span><span class="reserved">phrase_option</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure phrase_option is accessed in 2/sq, 2/si, 5/ins, 5/nv, 8/ef, 9/ma, 9/pk, 11/sm, 14/lv, 14/ds2, 15/pr, 15/ep, 15/vp, 15/spr, 16/in, 16/cmw, 17/rs, 19/tc, 19/tb, 19/tod, 20/eq, 21/rl, 21/rl2, 21/fao, 21/rps, 21/sv, 21/ac, 22/pu, 22/dptd, 22/pav, 25/cii, 26/uo, 26/ts and here.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. Creation. </b>By default, a phrase has no options.
</p>
<pre class="display">
<span class="reserved">ph_options_data</span><span class="plain"> </span><span class="functiontext">Phrases::Options::new</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">ph_options_data</span><span class="plain"> </span><span class="identifier">phod</span><span class="plain">;</span>
<span class="identifier">phod</span><span class="plain">.</span><span class="element">no_options_permitted</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="identifier">phod</span><span class="plain">.</span><span class="element">multiple_options_permitted</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">phod</span><span class="plain">.</span><span class="element">options_declaration</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">phod</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::Options::allows_options</span><span class="plain">(</span><span class="reserved">ph_options_data</span><span class="plain"> *</span><span class="identifier">phod</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phod</span><span class="plain">-&gt;</span><span class="identifier">no_options_permitted</span><span class="plain"> &gt; </span><span class="constant">0</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Options::new is used in <a href="#SP7">&#167;7</a>.</p>
<p class="endnote">The function Phrases::Options::allows_options is used in 22/ph (<a href="22-ph.html#SP6_5">&#167;6.5</a>), 22/tp (<a href="22-tp.html#SP12">&#167;12</a>).</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. Parsing. </b>This isn't very efficient, but doesn't need to be, since phrase options
are parsed only in a condition context, not in a value context, and
these are relatively rare in Inform source text.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::Options::parse</span><span class="plain">(</span><span class="reserved">ph_options_data</span><span class="plain"> *</span><span class="identifier">phod</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">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">; </span><span class="identifier">i</span><span class="plain"> &lt; </span><span class="identifier">phod</span><span class="plain">-&gt;</span><span class="element">no_options_permitted</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::match</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">phod</span><span class="plain">-&gt;</span><span class="element">options_permitted</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">]-&gt;</span><span class="element">name</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> (1 &lt;&lt; </span><span class="identifier">i</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> -1;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Options::parse is used in <a href="#SP12">&#167;12</a>, 22/tp (<a href="22-tp.html#SP12">&#167;12</a>).</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Indexing. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Options::index</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">ph_options_data</span><span class="plain"> *</span><span class="identifier">phod</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;</span><span class="identifier">phod</span><span class="plain">-&gt;</span><span class="element">no_options_permitted</span><span class="plain">; </span><span class="identifier">i</span><span class="plain">++) {</span>
<span class="reserved">phrase_option</span><span class="plain"> *</span><span class="identifier">po</span><span class="plain"> = </span><span class="identifier">phod</span><span class="plain">-&gt;</span><span class="element">options_permitted</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">];</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">==0) {</span>
<span class="identifier">HTML_TAG</span><span class="plain">(</span><span class="string">"br"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;i&gt;optionally&lt;/i&gt; "</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> == </span><span class="identifier">phod</span><span class="plain">-&gt;</span><span class="element">no_options_permitted</span><span class="plain">-1) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phod</span><span class="plain">-&gt;</span><span class="identifier">multiple_options_permitted</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;i&gt;and/or&lt;/i&gt; "</span><span class="plain">);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;i&gt;or&lt;/i&gt; "</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">HTML::Javascript::paste_W</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">po</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;nbsp;%+W"</span><span class="plain">, </span><span class="identifier">po</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> &lt; </span><span class="identifier">phod</span><span class="plain">-&gt;</span><span class="element">no_options_permitted</span><span class="plain">-1) {</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">","</span><span class="plain">);</span>
<span class="identifier">HTML_TAG</span><span class="plain">(</span><span class="string">"br"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"\n"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Options::index is used in 22/dptd (<a href="22-dptd.html#SP6">&#167;6</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Parsing phrase options in a declaration. </b></p>
<pre class="display">
<span class="reserved">ph_options_data</span><span class="plain"> *</span><span class="identifier">phod_being_parsed</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">phrase</span><span class="plain"> *</span><span class="identifier">ph_being_parsed</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">ph_options_data</span><span class="plain"> </span><span class="functiontext">Phrases::Options::parse_declared_options</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">ph_options_data</span><span class="plain"> </span><span class="identifier">phod</span><span class="plain"> = </span><span class="functiontext">Phrases::Options::new</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::nonempty</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="identifier">phod_being_parsed</span><span class="plain"> = &amp;</span><span class="identifier">phod</span><span class="plain">;</span>
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">declaration</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (&lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt;) </span><span class="identifier">phod</span><span class="plain">.</span><span class="element">multiple_options_permitted</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">phod</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Options::parse_declared_options is used in 22/ph (<a href="22-ph.html#SP6_4">&#167;6.4</a>).</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>I have to say that I regret the syntax for phrase options, which makes
us write commas like the one here:
</p>
<blockquote>
<p>let R be the best route from X to Y, using doors;</p>
</blockquote>
<p class="inwebparagraph">I sometimes even regret the existence of phrase options, but it must be
admitted that they are a clean way to interface to low-level Inform 6 code.
But it's mostly the comma which annoys me (making text substitutions unable
to support phrase options); I should have gone for brackets.
</p>
<p class="inwebparagraph">The syntax for declaring phrase options is uncontroversial &mdash; it's just
a list of names &mdash; but there are wrinkles: if the list is divided with "or"
then the options are mutually exclusive, but with "and/or" they're not.
For example, in:
</p>
<blockquote>
<p>To decide which object is best route from (R1 - object) to (R2 - object), using doors or using even locked doors: ...</p>
</blockquote>
<p class="inwebparagraph">the following parses this list:
</p>
<blockquote>
<p>using doors or using even locked doors</p>
</blockquote>
<p class="inwebparagraph">and creates two options with &lt;phrase-option-declaration-setting-entry&gt;.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">declaration</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; ::=</span>
<span class="plain">... | ==&gt; </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">preform_lookahead_mode</span><span class="plain">; </span><span class="comment">match only when looking ahead</span>
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">declaration</span><span class="plain">-</span><span class="identifier">setting</span><span class="plain">-</span><span class="identifier">entry</span><span class="plain">&gt; &lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">declaration</span><span class="plain">-</span><span class="identifier">tail</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">R</span><span class="plain">[2]</span>
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">declaration</span><span class="plain">-</span><span class="identifier">setting</span><span class="plain">-</span><span class="identifier">entry</span><span class="plain">&gt; ==&gt; </span><span class="identifier">FALSE</span>
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">declaration</span><span class="plain">-</span><span class="identifier">tail</span><span class="plain">&gt; ::=</span>
<span class="plain">, </span><span class="identifier">_or</span><span class="plain"> &lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">declaration</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
<span class="plain">, \</span><span class="identifier">and</span><span class="plain">/</span><span class="identifier">or</span><span class="plain"> &lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">declaration</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">TRUE</span>
<span class="identifier">_</span><span class="plain">,/</span><span class="identifier">or</span><span class="plain"> &lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">declaration</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
<span class="plain">\</span><span class="identifier">and</span><span class="plain">/</span><span class="identifier">or</span><span class="plain"> &lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">declaration</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; ==&gt; </span><span class="identifier">TRUE</span>
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">declaration</span><span class="plain">-</span><span class="identifier">setting</span><span class="plain">-</span><span class="identifier">entry</span><span class="plain">&gt; ::=</span>
<span class="plain">... ==&gt; </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="reserved">if</span><span class="plain"> (!</span><span class="identifier">preform_lookahead_mode</span><span class="plain">) </span><span class="functiontext">Phrases::Options::phod_add_phrase_option</span><span class="plain">(</span><span class="identifier">phod_being_parsed</span><span class="plain">, </span><span class="identifier">W</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b></p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">too_many_POs_error</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Phrases::Options::phod_add_phrase_option</span><span class="plain">(</span><span class="reserved">ph_options_data</span><span class="plain"> *</span><span class="identifier">phod</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">LOGIF</span><span class="plain">(</span><span class="identifier">PHRASE_CREATIONS</span><span class="plain">, </span><span class="string">"Adding phrase option &lt;%W&gt;\n"</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">phod</span><span class="plain">-&gt;</span><span class="identifier">no_options_permitted</span><span class="plain"> &gt;= </span><span class="constant">MAX_OPTIONS_PER_PHRASE</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">too_many_POs_error</span><span class="plain"> == </span><span class="identifier">FALSE</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_TooManyPhraseOptions</span><span class="plain">),</span>
<span class="string">"a phrase is only allowed to have 16 different options"</span><span class="plain">,</span>
<span class="string">"so either some of these will need to go, or you may want to "</span>
<span class="string">"consider breaking up the phrase into simpler ones whose usage "</span>
<span class="string">"is easier to describe."</span><span class="plain">);</span>
<span class="identifier">too_many_POs_error</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="identifier">too_many_POs_error</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="comment">so that the problem can recur on later phrases</span>
<span class="reserved">phrase_option</span><span class="plain"> *</span><span class="identifier">po</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">phrase_option</span><span class="plain">);</span>
<span class="identifier">po</span><span class="plain">-&gt;</span><span class="element">name</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="identifier">phod</span><span class="plain">-&gt;</span><span class="element">options_permitted</span><span class="plain">[</span><span class="identifier">phod</span><span class="plain">-&gt;</span><span class="element">no_options_permitted</span><span class="plain">++] = </span><span class="identifier">po</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Options::phod_add_phrase_option is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Parsing phrase options in an invocation. </b>At this point, we're looking at the text after the first comma in something
like:
</p>
<blockquote>
<p>list the contents of the box, as a sentence, with newlines;</p>
</blockquote>
<p class="inwebparagraph">The invocation has already been parsed enough that we know the options
chosen are:
</p>
<blockquote>
<p>as a sentence, with newlines</p>
</blockquote>
<p class="inwebparagraph">and the following routine turns that into a bitmap with two bits set, one
corresponding to each choice.
</p>
<p class="inwebparagraph">We return <code class="display"><span class="extract">TRUE</span></code> or <code class="display"><span class="extract">FALSE</span></code> according to whether the options were valid or
not, and the <code class="display"><span class="extract">silently</span></code> flag suppresses problem messages we would otherwise
produce.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">phod_being_parsed_silently</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="comment">context for the grammar below</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">Phrases::Options::parse_invoked_options</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="reserved">int</span><span class="plain"> </span><span class="identifier">silently</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">ParseTree::get_phrase_invoked</span><span class="plain">(</span><span class="identifier">inv</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">Invocations::get_phrase_options</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">);</span>
<span class="identifier">ph_being_parsed</span><span class="plain"> = </span><span class="identifier">ph</span><span class="plain">;</span>
<span class="identifier">phod_being_parsed</span><span class="plain"> = &amp;(</span><span class="identifier">ph_being_parsed</span><span class="plain">-&gt;</span><span class="element">options_data</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">bitmap</span><span class="plain"> = </span><span class="constant">0</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pc</span><span class="plain"> = </span><span class="identifier">problem_count</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Parse the supplied list of options into a bitmap</span> <span class="cwebmacronumber">10.1</span>&gt;<span class="plain">;</span>
<span class="functiontext">Invocations::set_phrase_options_bitmap</span><span class="plain">(</span><span class="identifier">inv</span><span class="plain">, </span><span class="identifier">bitmap</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">problem_count</span><span class="plain"> &gt; </span><span class="identifier">pc</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Phrases::Options::parse_invoked_options is used in 14/ds2 (<a href="14-ds2.html#SP11_9_1_1_7">&#167;11.9.1.1.7</a>).</p>
<p class="inwebparagraph"><a id="SP10_1"></a><b>&#167;10.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Parse the supplied list of options into a bitmap</span> <span class="cwebmacronumber">10.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">s</span><span class="plain"> = </span><span class="identifier">phod_being_parsed_silently</span><span class="plain">;</span>
<span class="identifier">phod_being_parsed_silently</span><span class="plain"> = </span><span class="identifier">silently</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt;(</span><span class="identifier">W</span><span class="plain">)) </span><span class="identifier">bitmap</span><span class="plain"> = &lt;&lt;</span><span class="identifier">r</span><span class="plain">&gt;&gt;;</span>
<span class="identifier">phod_being_parsed_silently</span><span class="plain"> = </span><span class="identifier">s</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">problem_count</span><span class="plain"> == </span><span class="identifier">pc</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">phod_being_parsed</span><span class="plain">-&gt;</span><span class="element">multiple_options_permitted</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Reject this if multiple options are set</span> <span class="cwebmacronumber">10.1.1</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10">&#167;10</a>.</p>
<p class="inwebparagraph"><a id="SP10_1_1"></a><b>&#167;10.1.1. </b>Ah, bit-twiddling: fun for all the family. There's no point computing the
Hamming distance of the bitmap, that is, the number of bits set: we only need
to know if it's a power of 2 or not. Note that subtracting 1, in binary,
clears the least significant set bit, leaves the higher bits as they are,
and changes the lower bits (which were previously all 0s) to 1s. So taking
a bitwise-and of a number and itself minus one leaves just the higher bits
alone. The original number therefore had a single set bit if and only if
this residue is zero.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Reject this if multiple options are set</span> <span class="cwebmacronumber">10.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">bitmap</span><span class="plain"> &amp; (</span><span class="identifier">bitmap</span><span class="plain"> - </span><span class="constant">1</span><span class="plain">)) != </span><span class="constant">0</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">silently</span><span class="plain"> == </span><span class="identifier">FALSE</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::quote_wording</span><span class="plain">(2, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_phrase</span><span class="plain">(3, </span><span class="identifier">ph</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(4, </span><span class="identifier">phod_being_parsed</span><span class="plain">-&gt;</span><span class="element">options_declaration</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">PM_PhraseOptionsExclusive</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, supplying the options '%2' to the phrase '%3', but "</span>
<span class="string">"the options listed for this phrase ('%4') are mutually exclusive."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP10_1">&#167;10.1</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>When setting options, in an actual use of a phrase, the list is divided
by "and":
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; ::=</span>
<span class="plain">... | ==&gt; </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">preform_lookahead_mode</span><span class="plain">; </span><span class="comment">match only when looking ahead</span>
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">setting</span><span class="plain">-</span><span class="identifier">entry</span><span class="plain">&gt; &lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">tail</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">R</span><span class="plain">[1] | </span><span class="identifier">R</span><span class="plain">[2]</span>
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">setting</span><span class="plain">-</span><span class="identifier">entry</span><span class="plain">&gt; ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">tail</span><span class="plain">&gt; ::=</span>
<span class="plain">, </span><span class="identifier">_and</span><span class="plain"> &lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
<span class="identifier">_</span><span class="plain">,/</span><span class="identifier">and</span><span class="plain"> &lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">list</span><span class="plain">&gt; ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">-</span><span class="identifier">setting</span><span class="plain">-</span><span class="identifier">entry</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">&gt; | ==&gt; </span><span class="identifier">R</span><span class="plain">[1]</span>
<span class="plain">... ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_NotAPhraseOption or C22NotTheOnlyPhraseOption problem</span> <span class="cwebmacronumber">11.1</span>&gt;
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP11_1"></a><b>&#167;11.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_NotAPhraseOption or C22NotTheOnlyPhraseOption problem</span> <span class="cwebmacronumber">11.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> ((!</span><span class="identifier">preform_lookahead_mode</span><span class="plain">) &amp;&amp; (!</span><span class="identifier">phod_being_parsed_silently</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::quote_wording</span><span class="plain">(2, </span><span class="identifier">W</span><span class="plain">);</span>
<span class="functiontext">Problems::quote_phrase</span><span class="plain">(3, </span><span class="identifier">ph_being_parsed</span><span class="plain">);</span>
<span class="identifier">Problems::quote_wording</span><span class="plain">(4, </span><span class="identifier">phod_being_parsed</span><span class="plain">-&gt;</span><span class="element">options_declaration</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">phod_being_parsed</span><span class="plain">-&gt;</span><span class="element">no_options_permitted</span><span class="plain"> &gt; </span><span class="constant">1</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">PM_NotAPhraseOption</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but '%2' is not one of the options allowed on "</span>
<span class="string">"the end of the phrase '%3'. (The options allowed are: '%4'.)"</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="plain">} </span><span class="reserved">else</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">PM_NotTheOnlyPhraseOption</span><span class="plain">));</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"You wrote %1, but the only option allowed on the end of the "</span>
<span class="string">"phrase '%3' is '%4', so '%2' is not something I know how to "</span>
<span class="string">"deal with."</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_end</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="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. </b>The following matches any single phrase option for the phrase being used.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="reserved">phrase</span><span class="plain">-</span><span class="identifier">option</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">bitmap</span><span class="plain"> = </span><span class="functiontext">Phrases::Options::parse</span><span class="plain">(</span><span class="identifier">phod_being_parsed</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">bitmap</span><span class="plain"> == -1) </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">X</span><span class="plain"> = </span><span class="identifier">bitmap</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>
</pre>
<p class="inwebparagraph"></p>
<hr class="tocbar">
<ul class="toc"><li><a href="22-dptd.html">Back to 'Describing Phrase Type Data'</a></li><li><a href="22-pav.html">Continue with 'Phrases as Values'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>