1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 08:34:22 +03:00
inform7/docs/if-module/5-gl.html
2020-03-22 10:50:19 +00:00

1795 lines
246 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>5/gv</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</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 '5/gl' 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">if</a></li><li><a href="index.html#5">Chapter 5: Command Grammar</a></li><li><b>Grammar Lines</b></li></ul><p class="purpose">A grammar line is a list of tokens to specify a textual pattern. For example, the NI source for a grammar line might be |"take [something] out"|, which is a sequence of three tokens.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP5">&#167;5. GL lists</a></li><li><a href="#SP6">&#167;6. Two special forms of grammar lines</a></li><li><a href="#SP7">&#167;7. Conditional lines</a></li><li><a href="#SP9">&#167;9. Mistakes</a></li><li><a href="#SP10">&#167;10. Single word optimisation</a></li><li><a href="#SP12">&#167;12. Phase I: Slash Grammar</a></li><li><a href="#SP14">&#167;14. Phase II: Determining Grammar</a></li><li><a href="#SP16">&#167;16. Phase III: Sort Grammar</a></li><li><a href="#SP18">&#167;18. Phase IV: Compile Grammar</a></li><li><a href="#SP22">&#167;22. Indexing by grammar</a></li><li><a href="#SP23">&#167;23. Indexing by action</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 grammar line is in turn a sequence of tokens. If it matches, it will
result in 0, 1 or 2 parameters, though only if the grammar verb owning
the line is a genuine <code class="display"><span class="extract">GV_IS_COMMAND</span></code> command grammar will the case of
2 parameters be possible. (This is for text matching, say, "put X in Y":
the objects X and Y are two parameters resulting.) And in that case (alone),
there will also be a <code class="display"><span class="extract">resulting_action</span></code>.
</p>
<p class="inwebparagraph">A small amount of disjunction is allowed in a grammar line: for instance,
"look in/inside/into [something]" consists of five tokens, but only three
lexemes, basic units to be matched. (The first is "look", the second
is "one out of in, inside or into", and the third is an object in scope.)
In the following structure we cache the lexeme count since it is fiddly
to calculate, and useful when sorting grammar lines into applicability order.
</p>
<p class="inwebparagraph">The individual tokens are stored simply as parse tree nodes of type
<code class="display"><span class="extract">TOKEN_NT</span></code>, and are the children of the node <code class="display"><span class="extract">gl-&gt;tokens</span></code>, which is why
(for now, anyway) there is no grammar token structure.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">UNCALCULATED_BONUS</span><span class="plain"> -1000000</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">grammar_line</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">next_line</span><span class="plain">; </span> <span class="comment">linked list in creation order</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">sorted_next_line</span><span class="plain">; </span> <span class="comment">and in applicability order</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">where_grammar_specified</span><span class="plain">; </span> <span class="comment">where found in source</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">original_text</span><span class="plain">; </span> <span class="comment">the word number of the double-quoted grammar text...</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">tokens</span><span class="plain">; </span> <span class="comment">...which is parsed into this list of tokens</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">lexeme_count</span><span class="plain">; </span> <span class="comment">number of lexemes, or <code class="display"><span class="extract">-1</span></code> if not yet counted</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">understand_when_text</span><span class="plain">; </span> <span class="comment">only when this condition holds</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">pcalc_prop</span><span class="plain"> *</span><span class="identifier">understand_when_prop</span><span class="plain">; </span> <span class="comment">and when this condition holds</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">pluralised</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">GV_IS_OBJECT</span></code>: refers in the plural</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">action_name</span><span class="plain"> *</span><span class="identifier">resulting_action</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">GV_IS_COMMAND</span></code>: the action</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">reversed</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">GV_IS_COMMAND</span></code>: the two arguments are in reverse order</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">mistaken</span><span class="plain">; </span> <span class="comment"><code class="display"><span class="extract">GV_IS_COMMAND</span></code>: is this understood as a mistake?</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">mistake_response_text</span><span class="plain">; </span> <span class="comment">if so, reply thus</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">grammar_type</span><span class="plain"> </span><span class="identifier">gl_type</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">suppress_compilation</span><span class="plain">; </span> <span class="comment">has been compiled in a single I6 grammar token already?</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">next_with_action</span><span class="plain">; </span> <span class="comment">used when indexing actions</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">grammar_verb</span><span class="plain"> *</span><span class="identifier">belongs_to_gv</span><span class="plain">; </span> <span class="comment">similarly, used only in indexing</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">cond_token_iname</span><span class="plain">; </span> <span class="comment">for its <code class="display"><span class="extract">Cond_Token_*</span></code> routine, if any</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">mistake_iname</span><span class="plain">; </span> <span class="comment">for its <code class="display"><span class="extract">Mistake_Token_*</span></code> routine, if any</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">general_sort_bonus</span><span class="plain">; </span> <span class="comment">temporary values used in grammar line sorting</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">understanding_sort_bonus</span><span class="plain">;</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">grammar_line</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure grammar_line is accessed in 5/tfg and here.</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b></p>
<pre class="display">
<span class="reserved">typedef</span><span class="plain"> </span><span class="reserved">struct</span><span class="plain"> </span><span class="reserved">slash_gpr</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">first_choice</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">last_choice</span><span class="plain">;</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">sgpr_iname</span><span class="plain">;</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">slash_gpr</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure slash_gpr is private to this section.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b></p>
<pre class="display">
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="functiontext">PL::Parsing::Lines::new</span><span class="plain">(</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">wn</span><span class="plain">, </span><span class="reserved">action_name</span><span class="plain"> *</span><span class="identifier">ac</span><span class="plain">,</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">token_list</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">reversed</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">pluralised</span><span class="plain">) {</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain">);</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;original_text</span><span class="plain"> = </span><span class="identifier">wn</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;resulting_action</span><span class="plain"> = </span><span class="identifier">ac</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;belongs_to_gv</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ac</span><span class="plain"> != </span><span class="identifier">NULL</span><span class="plain">) </span><span class="functiontext">PL::Actions::add_gl</span><span class="plain">(</span><span class="identifier">ac</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">);</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistaken</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistake_response_text</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;next_with_action</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;tokens</span><span class="plain"> = </span><span class="identifier">token_list</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;where_grammar_specified</span><span class="plain"> = </span><span class="identifier">current_sentence</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;gl_type</span><span class="plain"> = </span><span class="functiontext">PL::Parsing::Tokens::Types::new</span><span class="plain">(</span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain"> = -1; </span> <span class="comment">no count made as yet</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;reversed</span><span class="plain"> = </span><span class="identifier">reversed</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;pluralised</span><span class="plain"> = </span><span class="identifier">pluralised</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;understand_when_text</span><span class="plain"> = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;understand_when_prop</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;suppress_compilation</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;general_sort_bonus</span><span class="plain"> = </span><span class="constant">UNCALCULATED_BONUS</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;understanding_sort_bonus</span><span class="plain"> = </span><span class="constant">UNCALCULATED_BONUS</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;cond_token_iname</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistake_iname</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">gl</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::log</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;GL%d:%W&gt;"</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;tokens</span><span class="plain">));</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::set_single_type</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">gl_value</span><span class="plain">) {</span>
<span class="functiontext">PL::Parsing::Tokens::Types::set_single_type</span><span class="plain">(&amp;(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;gl_type</span><span class="plain">), </span><span class="identifier">gl_value</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::new is used in 5/tfg (<a href="5-tfg.html#SP21">&#167;21</a>).</p>
<p class="endnote">The function PL::Parsing::Lines::log is used in 1/im (<a href="1-im.html#SP4">&#167;4</a>, <a href="1-im.html#SP4_4">&#167;4.4</a>).</p>
<p class="endnote">The function PL::Parsing::Lines::set_single_type is used in 5/tfg (<a href="5-tfg.html#SP21">&#167;21</a>).</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. GL lists. </b>Grammar lines are themselves generally stored in linked lists (belonging,
for instance, to a GV). Here we add a GL to the back of a list.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::list_length</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">list_head</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = 0;</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">posn</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">posn</span><span class="plain"> = </span><span class="identifier">list_head</span><span class="plain">; </span><span class="identifier">posn</span><span class="plain">; </span><span class="identifier">posn</span><span class="plain"> = </span><span class="identifier">posn</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain">) </span><span class="identifier">c</span><span class="plain">++;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">c</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="functiontext">PL::Parsing::Lines::list_add</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">list_head</span><span class="plain">, </span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">new_gl</span><span class="plain">) {</span>
<span class="identifier">new_gl</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">list_head</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">list_head</span><span class="plain"> = </span><span class="identifier">new_gl</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">posn</span><span class="plain"> = </span><span class="identifier">list_head</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">posn</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain">) </span><span class="identifier">posn</span><span class="plain"> = </span><span class="identifier">posn</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain">;</span>
<span class="identifier">posn</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain"> = </span><span class="identifier">new_gl</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">list_head</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="functiontext">PL::Parsing::Lines::list_remove</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">list_head</span><span class="plain">, </span><span class="reserved">action_name</span><span class="plain"> *</span><span class="identifier">find</span><span class="plain">) {</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">prev</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">, *</span><span class="identifier">posn</span><span class="plain"> = </span><span class="identifier">list_head</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">posn</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">posn</span><span class="plain">-</span><span class="element">&gt;resulting_action</span><span class="plain"> == </span><span class="identifier">find</span><span class="plain">) {</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">GRAMMAR_CONSTRUCTION</span><span class="plain">, </span><span class="string">"Removing grammar line: $g\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">posn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prev</span><span class="plain">) </span><span class="identifier">prev</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain"> = </span><span class="identifier">posn</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">list_head</span><span class="plain"> = </span><span class="identifier">posn</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">prev</span><span class="plain"> = </span><span class="identifier">posn</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">posn</span><span class="plain"> = </span><span class="identifier">posn</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">list_head</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::list_length is used in 5/gv (<a href="5-gv.html#SP20">&#167;20</a>).</p>
<p class="endnote">The function PL::Parsing::Lines::list_add is used in 5/gv (<a href="5-gv.html#SP20">&#167;20</a>).</p>
<p class="endnote">The function PL::Parsing::Lines::list_remove is used in 5/gv (<a href="5-gv.html#SP9">&#167;9</a>).</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. Two special forms of grammar lines. </b>GLs can have either or both of two orthogonal special forms: they can be
mistaken or conditional. (Mistakes only occur in command grammars, but
conditional GLs can occur in any grammar.) GLs of this kind need special
support, in that I6 general parsing routines need to be compiled for them
to use as tokens: here's where that support is provided. The following
step needs to take place before the command grammar (I6 <code class="display"><span class="extract">Verb</span></code> directives,
etc.) is compiled because of I6's requirement that all GPRs be defined
as routines prior to the <code class="display"><span class="extract">Verb</span></code> directive using them.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::line_list_compile_condition_tokens</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">list_head</span><span class="plain">) {</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">list_head</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain">) {</span>
<span class="functiontext">PL::Parsing::Lines::gl_compile_condition_token_as_needed</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">);</span>
<span class="functiontext">PL::Parsing::Lines::gl_compile_mistake_token_as_needed</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::line_list_compile_condition_tokens is used in 5/gv (<a href="5-gv.html#SP22">&#167;22</a>).</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. Conditional lines. </b>Some grammar lines take effect only when some circumstance holds: most I7
conditions are valid to specify this, with the notation "Understand ... as
... when ...". However, we want to protect new authors from mistakes
like this:
</p>
<blockquote>
<p>Understand "mate" as Fred when asking Fred to do something: ...</p>
</blockquote>
<p class="inwebparagraph">where the condition couldn't test anything useful because it's not yet
known what the action will be.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">understand</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt; ::=</span>
<span class="plain">&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">non</span><span class="plain">-</span><span class="identifier">action</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt; | ==&gt; 0; &lt;&lt;</span><span class="identifier">parse_node</span><span class="plain">:</span><span class="identifier">cond</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">&gt; | ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_WhenAction problem</span> <span class="cwebmacronumber">7.1</span>&gt;
<span class="plain">... ==&gt; </span>&lt;<span class="cwebmacro">Issue PM_BadWhen problem</span> <span class="cwebmacronumber">7.2</span>&gt;<span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP7_1"></a><b>&#167;7.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_WhenAction problem</span> <span class="cwebmacronumber">7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_WhenAction</span><span class="plain">),</span>
<span class="string">"the condition after 'when' involves the current action"</span><span class="plain">,</span>
<span class="string">"but this can never work, because when Inform is still trying to "</span>
<span class="string">"understand a command, the current action isn't yet decided on."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>.</p>
<p class="inwebparagraph"><a id="SP7_2"></a><b>&#167;7.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Issue PM_BadWhen problem</span> <span class="cwebmacronumber">7.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_BadWhen</span><span class="plain">),</span>
<span class="string">"the condition after 'when' makes no sense to me"</span><span class="plain">,</span>
<span class="string">"although otherwise this worked - it is only the part after 'when' "</span>
<span class="string">"which I can't follow."</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7">&#167;7</a>, <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>Such GLs have an "understand when" set, as follows.
They compile preceded by a match-no-text token which matches correctly
if the condition holds and incorrectly if it fails. For instance, for
a command grammar, we might have:
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">* Cond_Token_26 'draw' noun -&gt; Draw</span></code>
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::set_understand_when</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</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">gl</span><span class="plain">-</span><span class="element">&gt;understand_when_text</span><span class="plain"> = </span><span class="identifier">W</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::set_understand_prop</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">, </span><span class="identifier">pcalc_prop</span><span class="plain"> *</span><span class="identifier">prop</span><span class="plain">) {</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;understand_when_prop</span><span class="plain"> = </span><span class="identifier">prop</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::conditional</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</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">gl</span><span class="plain">-</span><span class="element">&gt;understand_when_text</span><span class="plain">)) || (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;understand_when_prop</span><span class="plain">))</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::gl_compile_condition_token_as_needed</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::Parsing::Lines::conditional</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">)) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;where_grammar_specified</span><span class="plain">;</span>
<span class="identifier">package_request</span><span class="plain"> *</span><span class="identifier">PR</span><span class="plain"> = </span><span class="identifier">Hierarchy::local_package</span><span class="plain">(</span><span class="identifier">COND_TOKENS_HAP</span><span class="plain">);</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;cond_token_iname</span><span class="plain"> = </span><span class="identifier">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="identifier">CONDITIONAL_TOKEN_FN_HL</span><span class="plain">, </span><span class="identifier">PR</span><span class="plain">);</span>
<span class="identifier">packaging_state</span><span class="plain"> </span><span class="identifier">save</span><span class="plain"> = </span><span class="identifier">Routines::begin</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;cond_token_iname</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">NULL</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">gl</span><span class="plain">-</span><span class="element">&gt;understand_when_text</span><span class="plain">)) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;where_grammar_specified</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">understand</span><span class="plain">-</span><span class="identifier">condition</span><span class="plain">&gt;(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;understand_when_text</span><span class="plain">)) {</span>
<span class="identifier">spec</span><span class="plain"> = &lt;&lt;</span><span class="identifier">parse_node</span><span class="plain">:</span><span class="identifier">cond</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Dash::validate_conditional_clause</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Issue PM_BadWhen problem</span> <span class="cwebmacronumber">7.2</span>&gt;<span class="plain">;</span>
<span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">pcalc_prop</span><span class="plain"> *</span><span class="identifier">prop</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;understand_when_prop</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">spec</span><span class="plain">) || (</span><span class="identifier">prop</span><span class="plain">)) {</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">IF_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">spec</span><span class="plain">) &amp;&amp; (</span><span class="identifier">prop</span><span class="plain">)) {</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">AND_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spec</span><span class="plain">) </span><span class="identifier">Specifications::Compiler::emit_as_val</span><span class="plain">(</span><span class="identifier">K_truth_state</span><span class="plain">, </span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">prop</span><span class="plain">) </span><span class="identifier">Calculus::Deferrals::emit_test_of_proposition</span><span class="plain">(</span><span class="identifier">Rvalues::new_self_object_constant</span><span class="plain">(), </span><span class="identifier">prop</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">spec</span><span class="plain">) &amp;&amp; (</span><span class="identifier">prop</span><span class="plain">)) {</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="plain">}</span>
<span class="identifier">Produce::code</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">RETURN_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">GPR_PREPOSITION_HL</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="plain">}</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">RETURN_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">GPR_FAIL_HL</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Routines::end</span><span class="plain">(</span><span class="identifier">save</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::gl_compile_extra_token_for_condition</span><span class="plain">(</span><span class="reserved">gpr_kit</span><span class="plain"> *</span><span class="identifier">gprk</span><span class="plain">, </span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">gv_is</span><span class="plain">, </span><span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">current_label</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::Parsing::Lines::conditional</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;cond_token_iname</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"GL cond token not ready"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gv_is</span><span class="plain"> == </span><span class="constant">GV_IS_COMMAND</span><span class="plain">) {</span>
<span class="identifier">Emit::array_iname_entry</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;cond_token_iname</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">IF_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">EQ_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_call_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;cond_token_iname</span><span class="plain">);</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">GPR_FAIL_HL</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::code</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">JUMP_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::lab</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">current_label</span><span class="plain">);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::set_understand_when is used in 5/tfg (<a href="5-tfg.html#SP21">&#167;21</a>).</p>
<p class="endnote">The function PL::Parsing::Lines::set_understand_prop is used in 5/tfg (<a href="5-tfg.html#SP21">&#167;21</a>).</p>
<p class="endnote">The function PL::Parsing::Lines::conditional is used in <a href="#SP10">&#167;10</a>, <a href="#SP17">&#167;17</a>.</p>
<p class="endnote">The function PL::Parsing::Lines::gl_compile_condition_token_as_needed is used in <a href="#SP6">&#167;6</a>.</p>
<p class="endnote">The function PL::Parsing::Lines::gl_compile_extra_token_for_condition is used in <a href="#SP20">&#167;20</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. Mistakes. </b>These are grammar lines used in command GVs for commands which are accepted
but only in order to print nicely worded rejections. A number of schemes
were tried for this, for instance producing parser errors and setting <code class="display"><span class="extract">pe</span></code>
to some high value, but the method now used is for a mistaken line to
produce a successful parse at the I6 level, resulting in the (I6 only)
action <code class="display"><span class="extract">##MistakeAction</span></code>. The tricky part is to send information to the
I6 action routine <code class="display"><span class="extract">MistakeActionSub</span></code> indicating what the mistake was,
exactly: we do this by including, in the I6 grammar, a token which
matches empty text and returns a "preposition", so that it has no
direct result, but which also sets a special global variable as a
side-effect. Thus a mistaken line "act [thing]" comes out as something
like:
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">* Mistake_Token_12 'act' noun -&gt; MistakeAction</span></code>
</p>
<p class="inwebparagraph">Since the I6 parser accepts the first command which matches, and since
none of this can be recursive, the value of this variable at the end of
I6 parsing is guaranteed to be the one set during the line causing
the mistake.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::set_mistake</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">wn</span><span class="plain">) {</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistaken</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistake_response_text</span><span class="plain"> = </span><span class="identifier">Wordings::one_word</span><span class="plain">(</span><span class="identifier">wn</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistake_iname</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">package_request</span><span class="plain"> *</span><span class="identifier">PR</span><span class="plain"> = </span><span class="identifier">Hierarchy::local_package</span><span class="plain">(</span><span class="identifier">MISTAKES_HAP</span><span class="plain">);</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistake_iname</span><span class="plain"> = </span><span class="identifier">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="identifier">MISTAKE_FN_HL</span><span class="plain">, </span><span class="identifier">PR</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::gl_compile_mistake_token_as_needed</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistaken</span><span class="plain">) {</span>
<span class="identifier">packaging_state</span><span class="plain"> </span><span class="identifier">save</span><span class="plain"> = </span><span class="identifier">Routines::begin</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistake_iname</span><span class="plain">);</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">IF_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">NE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">ACTOR_HL</span><span class="plain">));</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">PLAYER_HL</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::code</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">RETURN_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">GPR_FAIL_HL</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">STORE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::ref_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">UNDERSTAND_AS_MISTAKE_NUMBER_HL</span><span class="plain">));</span>
<span class="identifier">Produce::val</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (100 + </span><span class="identifier">gl</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">RETURN_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">GPR_PREPOSITION_HL</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Routines::end</span><span class="plain">(</span><span class="identifier">save</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::gl_compile_extra_token_for_mistake</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">gv_is</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistaken</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gv_is</span><span class="plain"> == </span><span class="constant">GV_IS_COMMAND</span><span class="plain">) {</span>
<span class="identifier">Emit::array_iname_entry</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistake_iname</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"GLs may only be mistaken in command grammar"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">inter_name</span><span class="plain"> *</span><span class="identifier">MistakeAction_iname</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::gl_compile_result_of_mistake</span><span class="plain">(</span><span class="reserved">gpr_kit</span><span class="plain"> *</span><span class="identifier">gprk</span><span class="plain">, </span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistaken</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">MistakeAction_iname</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"no MistakeAction yet"</span><span class="plain">);</span>
<span class="identifier">Emit::array_iname_entry</span><span class="plain">(</span><span class="identifier">VERB_DIRECTIVE_RESULT_iname</span><span class="plain">);</span>
<span class="identifier">Emit::array_iname_entry</span><span class="plain">(</span><span class="identifier">MistakeAction_iname</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>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::MistakeActionSub_routine</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">package_request</span><span class="plain"> *</span><span class="identifier">MAP</span><span class="plain"> = </span><span class="identifier">Hierarchy::synoptic_package</span><span class="plain">(</span><span class="identifier">SACTIONS_HAP</span><span class="plain">);</span>
<span class="identifier">packaging_state</span><span class="plain"> </span><span class="identifier">save</span><span class="plain"> = </span><span class="identifier">Routines::begin</span><span class="plain">(</span><span class="identifier">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="identifier">MISTAKEACTIONSUB_HL</span><span class="plain">, </span><span class="identifier">MAP</span><span class="plain">));</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">SWITCH_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">UNDERSTAND_AS_MISTAKE_NUMBER_HL</span><span class="plain">));</span>
<span class="identifier">Produce::code</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">, </span><span class="reserved">grammar_line</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistaken</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">gl</span><span class="plain">-</span><span class="element">&gt;mistake_response_text</span><span class="plain">)) {</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;where_grammar_specified</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">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (&lt;</span><span class="identifier">s</span><span class="plain">-</span><span class="identifier">value</span><span class="plain">&gt;(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistake_response_text</span><span class="plain">))</span>
<span class="identifier">spec</span><span class="plain"> = &lt;&lt;</span><span class="identifier">rp</span><span class="plain">&gt;&gt;;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">Specifications::new_UNKNOWN</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;mistake_response_text</span><span class="plain">);</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">CASE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, (</span><span class="identifier">inter_t</span><span class="plain">) (100+</span><span class="identifier">gl</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">));</span>
<span class="identifier">Produce::code</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_call_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">PARSERERROR_HL</span><span class="plain">));</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Specifications::Compiler::emit_constant_to_kind_as_val</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="identifier">K_text</span><span class="plain">);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">DEFAULT_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::code</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">PRINT_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_text</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">I</span><span class="string">"I didn't understand that sentence.\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::rtrue</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">STORE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::ref_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">SAY__P_HL</span><span class="plain">));</span>
<span class="identifier">Produce::val</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 1);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Routines::end</span><span class="plain">(</span><span class="identifier">save</span><span class="plain">);</span>
<span class="identifier">MistakeAction_iname</span><span class="plain"> = </span><span class="identifier">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="identifier">MISTAKEACTION_HL</span><span class="plain">, </span><span class="identifier">MAP</span><span class="plain">);</span>
<span class="identifier">Emit::named_pseudo_numeric_constant</span><span class="plain">(</span><span class="identifier">MistakeAction_iname</span><span class="plain">, </span><span class="identifier">K_action_name</span><span class="plain">, 10000);</span>
<span class="identifier">Produce::annotate_i</span><span class="plain">(</span><span class="identifier">MistakeAction_iname</span><span class="plain">, </span><span class="identifier">ACTION_IANN</span><span class="plain">, 1);</span>
<span class="identifier">Hierarchy::make_available</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">MistakeAction_iname</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::set_mistake is used in 5/tfg (<a href="5-tfg.html#SP21">&#167;21</a>).</p>
<p class="endnote">The function PL::Parsing::Lines::gl_compile_mistake_token_as_needed is used in <a href="#SP6">&#167;6</a>.</p>
<p class="endnote">The function PL::Parsing::Lines::gl_compile_extra_token_for_mistake is used in <a href="#SP20">&#167;20</a>.</p>
<p class="endnote">The function PL::Parsing::Lines::gl_compile_result_of_mistake is used in <a href="#SP20">&#167;20</a>.</p>
<p class="endnote">The function PL::Parsing::Lines::MistakeActionSub_routine appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Single word optimisation. </b>The grammars used to parse names of objects are normally compiled into
<code class="display"><span class="extract">parse_name</span></code> routines. But the I6 parser also uses the <code class="display"><span class="extract">name</span></code> property,
and it is advantageous to squeeze as much as possible into <code class="display"><span class="extract">name</span></code> and
as little as possible into <code class="display"><span class="extract">parse_name</span></code>. The only possible candidates
are grammar lines consisting of single unconditional words, as detected
by the following routine:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::gl_contains_single_unconditional_word</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;tokens</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pn</span><span class="plain">)</span>
<span class="plain">&amp;&amp; (</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="plain">&amp;&amp; (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">) == 0)</span>
<span class="plain">&amp;&amp; (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">grammar_token_literal_ANNOT</span><span class="plain">))</span>
<span class="plain">&amp;&amp; (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;pluralised</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)</span>
<span class="plain">&amp;&amp; (</span><span class="functiontext">PL::Parsing::Lines::conditional</span><span class="plain">(</span><span class="identifier">gl</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">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">));</span>
<span class="reserved">return</span><span class="plain"> -1;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::gl_contains_single_unconditional_word is used in <a href="#SP11">&#167;11</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. </b>This routine looks through a GL list and marks to suppress all those
GLs consisting only of single unconditional words, which means they
will not be compiled into a <code class="display"><span class="extract">parse_name</span></code> routine (or anywhere else).
If the <code class="display"><span class="extract">of</span></code> file handle is set, then the words in question are printed
as I6-style dictionary words to it. In practice, this is done when
compiling the <code class="display"><span class="extract">name</span></code> property, so that a single scan achieves both
the transfer into <code class="display"><span class="extract">name</span></code> and the exclusion from <code class="display"><span class="extract">parse_name</span></code> of
affected GLs.
</p>
<pre class="display">
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="functiontext">PL::Parsing::Lines::list_take_out_one_word_grammar</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">list_head</span><span class="plain">) {</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">, *</span><span class="identifier">glp</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">list_head</span><span class="plain">, </span><span class="identifier">glp</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">wn</span><span class="plain"> = </span><span class="functiontext">PL::Parsing::Lines::gl_contains_single_unconditional_word</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">wn</span><span class="plain"> &gt;= 0) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">content</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">content</span><span class="plain">, </span><span class="string">"%w"</span><span class="plain">, </span><span class="identifier">Lexer::word_text</span><span class="plain">(</span><span class="identifier">wn</span><span class="plain">));</span>
<span class="identifier">Emit::array_dword_entry</span><span class="plain">(</span><span class="identifier">content</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">content</span><span class="plain">);</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;suppress_compilation</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">glp</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">list_head</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::list_take_out_one_word_grammar is used in 5/gv (<a href="5-gv.html#SP17">&#167;17</a>).</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Phase I: Slash Grammar. </b>Slashing is an activity carried out on a per-grammar-line basis, so to slash
a list of GLs we simply slash each GL in turn.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::line_list_slash</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl_head</span><span class="plain">) {</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">gl_head</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain">) {</span>
<span class="functiontext">PL::Parsing::Lines::slash_grammar_line</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::line_list_slash is used in 5/gv (<a href="5-gv.html#SP24">&#167;24</a>).</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. </b>Now the actual slashing process, which does not descend to tokens. We
remove any slashes, and fill in positive numbers in the <code class="display"><span class="extract">qualifier</span></code> field
corresponding to non-singleton equivalence classes. Thus "take up/in all
washing/laundry/linen" begins as 10 tokens, three of them forward slashes,
and ends as 7 tokens, with <code class="display"><span class="extract">qualifier</span></code> values 0, 1, 1, 0, 2, 2, 2, for
four equivalence classes in turn. Each equivalence class is one lexical
unit, or "lexeme", so the lexeme count is then 4.
</p>
<p class="inwebparagraph">In addition, if one of the slashed options is "--", then this means the
empty word, and is removed from the token list; but the first token of the
lexeme is annotated accordingly.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::slash_grammar_line</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">alternatives_group</span><span class="plain"> = 0;</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;where_grammar_specified</span><span class="plain">; </span> <span class="comment">to report problems</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;tokens</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Null tokens on grammar"</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">GRAMMAR_CONSTRUCTION</span><span class="plain">, </span><span class="string">"Preparing grammar line:\</span><span class="plain">n</span><span class="string">$T"</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;tokens</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;tokens</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">)</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">, 0);</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">class_start</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;tokens</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Wordings::length</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">)) == 1) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">))) == </span><span class="identifier">FORWARDSLASH_V</span><span class="plain">)) { </span> <span class="comment">slash follows:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">) == 0) {</span>
<span class="identifier">class_start</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">alternatives_group</span><span class="plain">++; </span> <span class="comment">start new equiv class</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">class_start</span><span class="plain">, </span><span class="identifier">slash_dash_dash_ANNOT</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">,</span>
<span class="identifier">alternatives_group</span><span class="plain">); </span> <span class="comment">make two sides of slash equiv</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">)</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">, </span><span class="identifier">alternatives_group</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Wordings::length</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">)) == 1) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Lexer::word</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">))) == </span><span class="identifier">DOUBLEDASH_V</span><span class="plain">)) { </span> <span class="comment">&mdash; follows:</span>
<span class="identifier">ParseTree::annotate_int</span><span class="plain">(</span><span class="identifier">class_start</span><span class="plain">, </span><span class="identifier">slash_dash_dash_ANNOT</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">; </span> <span class="comment">excise slash and dash-dash</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">; </span> <span class="comment">excise the slash from the token list</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">GRAMMAR_CONSTRUCTION</span><span class="plain">, </span><span class="string">"Regrouped as:\</span><span class="plain">n</span><span class="string">$T"</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;tokens</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;tokens</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">) &gt; 0) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">grammar_token_literal_ANNOT</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="identifier">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_OverAmbitiousSlash</span><span class="plain">),</span>
<span class="string">"the slash '/' can only be used between single literal words"</span><span class="plain">,</span>
<span class="string">"so 'underneath/under/beneath' is allowed but "</span>
<span class="string">"'beneath/[florid ways to say under]/under' isn't."</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain"> = 0;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;tokens</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain"> = </span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain"> &gt; 0)</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) &amp;&amp; (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">) == </span><span class="identifier">i</span><span class="plain">))</span>
<span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">GRAMMAR_CONSTRUCTION</span><span class="plain">, </span><span class="string">"Slashed as:\</span><span class="plain">n</span><span class="string">$T"</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;tokens</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::slash_grammar_line is used in <a href="#SP12">&#167;12</a>.</p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. Phase II: Determining Grammar. </b>Here there is substantial work to do both at the line list level and on
individual lines, and the latter does recurse down to token level too.
</p>
<p class="inwebparagraph">The following routine calculates the type of the GL list as the union
of the types of the GLs within it, where union means the narrowest type
such that every GL in the list casts to it. We return null if there
are no GLs in the list, or if the GLs all return null types, or if
an error occurs. (Note that actions in command verb grammars are counted
as null for this purpose, since a grammar used for parsing the player's
commands is not also used to determine a value.)
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">PL::Parsing::Lines::line_list_determine</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">list_head</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">depth</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">gv_is</span><span class="plain">, </span><span class="reserved">grammar_verb</span><span class="plain"> *</span><span class="identifier">gv</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">genuinely_verbal</span><span class="plain">) {</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">first_flag</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec_union</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">GRAMMAR_CONSTRUCTION</span><span class="plain">, </span><span class="string">"Determining GL list for $G\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">gv</span><span class="plain">);</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">list_head</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">spec_of_line</span><span class="plain"> =</span>
<span class="functiontext">PL::Parsing::Lines::gl_determine</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">, </span><span class="identifier">gv_is</span><span class="plain">, </span><span class="identifier">gv</span><span class="plain">, </span><span class="identifier">genuinely_verbal</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first_flag</span><span class="plain">) { </span> <span class="comment">initially no expectations: <code class="display"><span class="extract">spec_union</span></code> is meaningless</span>
<span class="identifier">spec_union</span><span class="plain"> = </span><span class="identifier">spec_of_line</span><span class="plain">; </span> <span class="comment">so we set it to the first result</span>
<span class="identifier">first_flag</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">spec_union</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) &amp;&amp; (</span><span class="identifier">spec_of_line</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">))</span>
<span class="reserved">continue</span><span class="plain">; </span> <span class="comment">we expected to find no result, and did: so no problem</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">spec_union</span><span class="plain">) &amp;&amp; (</span><span class="identifier">spec_of_line</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Dash::compatible_with_description</span><span class="plain">(</span><span class="identifier">spec_union</span><span class="plain">, </span><span class="identifier">spec_of_line</span><span class="plain">) == </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">) {</span>
<span class="identifier">spec_union</span><span class="plain"> = </span><span class="identifier">spec_of_line</span><span class="plain">; </span> <span class="comment">here <code class="display"><span class="extract">spec_of_line</span></code> was a wider type</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Dash::compatible_with_description</span><span class="plain">(</span><span class="identifier">spec_of_line</span><span class="plain">, </span><span class="identifier">spec_union</span><span class="plain">) == </span><span class="identifier">ALWAYS_MATCH</span><span class="plain">) {</span>
<span class="reserved">continue</span><span class="plain">; </span> <span class="comment">here <code class="display"><span class="extract">spec_union</span></code> was already wide enough</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::Parsing::Verbs::allow_mixed_lines</span><span class="plain">(</span><span class="identifier">gv</span><span class="plain">)) </span><span class="reserved">continue</span><span class="plain">;</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;where_grammar_specified</span><span class="plain">;</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_MixedOutcome</span><span class="plain">),</span>
<span class="string">"grammar tokens must have the same outcome whatever the way they are "</span>
<span class="string">"reached"</span><span class="plain">,</span>
<span class="string">"so writing a line like 'Understand \</span><span class="plain">"</span><span class="string">within\</span><span class="plain">"</span><span class="string"> or \</span><span class="plain">"</span><span class="string">next to "</span>
<span class="string">"[something]\</span><span class="plain">"</span><span class="string"> as \</span><span class="plain">"</span><span class="string">[my token]\</span><span class="plain">"</span><span class="string"> must be wrong: one way it produces "</span>
<span class="string">"a thing, the other way it doesn't."</span><span class="plain">);</span>
<span class="identifier">spec_union</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">; </span> <span class="comment">to prevent the problem being repeated for the same grammar</span>
<span class="plain">}</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">GRAMMAR_CONSTRUCTION</span><span class="plain">, </span><span class="string">"Union: $P\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">spec_union</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::line_list_determine is used in 5/gv (<a href="5-gv.html#SP25">&#167;25</a>).</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. </b>There are three tasks here: to determine the type of the GL, to issue a
problem if this type is impossibly large, and to calculate two numerical
quantities used in sorting GLs: the "general sorting bonus" and the
"understanding sorting bonus" (see below).
</p>
<pre class="display">
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="functiontext">PL::Parsing::Lines::gl_determine</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">depth</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">gv_is</span><span class="plain">, </span><span class="reserved">grammar_verb</span><span class="plain"> *</span><span class="identifier">gv</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">genuinely_verbal</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">NULL</span><span class="plain">;</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, *</span><span class="identifier">pn2</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">nulls_count</span><span class="plain">, </span><span class="identifier">i</span><span class="plain">, </span><span class="identifier">nrv</span><span class="plain">, </span><span class="identifier">line_length</span><span class="plain">;</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;where_grammar_specified</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;understanding_sort_bonus</span><span class="plain"> = 0;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;general_sort_bonus</span><span class="plain"> = 0;</span>
<span class="identifier">nulls_count</span><span class="plain"> = 0; </span> <span class="comment">number of tokens with null results</span>
<span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;tokens</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain">; </span> <span class="comment">start from first token</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">genuinely_verbal</span><span class="plain">) &amp;&amp; (</span><span class="identifier">pn</span><span class="plain">)) </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">; </span> <span class="comment">unless it's a command verb</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pn2</span><span class="plain">=</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">line_length</span><span class="plain">=0; </span><span class="identifier">pn2</span><span class="plain">; </span><span class="identifier">pn2</span><span class="plain"> = </span><span class="identifier">pn2</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) </span><span class="identifier">line_length</span><span class="plain">++;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">multiples</span><span class="plain"> = 0;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</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">ParseTree::get_type</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">) != </span><span class="identifier">TOKEN_NT</span><span class="plain">)</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"Bogus node types on grammar"</span><span class="plain">);</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">score</span><span class="plain"> = 0;</span>
<span class="identifier">spec</span><span class="plain"> = </span><span class="functiontext">PL::Parsing::Tokens::determine</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">depth</span><span class="plain">, &amp;</span><span class="identifier">score</span><span class="plain">);</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">GRAMMAR_CONSTRUCTION</span><span class="plain">, </span><span class="string">"Result of token &lt;%W&gt; is $P\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">ParseTree::get_text</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">), </span><span class="identifier">spec</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">spec</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">Specifications::is_kind_like</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">)) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">K_understanding</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">Kinds::Compare::eq</span><span class="plain">(</span><span class="identifier">Specifications::to_kind</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">), </span><span class="identifier">K_understanding</span><span class="plain">))) { </span> <span class="comment">"[text]" token</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">usb_contribution</span><span class="plain"> = </span><span class="identifier">i</span><span class="plain"> - 100;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">usb_contribution</span><span class="plain"> &gt;= 0) </span><span class="identifier">usb_contribution</span><span class="plain"> = -1;</span>
<span class="identifier">usb_contribution</span><span class="plain"> = 100*</span><span class="identifier">usb_contribution</span><span class="plain"> + (</span><span class="identifier">line_length</span><span class="plain">-1-</span><span class="identifier">i</span><span class="plain">);</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;understanding_sort_bonus</span><span class="plain"> += </span><span class="identifier">usb_contribution</span><span class="plain">; </span> <span class="comment">reduces!</span>
<span class="plain">}</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;general_sort_bonus</span><span class="plain"> +=</span>
<span class="functiontext">PL::Parsing::Tokens::Types::add_type</span><span class="plain">(&amp;(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;gl_type</span><span class="plain">), </span><span class="identifier">spec</span><span class="plain">,</span>
<span class="functiontext">PL::Parsing::Tokens::is_multiple</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">), </span><span class="identifier">score</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">nulls_count</span><span class="plain">++;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::Parsing::Tokens::is_multiple</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">)) </span><span class="identifier">multiples</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">multiples</span><span class="plain"> &gt; 1)</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_MultipleMultiples</span><span class="plain">),</span>
<span class="string">"there can be at most one token in any line which can match "</span>
<span class="string">"multiple things"</span><span class="plain">,</span>
<span class="string">"so you'll have to remove one of the 'things' tokens and "</span>
<span class="string">"make it a 'something' instead."</span><span class="plain">);</span>
<span class="identifier">nrv</span><span class="plain"> = </span><span class="functiontext">PL::Parsing::Tokens::Types::get_no_resulting_values</span><span class="plain">(&amp;(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;gl_type</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nrv</span><span class="plain"> == 0) </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;general_sort_bonus</span><span class="plain"> = 100*</span><span class="identifier">nulls_count</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gv_is</span><span class="plain"> == </span><span class="constant">GV_IS_COMMAND</span><span class="plain">) </span><span class="identifier">spec</span><span class="plain"> = </span><span class="identifier">NULL</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">nrv</span><span class="plain"> &lt; 2) </span><span class="identifier">spec</span><span class="plain"> = </span><span class="functiontext">PL::Parsing::Tokens::Types::get_single_type</span><span class="plain">(&amp;(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;gl_type</span><span class="plain">));</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TwoValuedToken</span><span class="plain">),</span>
<span class="string">"there can be at most one varying part in the definition of a "</span>
<span class="string">"named token"</span><span class="plain">,</span>
<span class="string">"so 'Understand \</span><span class="plain">"</span><span class="string">button [a number]\</span><span class="plain">"</span><span class="string"> as \</span><span class="plain">"</span><span class="string">[button indication]\</span><span class="plain">"</span><span class="string">' "</span>
<span class="string">"is allowed but 'Understand \</span><span class="plain">"</span><span class="string">button [a number] on [something]\</span><span class="plain">"</span><span class="string"> "</span>
<span class="string">"as \</span><span class="plain">"</span><span class="string">[button indication]\</span><span class="plain">"</span><span class="string">' is not."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">GRAMMAR_CONSTRUCTION</span><span class="plain">,</span>
<span class="string">"Determined $g: lexeme count %d, sorting bonus %d, arguments %d, "</span>
<span class="string">"fixed initials %d, type $P\</span><span class="plain">n</span><span class="string">"</span><span class="plain">,</span>
<span class="identifier">gl</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;general_sort_bonus</span><span class="plain">, </span><span class="identifier">nrv</span><span class="plain">,</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;understanding_sort_bonus</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">spec</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::gl_determine is used in <a href="#SP14">&#167;14</a>.</p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. Phase III: Sort Grammar. </b>Insertion sort is used to take the linked list of GLs and construct a
separate, sorted version. This is not the controversial part.
</p>
<pre class="display">
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="functiontext">PL::Parsing::Lines::list_sort</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">list_head</span><span class="plain">) {</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">, *</span><span class="identifier">gl2</span><span class="plain">, *</span><span class="identifier">gl3</span><span class="plain">, *</span><span class="identifier">sorted_head</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">list_head</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">sorted_head</span><span class="plain"> = </span><span class="identifier">list_head</span><span class="plain">;</span>
<span class="identifier">list_head</span><span class="plain">-</span><span class="element">&gt;sorted_next_line</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">list_head</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain">) {</span>
<span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain">;</span>
<span class="identifier">gl2</span><span class="plain"> = </span><span class="identifier">sorted_head</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::Parsing::Lines::grammar_line_must_precede</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">, </span><span class="identifier">gl2</span><span class="plain">)) {</span>
<span class="identifier">sorted_head</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;sorted_next_line</span><span class="plain"> = </span><span class="identifier">gl2</span><span class="plain">;</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">gl2</span><span class="plain">) {</span>
<span class="identifier">gl3</span><span class="plain"> = </span><span class="identifier">gl2</span><span class="plain">;</span>
<span class="identifier">gl2</span><span class="plain"> = </span><span class="identifier">gl2</span><span class="plain">-</span><span class="element">&gt;sorted_next_line</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl2</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">gl3</span><span class="plain">-</span><span class="element">&gt;sorted_next_line</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::Parsing::Lines::grammar_line_must_precede</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">, </span><span class="identifier">gl2</span><span class="plain">)) {</span>
<span class="identifier">gl3</span><span class="plain">-</span><span class="element">&gt;sorted_next_line</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">;</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;sorted_next_line</span><span class="plain"> = </span><span class="identifier">gl2</span><span class="plain">;</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">sorted_head</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::list_sort is used in 5/gv (<a href="5-gv.html#SP30">&#167;30</a>).</p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. </b>This is the controversial part: the routine which decides whether one GL
takes precedence (i.e., is parsed earlier than and thus in preference to)
another GL. This algorithm has been hacked many times to try to reach a
position which pleases all designers: something of a lost cause. The
basic motivation is that we need to sort because the various parsers of
I7 grammar (<code class="display"><span class="extract">parse_name</span></code> routines, general parsing routines, the I6 command
parser itself) all work by returning the first match achieved. This means
that if grammar line L2 matches a superset of the texts which grammar line
L1 matches, then L1 should be tried first: trying them in the order L2, L1
would mean that L1 could never be matched, which is surely contrary to the
designer's intention. (Compare the rule-sorting algorithm, which has similar
motivation but is entirely distinct, though both use the same primitive
methods for comparing types of single values, i.e., at stages 5b1 and 5c1
below.)
</p>
<p class="inwebparagraph">Recall that each GL has a numerical USB (understanding sort bonus) and
GSB (general sort bonus). The following rules are applied in sequence:
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(1) Higher USBs beat lower USBs.
</li></ul>
<ul class="items"><li>(2a) For sorting GLs in player-command grammar, shorter lines beat longer
lines, where length is calculated as the lexeme count.
</li></ul>
<ul class="items"><li>(2b) For sorting all other GLs, longer lines beat shorter lines.
</li></ul>
<ul class="items"><li>(3) Mistaken commands beat unmistaken commands.
</li></ul>
<ul class="items"><li>(4) Higher GSBs beat lower GSBs.
</li></ul>
<ul class="items"><li>(5a) Fewer resulting values beat more resulting values.
</li></ul>
<ul class="items"><li>(5b1) A narrower first result type beats a wider first result type, if
there is a first result.
</li></ul>
<ul class="items"><li>(5b2) A multiples-disallowed first result type beats a multiples-allowed
first result type, if there is a first result.
</li></ul>
<ul class="items"><li>(5c1) A narrower second result type beats a wider second result type, if
there is a second result.
</li></ul>
<ul class="items"><li>(5c2) A multiples-disallowed second result type beats a multiples-allowed
second result type, if there is a second result.
</li></ul>
<ul class="items"><li>(6) Conditional lines (with a "when" proviso, that is) beat
unconditional lines.
</li></ul>
<ul class="items"><li>(7) The grammar line defined earlier beats the one defined later.
</li></ul>
<p class="inwebparagraph">Rule 1 is intended to resolve awkward ambiguities involved with command
grammar which includes "[text]" tokens. Each such token subtracts 10000 from
the USB of a line but adds back 100 times the token position (which is at least
0 and which we can safely suppose is less than 99: we truncate just in case
so that every <code class="display"><span class="extract">"[text]"</span></code> certainly makes a negative contribution of at least
-100) and then subtracts off the number of tokens left on the line.
</p>
<p class="inwebparagraph">Because a high USB gets priority, and "[text]" tokens make a negative
contribution, the effect is to relegate lines containing "[text]" tokens
to the bottom of the list &mdash; which is good because "[text]" voraciously
eats up words, matching more or less anything, so that any remotely
specific case ought to be tried first. The effect of the curious addition
back in of the token position is that later-placed "[text]" tokens are
tried before earlier-placed ones. Thus <code class="display"><span class="extract">"read chapter [text]"</span></code> has a USB
of -98, and takes precedence over <code class="display"><span class="extract">"read [text]"</span></code> with a USB of -99,
but both are beaten by just <code class="display"><span class="extract">"read [something]"</span></code> with a USB of 0.
The effect of the subtraction back of the number of tokens remaining
is to ensure that <code class="display"><span class="extract">"read [token] backwards"</span></code> takes priority over
<code class="display"><span class="extract">"read [token]"</span></code>.
</p>
<p class="inwebparagraph">The voracity of <code class="display"><span class="extract">"[text]"</span></code>, and its tendency to block out all other
possibilities unless restrained, has to be addressed by this lexically
based numerical calculation because it works in a lexical sort of way:
playing with the types system to prefer <code class="display"><span class="extract">DESCRIPTION/UNDERSTANDING</span></code>
over, say, <code class="display"><span class="extract">VALUE/OBJECT</span></code> would not be sufficient.
</p>
<p class="inwebparagraph">The most surprising point here is the asymmetry in rule 2, which basically
says that when parsing commands typed at the keyboard, shorter beats longer,
whereas in all other settings longer beats shorter. This arises because the
I6 parser, at run time, traditionally works that way: I6 command grammars
are normally stored with short forms first and long forms afterward. The
I6 parser can afford to do this because it is matching text of known length:
if parsing TAKE FROG FROM AQUARIUM, it will try TAKE FROG first but is able
to reject this as not matching the whole text. In other parsing settings,
we are trying to make a maximum-length match against a potentially infinite
stream of words, and it is therefore important to try to match WATERY
CASCADE EFFECT before WATERY CASCADE when looking at text like WATERY
CASCADE EFFECT IMPRESSES PEOPLE, given that the simplistic parsers we
compile generally return the first match found.
</p>
<p class="inwebparagraph">Rule 3, that mistakes beat non-mistakes, was in fact rule 1 during 2006: it
seemed logical that since mistakes were exceptional cases, they would be
better checked earlier before moving on to general cases. However, an
example provided by Eric Eve showed that although this was logically correct,
the I6 parser would try to auto-complete lengthy mistakes and thus fail to
check subsequent commands. For this reason, <code class="display"><span class="extract">"look behind [something]"</span></code>
as a mistake needs to be checked after <code class="display"><span class="extract">"look"</span></code>, or else the I6 parser
will respond to the command LOOK by replying "What do you want to look
behind?" &mdash; and then saying that you are mistaken.
</p>
<p class="inwebparagraph">Rule 4 is intended as a lexeme-based tiebreaker. We only get here if there
are the same number of lexemes in the two GLs being compared. Each is
given a GSB score as follows: a literal lexeme, which produces no result,
such as <code class="display"><span class="extract">"draw"</span></code> or <code class="display"><span class="extract">"in/inside/within"</span></code>, scores 100; all other lexemes
score as follows:
</p>
<p class="inwebparagraph">&mdash; <code class="display"><span class="extract">"[things inside]"</span></code> scores a GSB of 10 as the first parameter, 1 as the second;
</p>
<p class="inwebparagraph">&mdash; <code class="display"><span class="extract">"[things preferably held]"</span></code> similarly scores a GSB of 20 or 2;
</p>
<p class="inwebparagraph">&mdash; <code class="display"><span class="extract">"[other things]"</span></code> similarly scores a GSB of 20 or 2;
</p>
<p class="inwebparagraph">&mdash; <code class="display"><span class="extract">"[something preferably held]"</span></code> similarly scores a GSB of 30 or 3;
</p>
<p class="inwebparagraph">&mdash; any token giving a logical description of some class of objects, such as
<code class="display"><span class="extract">"[open container]"</span></code>, similarly scores a GSB of 50 or 5;
</p>
<p class="inwebparagraph">&mdash; and any remaining token (for instance, one matching a number or some other
kind of value) scores a GSB of 0.
</p>
<p class="inwebparagraph">Literals score highly because they are structural, and differentiate
cases: under the superset rule, <code class="display"><span class="extract">"look up [thing]"</span></code> must be parsed before
<code class="display"><span class="extract">"look [direction] [thing]"</span></code>, and it is only the number of literals which
differentiates these cases. If two lines have an equal number of literals,
we now look at the first resultant lexeme. Here we find that a lexeme which
specifies an object (with a GSB of at least 10/1) beats a lexeme which only
specifies a value. Thus the same text will be parsed against objects in
preference to values, which is sensible since there are generally few
objects available to the player and they are generally likely to be the
things being referred to. Among possible object descriptions, the very
general catch-all special cases above are given lower GSB scores than
more specific ones, to enable the more specific cases to go first.
</p>
<p class="inwebparagraph">Rule 5a is unlikely to have much effect: it is likely to be rare for GL
lists to contain GLs mixing different numbers of results. But Rule 5b1
is very significant: it causes <code class="display"><span class="extract">"draw [animal]"</span></code> to have precedence over
<code class="display"><span class="extract">"draw [thing]"</span></code>, for instance. Rule 5b2 ensures that <code class="display"><span class="extract">"draw [thing]"</span></code>
takes precedence over <code class="display"><span class="extract">"draw [things]"</span></code>, which may be useful to handle
multiple and single objects differently.
</p>
<p class="inwebparagraph">The motivation for rule 6 is similar to the case of "when" clauses for
rules in rulebooks: it ensures that a match of <code class="display"><span class="extract">"draw [thing]"</span></code> when some
condition holds beats a match of <code class="display"><span class="extract">"draw [thing]"</span></code> at any time, and this is
necessary under the strict superset principle.
</p>
<p class="inwebparagraph">To get to rule 7 looks difficult, given the number of things about the
grammar lines which must match up &mdash; same USB, GSB, number of lexemes,
number of resulting types, equivalent resulting types, same conditional
status &mdash; but in fact it isn't all that uncommon. Equivalent pairs produced
by the Standard Rules include:
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">"get off [something]"</span></code> and <code class="display"><span class="extract">"get in/into/on/onto [something]"</span></code>
</p>
<p class="inwebparagraph"><code class="display"><span class="extract">"turn on [something]"</span></code> and <code class="display"><span class="extract">"turn [something] on"</span></code>
</p>
<p class="inwebparagraph">Only the second of these pairs leads to ambiguity, and even then only if
an object has a name like ON VISION ON &mdash; perhaps a book about the antique
BBC children's television programme "Vision On" &mdash; so that the command
TURN ON VISION ON would match both of the alternative GLs.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::grammar_line_must_precede</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">L1</span><span class="plain">, </span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">L2</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">cs</span><span class="plain">, </span><span class="identifier">a</span><span class="plain">, </span><span class="identifier">b</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">L1</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) || (</span><span class="identifier">L2</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">))</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to sort null GLs"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain"> == -1) || (</span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain"> == -1))</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to sort unslashed GLs"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;general_sort_bonus</span><span class="plain"> == </span><span class="constant">UNCALCULATED_BONUS</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;general_sort_bonus</span><span class="plain"> == </span><span class="constant">UNCALCULATED_BONUS</span><span class="plain">))</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to sort uncalculated GLs"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L1</span><span class="plain"> == </span><span class="identifier">L2</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">a</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">L1</span><span class="plain">-</span><span class="element">&gt;resulting_action</span><span class="plain">) || (</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;mistaken</span><span class="plain">)) </span><span class="identifier">a</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">b</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">L2</span><span class="plain">-</span><span class="element">&gt;resulting_action</span><span class="plain">) || (</span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;mistaken</span><span class="plain">)) </span><span class="identifier">b</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">a</span><span class="plain"> != </span><span class="identifier">b</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"L1 = $g\</span><span class="plain">n</span><span class="string">L2 = $g\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">L1</span><span class="plain">, </span><span class="identifier">L2</span><span class="plain">);</span>
<span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to sort on incomparable GLs"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;understanding_sort_bonus</span><span class="plain"> &gt; </span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;understanding_sort_bonus</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;understanding_sort_bonus</span><span class="plain"> &lt; </span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;understanding_sort_bonus</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">a</span><span class="plain">) { </span> <span class="comment">command grammar: shorter beats longer</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain"> &lt; </span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain"> &gt; </span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> { </span> <span class="comment">all other grammars: longer beats shorter</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain"> &lt; </span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain"> &gt; </span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;lexeme_count</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;mistaken</span><span class="plain">) &amp;&amp; (</span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;mistaken</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="reserved">if</span><span class="plain"> ((</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;mistaken</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;mistaken</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;general_sort_bonus</span><span class="plain"> &gt; </span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;general_sort_bonus</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;general_sort_bonus</span><span class="plain"> &lt; </span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;general_sort_bonus</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">cs</span><span class="plain"> = </span><span class="functiontext">PL::Parsing::Tokens::Types::must_precede</span><span class="plain">(&amp;(</span><span class="identifier">L1</span><span class="plain">-</span><span class="element">&gt;gl_type</span><span class="plain">), &amp;(</span><span class="identifier">L2</span><span class="plain">-</span><span class="element">&gt;gl_type</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">cs</span><span class="plain"> != </span><span class="identifier">NOT_APPLICABLE</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">cs</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">PL::Parsing::Lines::conditional</span><span class="plain">(</span><span class="identifier">L1</span><span class="plain">)) &amp;&amp; (</span><span class="functiontext">PL::Parsing::Lines::conditional</span><span class="plain">(</span><span class="identifier">L2</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="reserved">if</span><span class="plain"> ((</span><span class="functiontext">PL::Parsing::Lines::conditional</span><span class="plain">(</span><span class="identifier">L1</span><span class="plain">) == </span><span class="identifier">FALSE</span><span class="plain">) &amp;&amp; (</span><span class="functiontext">PL::Parsing::Lines::conditional</span><span class="plain">(</span><span class="identifier">L2</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">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::grammar_line_must_precede is used in <a href="#SP16">&#167;16</a>.</p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. Phase IV: Compile Grammar. </b>At this level we compile the list of GLs in sorted order: this is what the
sorting was all for. In certain cases, we skip any GLs marked as "one word":
these are cases arising from, e.g., "Understand "frog" as the toad.",
where we noticed that the GL was a single word and included it in the <code class="display"><span class="extract">name</span></code>
property instead. This is faster and more flexible, besides writing tidier
code.
</p>
<p class="inwebparagraph">The need for this is not immediately obvious. After all, shouldn't we have
simply deleted the GL in the first place, rather than leaving it in but
marking it? The answer is no, because of the way inheritance works: values
of the <code class="display"><span class="extract">name</span></code> property accumulate from class to instance in I6, since
<code class="display"><span class="extract">name</span></code> is additive, but grammar doesn't.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::sorted_line_list_compile</span><span class="plain">(</span><span class="reserved">gpr_kit</span><span class="plain"> *</span><span class="identifier">gprk</span><span class="plain">, </span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">list_head</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">gv_is</span><span class="plain">, </span><span class="reserved">grammar_verb</span><span class="plain"> *</span><span class="identifier">gv</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">genuinely_verbal</span><span class="plain">) {</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">list_head</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;sorted_next_line</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;suppress_compilation</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)</span>
<span class="functiontext">PL::Parsing::Lines::compile_grammar_line</span><span class="plain">(</span><span class="identifier">gprk</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">, </span><span class="identifier">gv_is</span><span class="plain">, </span><span class="identifier">gv</span><span class="plain">, </span><span class="identifier">genuinely_verbal</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::sorted_line_list_compile is used in 5/gv (<a href="5-gv.html#SP29">&#167;29</a>).</p>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. </b>The following apparently global variables are used to provide a persistent
state for the routine below, but are not accessed elsewhere. The label
counter is reset at the start of each GV's compilation, though this is a
purely cosmetic effect.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">current_grammar_block</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">current_label</span><span class="plain"> = 1;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">GV_IS_VALUE_instance_mode</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">PL::Parsing::Lines::reset_labels</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">current_label</span><span class="plain"> = 1;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::reset_labels is used in 5/gv (<a href="5-gv.html#SP27">&#167;27</a>).</p>
<p class="inwebparagraph"><a id="SP20"></a><b>&#167;20. </b>As fancy as the following routine may look, it contains very little.
What complexity there is comes from the fact that command GVs are compiled
very differently to all others (most grammars are compiled in "code mode",
generating procedural I6 statements, but command GVs are compiled to lines
in <code class="display"><span class="extract">Verb</span></code> directives) and that GLs resulting in actions (i.e., GLs in
command GVs) have not yet been type-checked, whereas all others have.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::compile_grammar_line</span><span class="plain">(</span><span class="reserved">gpr_kit</span><span class="plain"> *</span><span class="identifier">gprk</span><span class="plain">, </span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">gv_is</span><span class="plain">, </span><span class="reserved">grammar_verb</span><span class="plain"> *</span><span class="identifier">gv</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">genuinely_verbal</span><span class="plain">) {</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">i</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">token_values</span><span class="plain">;</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">token_value_kinds</span><span class="plain">[2];</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">code_mode</span><span class="plain">, </span><span class="identifier">consult_mode</span><span class="plain">;</span>
<span class="identifier">LOGIF</span><span class="plain">(</span><span class="identifier">GRAMMAR</span><span class="plain">, </span><span class="string">"Compiling grammar line: $g\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">);</span>
<span class="identifier">current_sentence</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;where_grammar_specified</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gv_is</span><span class="plain"> == </span><span class="constant">GV_IS_COMMAND</span><span class="plain">) </span><span class="identifier">code_mode</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">code_mode</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gv_is</span><span class="plain"> == </span><span class="constant">GV_IS_CONSULT</span><span class="plain">) </span><span class="identifier">consult_mode</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">; </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">consult_mode</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">gv_is</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">GV_IS_COMMAND</span><span class="plain">:</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">GV_IS_TOKEN</span><span class="plain">:</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">GV_IS_CONSULT</span><span class="plain">:</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">GV_IS_OBJECT</span><span class="plain">:</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">GV_IS_VALUE</span><span class="plain">:</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">GV_IS_PROPERTY_NAME</span><span class="plain">:</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">default</span><span class="plain">: </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to compile unknown GV type"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">current_grammar_block</span><span class="plain">++;</span>
<span class="identifier">token_values</span><span class="plain"> = 0;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">i</span><span class="plain">=0; </span><span class="identifier">i</span><span class="plain">&lt;2; </span><span class="identifier">i</span><span class="plain">++) </span><span class="identifier">token_value_kinds</span><span class="plain">[</span><span class="identifier">i</span><span class="plain">] = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">code_mode</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="identifier">Emit::array_iname_entry</span><span class="plain">(</span><span class="identifier">VERB_DIRECTIVE_DIVIDER_iname</span><span class="plain">);</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">fail_label</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gprk</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">, </span><span class="string">".Fail_%d"</span><span class="plain">, </span><span class="identifier">current_label</span><span class="plain">);</span>
<span class="identifier">fail_label</span><span class="plain"> = </span><span class="identifier">Produce::reserve_label</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">PL::Parsing::Lines::gl_compile_extra_token_for_condition</span><span class="plain">(</span><span class="identifier">gprk</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">, </span><span class="identifier">gv_is</span><span class="plain">, </span><span class="identifier">fail_label</span><span class="plain">);</span>
<span class="functiontext">PL::Parsing::Lines::gl_compile_extra_token_for_mistake</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">, </span><span class="identifier">gv_is</span><span class="plain">);</span>
<span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;tokens</span><span class="plain">-&gt;</span><span class="identifier">down</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">genuinely_verbal</span><span class="plain">) &amp;&amp; (</span><span class="identifier">pn</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">) != 0) {</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_SlashedCommand</span><span class="plain">),</span>
<span class="string">"at present you're not allowed to use a / between command "</span>
<span class="string">"words at the start of a line"</span><span class="plain">,</span>
<span class="string">"so 'put/interpose/insert [something]' is out."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">; </span> <span class="comment">skip command word: the <code class="display"><span class="extract">Verb</span></code> header contains it already</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">gv_is</span><span class="plain"> == </span><span class="constant">GV_IS_VALUE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">GV_IS_VALUE_instance_mode</span><span class="plain">)) {</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">IF_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">EQ_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;instance_s</span><span class="plain">);</span>
<span class="functiontext">PL::Parsing::Tokens::Types::compile_to_string</span><span class="plain">(&amp;(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;gl_type</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::code</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="plain">}</span>
<span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">pn_from</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">, *</span><span class="identifier">pn_to</span><span class="plain"> = </span><span class="identifier">pn_from</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) </span><span class="identifier">pn_to</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="functiontext">PL::Parsing::Lines::compile_token_line</span><span class="plain">(</span><span class="identifier">gprk</span><span class="plain">, </span><span class="identifier">code_mode</span><span class="plain">, </span><span class="identifier">pn_from</span><span class="plain">, </span><span class="identifier">pn_to</span><span class="plain">, </span><span class="identifier">gv_is</span><span class="plain">, </span><span class="identifier">consult_mode</span><span class="plain">, &amp;</span><span class="identifier">token_values</span><span class="plain">, </span><span class="identifier">token_value_kinds</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">fail_label</span><span class="plain">);</span>
<span class="reserved">switch</span><span class="plain"> (</span><span class="identifier">gv_is</span><span class="plain">) {</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">GV_IS_COMMAND</span><span class="plain">:</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::Parsing::Lines::gl_compile_result_of_mistake</span><span class="plain">(</span><span class="identifier">gprk</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">)) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="identifier">Emit::array_iname_entry</span><span class="plain">(</span><span class="identifier">VERB_DIRECTIVE_RESULT_iname</span><span class="plain">);</span>
<span class="identifier">Emit::array_action_entry</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;resulting_action</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;reversed</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">token_values</span><span class="plain"> &lt; 2) {</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_CantReverseOne</span><span class="plain">),</span>
<span class="string">"you can't use a 'reversed' action when you supply fewer "</span>
<span class="string">"than two values for it to apply to"</span><span class="plain">,</span>
<span class="string">"since reversal is the process of exchanging them."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">swap</span><span class="plain"> = </span><span class="identifier">token_value_kinds</span><span class="plain">[0];</span>
<span class="identifier">token_value_kinds</span><span class="plain">[0] = </span><span class="identifier">token_value_kinds</span><span class="plain">[1];</span>
<span class="identifier">token_value_kinds</span><span class="plain">[1] = </span><span class="identifier">swap</span><span class="plain">;</span>
<span class="identifier">Emit::array_iname_entry</span><span class="plain">(</span><span class="identifier">VERB_DIRECTIVE_REVERSE_iname</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="functiontext">PL::Actions::check_types_for_grammar</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;resulting_action</span><span class="plain">, </span><span class="identifier">token_values</span><span class="plain">,</span>
<span class="identifier">token_value_kinds</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">GV_IS_PROPERTY_NAME</span><span class="plain">:</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">GV_IS_TOKEN</span><span class="plain">:</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">RETURN_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;rv_s</span><span class="plain">);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::place_label</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">fail_label</span><span class="plain">);</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">STORE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::ref_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;rv_s</span><span class="plain">);</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">GPR_PREPOSITION_HL</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">STORE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::ref_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">WN_HL</span><span class="plain">));</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;original_wn_s</span><span class="plain">);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">GV_IS_CONSULT</span><span class="plain">:</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">IF_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">OR_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">EQ_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;range_words_s</span><span class="plain">);</span>
<span class="identifier">Produce::val</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_number</span><span class="plain">, </span><span class="identifier">LITERAL_IVAL</span><span class="plain">, 0);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">EQ_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">MINUS_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">WN_HL</span><span class="plain">));</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;range_from_s</span><span class="plain">);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;range_words_s</span><span class="plain">);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::code</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">RETURN_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;rv_s</span><span class="plain">);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::place_label</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">fail_label</span><span class="plain">);</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">STORE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::ref_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;rv_s</span><span class="plain">);</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">GPR_PREPOSITION_HL</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">STORE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::ref_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">WN_HL</span><span class="plain">));</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;original_wn_s</span><span class="plain">);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">GV_IS_OBJECT</span><span class="plain">:</span>
<span class="functiontext">PL::Parsing::Tokens::General::after_gl_failed</span><span class="plain">(</span><span class="identifier">gprk</span><span class="plain">, </span><span class="identifier">fail_label</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;pluralised</span><span class="plain">);</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="reserved">case</span><span class="plain"> </span><span class="constant">GV_IS_VALUE</span><span class="plain">:</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">STORE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::ref_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">PARSED_NUMBER_HL</span><span class="plain">));</span>
<span class="functiontext">PL::Parsing::Tokens::Types::compile_to_string</span><span class="plain">(&amp;(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;gl_type</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">RETURN_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_object</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">GPR_NUMBER_HL</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::place_label</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">fail_label</span><span class="plain">);</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">STORE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::ref_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">WN_HL</span><span class="plain">));</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;original_wn_s</span><span class="plain">);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">gv_is</span><span class="plain"> == </span><span class="constant">GV_IS_VALUE</span><span class="plain">) &amp;&amp; (</span><span class="identifier">GV_IS_VALUE_instance_mode</span><span class="plain">)) {</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="plain">}</span>
<span class="identifier">current_label</span><span class="plain">++;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::compile_token_line</span><span class="plain">(</span><span class="reserved">gpr_kit</span><span class="plain"> *</span><span class="identifier">gprk</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">code_mode</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">parse_node</span><span class="plain"> *</span><span class="identifier">pn_to</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">gv_is</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">consult_mode</span><span class="plain">,</span>
<span class="reserved">int</span><span class="plain"> *</span><span class="identifier">token_values</span><span class="plain">, </span><span class="identifier">kind</span><span class="plain"> **</span><span class="identifier">token_value_kinds</span><span class="plain">, </span><span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">group_wn_s</span><span class="plain">, </span><span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">fail_label</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">lexeme_equivalence_class</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">alternative_number</span><span class="plain"> = 0;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">empty_text_allowed_in_lexeme</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">next_reserved_label</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">eog_reserved_label</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (; </span><span class="identifier">pn</span><span class="plain">; </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="functiontext">PL::Parsing::Tokens::is_text</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">)) &amp;&amp; (</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="functiontext">PL::Parsing::Tokens::is_literal</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</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="identifier">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_TextFollowedBy</span><span class="plain">),</span>
<span class="string">"a '[text]' token must either match the end of some text, or "</span>
<span class="string">"be followed by definitely known wording"</span><span class="plain">,</span>
<span class="string">"since otherwise the run-time parser isn't good enough to "</span>
<span class="string">"make sense of things."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ParseTree::get_grammar_token_relation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">)) &amp;&amp; (</span><span class="identifier">gv_is</span><span class="plain"> != </span><span class="constant">GV_IS_OBJECT</span><span class="plain">)) {</span>
<span class="identifier">Problems::Issue::sentence_problem</span><span class="plain">(</span><span class="identifier">Task::syntax_tree</span><span class="plain">(), </span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">PM_GrammarObjectlessRelation</span><span class="plain">),</span>
<span class="string">"a grammar token in an 'Understand...' can only be based "</span>
<span class="string">"on a relation if it is to understand the name of a room or thing"</span><span class="plain">,</span>
<span class="string">"since otherwise there is nothing for the relation to be with."</span><span class="plain">);</span>
<span class="reserved">continue</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">first_token_in_lexeme</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">last_token_in_lexeme</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">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">) != 0) { </span> <span class="comment">in a multi-token lexeme</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) ||</span>
<span class="plain">(</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">) !=</span>
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">)))</span>
<span class="identifier">last_token_in_lexeme</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">) != </span><span class="identifier">lexeme_equivalence_class</span><span class="plain">) {</span>
<span class="identifier">first_token_in_lexeme</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">empty_text_allowed_in_lexeme</span><span class="plain"> =</span>
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">slash_dash_dash_ANNOT</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">lexeme_equivalence_class</span><span class="plain"> = </span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first_token_in_lexeme</span><span class="plain">) </span><span class="identifier">alternative_number</span><span class="plain"> = 1;</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">alternative_number</span><span class="plain">++;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> { </span> <span class="comment">in a single-token lexeme</span>
<span class="identifier">lexeme_equivalence_class</span><span class="plain"> = 0;</span>
<span class="identifier">first_token_in_lexeme</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">last_token_in_lexeme</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">empty_text_allowed_in_lexeme</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">alternative_number</span><span class="plain"> = 1;</span>
<span class="plain">}</span>
<span class="identifier">inter_symbol</span><span class="plain"> *</span><span class="identifier">jump_on_fail</span><span class="plain"> = </span><span class="identifier">fail_label</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lexeme_equivalence_class</span><span class="plain"> &gt; 0) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">code_mode</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first_token_in_lexeme</span><span class="plain">) {</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">STORE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::ref_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;group_wn_s</span><span class="plain">);</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">WN_HL</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">next_reserved_label</span><span class="plain">) </span><span class="identifier">Produce::place_label</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">next_reserved_label</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">, </span><span class="string">".group_%d_%d_%d"</span><span class="plain">, </span><span class="identifier">current_grammar_block</span><span class="plain">, </span><span class="identifier">lexeme_equivalence_class</span><span class="plain">, </span><span class="identifier">alternative_number</span><span class="plain">+1);</span>
<span class="identifier">next_reserved_label</span><span class="plain"> = </span><span class="identifier">Produce::reserve_label</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">STORE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::ref_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">WN_HL</span><span class="plain">));</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;group_wn_s</span><span class="plain">);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">last_token_in_lexeme</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) || (</span><span class="identifier">empty_text_allowed_in_lexeme</span><span class="plain">)) {</span>
<span class="identifier">jump_on_fail</span><span class="plain"> = </span><span class="identifier">next_reserved_label</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">empty_text_allowed_in_lexeme</span><span class="plain">) &amp;&amp; (</span><span class="identifier">code_mode</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">)) {</span>
<span class="reserved">slash_gpr</span><span class="plain"> *</span><span class="identifier">sgpr</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">slash_gpr</span><span class="plain">);</span>
<span class="identifier">sgpr</span><span class="plain">-</span><span class="element">&gt;first_choice</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> ((</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">) ==</span>
<span class="identifier">ParseTree::int_annotation</span><span class="plain">(</span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">slash_class_ANNOT</span><span class="plain">))) </span><span class="identifier">pn</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="identifier">sgpr</span><span class="plain">-</span><span class="element">&gt;last_choice</span><span class="plain"> = </span><span class="identifier">pn</span><span class="plain">;</span>
<span class="identifier">package_request</span><span class="plain"> *</span><span class="identifier">PR</span><span class="plain"> = </span><span class="identifier">Hierarchy::local_package</span><span class="plain">(</span><span class="identifier">SLASH_TOKENS_HAP</span><span class="plain">);</span>
<span class="identifier">sgpr</span><span class="plain">-</span><span class="element">&gt;sgpr_iname</span><span class="plain"> = </span><span class="identifier">Hierarchy::make_iname_in</span><span class="plain">(</span><span class="identifier">SLASH_FN_HL</span><span class="plain">, </span><span class="identifier">PR</span><span class="plain">);</span>
<span class="identifier">Emit::array_iname_entry</span><span class="plain">(</span><span class="identifier">sgpr</span><span class="plain">-</span><span class="element">&gt;sgpr_iname</span><span class="plain">);</span>
<span class="identifier">last_token_in_lexeme</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">grammar_token_kind</span><span class="plain"> =</span>
<span class="functiontext">PL::Parsing::Tokens::compile</span><span class="plain">(</span><span class="identifier">gprk</span><span class="plain">, </span><span class="identifier">pn</span><span class="plain">, </span><span class="identifier">code_mode</span><span class="plain">, </span><span class="identifier">jump_on_fail</span><span class="plain">, </span><span class="identifier">consult_mode</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">grammar_token_kind</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">token_values</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (*</span><span class="identifier">token_values</span><span class="plain"> == 2) {</span>
<span class="identifier">internal_error</span><span class="plain">(</span>
<span class="string">"There can be at most two value-producing tokens and this "</span>
<span class="string">"should have been detected earlier."</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">token_value_kinds</span><span class="plain">[(*</span><span class="identifier">token_values</span><span class="plain">)++] = </span><span class="identifier">grammar_token_kind</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">lexeme_equivalence_class</span><span class="plain"> &gt; 0) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">code_mode</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">last_token_in_lexeme</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">empty_text_allowed_in_lexeme</span><span class="plain">) {</span>
&lt;<span class="cwebmacro">Jump to end of group</span> <span class="cwebmacronumber">20.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">next_reserved_label</span><span class="plain">)</span>
<span class="identifier">Produce::place_label</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">next_reserved_label</span><span class="plain">);</span>
<span class="identifier">next_reserved_label</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">STORE_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::ref_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">WN_HL</span><span class="plain">));</span>
<span class="identifier">Produce::val_symbol</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">gprk</span><span class="plain">-</span><span class="element">&gt;group_wn_s</span><span class="plain">);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eog_reserved_label</span><span class="plain">) </span><span class="identifier">Produce::place_label</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">eog_reserved_label</span><span class="plain">);</span>
<span class="identifier">eog_reserved_label</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
&lt;<span class="cwebmacro">Jump to end of group</span> <span class="cwebmacronumber">20.1</span>&gt;<span class="plain">;</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">last_token_in_lexeme</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span><span class="identifier">Emit::array_iname_entry</span><span class="plain">(</span><span class="identifier">VERB_DIRECTIVE_SLASH_iname</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pn</span><span class="plain"> == </span><span class="identifier">pn_to</span><span class="plain">) </span><span class="reserved">break</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::compile_grammar_line is used in <a href="#SP18">&#167;18</a>.</p>
<p class="endnote">The function PL::Parsing::Lines::compile_token_line is used in <a href="#SP21">&#167;21</a>.</p>
<p class="inwebparagraph"><a id="SP20_1"></a><b>&#167;20.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Jump to end of group</span> <span class="cwebmacronumber">20.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">eog_reserved_label</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">L</span><span class="plain">, </span><span class="string">".group_%d_%d_end"</span><span class="plain">,</span>
<span class="identifier">current_grammar_block</span><span class="plain">, </span><span class="identifier">lexeme_equivalence_class</span><span class="plain">);</span>
<span class="identifier">eog_reserved_label</span><span class="plain"> = </span><span class="identifier">Produce::reserve_label</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">L</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">JUMP_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::lab</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">eog_reserved_label</span><span class="plain">);</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP20">&#167;20</a> (twice).</p>
<p class="inwebparagraph"><a id="SP21"></a><b>&#167;21. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::compile_slash_gprs</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">slash_gpr</span><span class="plain"> *</span><span class="identifier">sgpr</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">sgpr</span><span class="plain">, </span><span class="reserved">slash_gpr</span><span class="plain">) {</span>
<span class="identifier">packaging_state</span><span class="plain"> </span><span class="identifier">save</span><span class="plain"> = </span><span class="identifier">Routines::begin</span><span class="plain">(</span><span class="identifier">sgpr</span><span class="plain">-</span><span class="element">&gt;sgpr_iname</span><span class="plain">);</span>
<span class="reserved">gpr_kit</span><span class="plain"> </span><span class="identifier">gprk</span><span class="plain"> = </span><span class="functiontext">PL::Parsing::Tokens::Values::new_kit</span><span class="plain">();</span>
<span class="functiontext">PL::Parsing::Tokens::Values::add_original</span><span class="plain">(&amp;</span><span class="identifier">gprk</span><span class="plain">);</span>
<span class="functiontext">PL::Parsing::Tokens::Values::add_standard_set</span><span class="plain">(&amp;</span><span class="identifier">gprk</span><span class="plain">);</span>
<span class="functiontext">PL::Parsing::Lines::compile_token_line</span><span class="plain">(&amp;</span><span class="identifier">gprk</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">, </span><span class="identifier">sgpr</span><span class="plain">-</span><span class="element">&gt;first_choice</span><span class="plain">, </span><span class="identifier">sgpr</span><span class="plain">-</span><span class="element">&gt;last_choice</span><span class="plain">, </span><span class="constant">GV_IS_TOKEN</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">, </span><span class="identifier">gprk</span><span class="element">.group_wn_s</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">Produce::inv_primitive</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">RETURN_BIP</span><span class="plain">);</span>
<span class="identifier">Produce::down</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Produce::val_iname</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">(), </span><span class="identifier">K_value</span><span class="plain">, </span><span class="identifier">Hierarchy::find</span><span class="plain">(</span><span class="identifier">GPR_PREPOSITION_HL</span><span class="plain">));</span>
<span class="identifier">Produce::up</span><span class="plain">(</span><span class="identifier">Emit::tree</span><span class="plain">());</span>
<span class="identifier">Routines::end</span><span class="plain">(</span><span class="identifier">save</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::compile_slash_gprs is used in 5/gv (<a href="5-gv.html#SP26">&#167;26</a>).</p>
<p class="inwebparagraph"><a id="SP22"></a><b>&#167;22. Indexing by grammar. </b>This is the more obvious form of indexing: we show the grammar lines which
make up an individual GL. (For instance, this is used in the Actions index
to show the grammar for an individual command word, by calling the routine
below for that command word's GV.) Such an index list is done in sorted
order, so that the order of appearance in the index corresponds to the
order of parsing &mdash; this is what the reader of the index is interested in.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::sorted_list_index_normal</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">,</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">list_head</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">headword</span><span class="plain">) {</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">list_head</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;sorted_next_line</span><span class="plain">)</span>
<span class="functiontext">PL::Parsing::Lines::gl_index_normal</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">, </span><span class="identifier">headword</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::gl_index_normal</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">, </span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">headword</span><span class="plain">) {</span>
<span class="reserved">action_name</span><span class="plain"> *</span><span class="identifier">an</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;resulting_action</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">an</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="reserved">return</span><span class="plain">;</span>
<span class="identifier">Index::anchor</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">headword</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::Actions::is_out_of_world</span><span class="plain">(</span><span class="identifier">an</span><span class="plain">))</span>
<span class="identifier">HTML::begin_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"800000"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;quot;"</span><span class="plain">);</span>
<span class="functiontext">PL::Actions::Index::verb_definition</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">Lexer::word_text</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;original_text</span><span class="plain">),</span>
<span class="identifier">headword</span><span class="plain">, </span><span class="identifier">EMPTY_WORDING</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;quot;"</span><span class="plain">);</span>
<span class="identifier">Index::link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;original_text</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" - &lt;i&gt;%+W"</span><span class="plain">, </span><span class="identifier">an</span><span class="plain">-</span><span class="element">&gt;present_name</span><span class="plain">);</span>
<span class="identifier">Index::detail_link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="string">"A"</span><span class="plain">, </span><span class="identifier">an</span><span class="plain">-&gt;</span><span class="identifier">allocation_id</span><span class="plain">, </span><span class="identifier">TRUE</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;reversed</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" (reversed)"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&lt;/i&gt;"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="functiontext">PL::Actions::is_out_of_world</span><span class="plain">(</span><span class="identifier">an</span><span class="plain">))</span>
<span class="identifier">HTML::end_colour</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">);</span>
<span class="identifier">HTML_TAG</span><span class="plain">(</span><span class="string">"br"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::sorted_list_index_normal is used in 5/gv (<a href="5-gv.html#SP12">&#167;12</a>).</p>
<p class="endnote">The function PL::Parsing::Lines::gl_index_normal appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP23"></a><b>&#167;23. Indexing by action. </b>Grammar lines are typically indexed twice: the other time is when all
grammar lines belonging to a given action are tabulated. Special linked
lists are kept for this purpose, and this is where we unravel them and
print to the index. The question of sorted vs unsorted is meaningless
here, since the GLs appearing in such a list will typically belong to
several different GVs. (As it happens, they appear in order of creation,
i.e., in source text order.)
</p>
<p class="inwebparagraph">Tiresomely, all of this means that we need to store "uphill" pointers
in GLs: back up to the GVs that own them. The following routine does
this for a whole list of GLs:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::list_assert_ownership</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">list_head</span><span class="plain">, </span><span class="reserved">grammar_verb</span><span class="plain"> *</span><span class="identifier">gv</span><span class="plain">) {</span>
<span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">list_head</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain">; </span><span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;next_line</span><span class="plain">)</span>
<span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;belongs_to_gv</span><span class="plain"> = </span><span class="identifier">gv</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::list_assert_ownership is used in 5/gv (<a href="5-gv.html#SP29">&#167;29</a>).</p>
<p class="inwebparagraph"><a id="SP24"></a><b>&#167;24. </b>And this routine accumulates the per-action lists of GLs:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::list_with_action_add</span><span class="plain">(</span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">list_head</span><span class="plain">, </span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">list_head</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">internal_error</span><span class="plain">(</span><span class="string">"tried to add to null action list"</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">list_head</span><span class="plain">-</span><span class="element">&gt;next_with_action</span><span class="plain">)</span>
<span class="identifier">list_head</span><span class="plain"> = </span><span class="identifier">list_head</span><span class="plain">-</span><span class="element">&gt;next_with_action</span><span class="plain">;</span>
<span class="identifier">list_head</span><span class="plain">-</span><span class="element">&gt;next_with_action</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::list_with_action_add is used in 4/act (<a href="4-act.html#SP34">&#167;34</a>).</p>
<p class="inwebparagraph"><a id="SP25"></a><b>&#167;25. </b>Finally, here we index an action list of GLs, each getting a line in
the HTML index.
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::index_list_with_action</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">said_something</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain"> != </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;belongs_to_gv</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">VW</span><span class="plain"> = </span><span class="functiontext">PL::Parsing::Verbs::get_verb_text</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;belongs_to_gv</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">trueverb</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">VW</span><span class="plain">))</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">trueverb</span><span class="plain">, </span><span class="string">"%W"</span><span class="plain">, </span><span class="identifier">Wordings::one_word</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">VW</span><span class="plain">)));</span>
<span class="identifier">HTMLFiles::open_para</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 2, </span><span class="string">"hanging"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;quot;"</span><span class="plain">);</span>
<span class="functiontext">PL::Actions::Index::verb_definition</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">,</span>
<span class="identifier">Lexer::word_text</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;original_text</span><span class="plain">), </span><span class="identifier">trueverb</span><span class="plain">, </span><span class="identifier">VW</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;quot;"</span><span class="plain">);</span>
<span class="identifier">Index::link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;original_text</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;reversed</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" &lt;i&gt;reversed&lt;/i&gt;"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="identifier">said_something</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">trueverb</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;next_with_action</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">said_something</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::index_list_with_action is used in 4/act (<a href="4-act.html#SP39">&#167;39</a>).</p>
<p class="inwebparagraph"><a id="SP26"></a><b>&#167;26. </b>And the same, but more simply:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">PL::Parsing::Lines::index_list_for_token</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">grammar_line</span><span class="plain"> *</span><span class="identifier">gl</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">k</span><span class="plain"> = 0;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain"> != </span><span class="identifier">NULL</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;belongs_to_gv</span><span class="plain">) {</span>
<span class="identifier">wording</span><span class="plain"> </span><span class="identifier">VW</span><span class="plain"> = </span><span class="functiontext">PL::Parsing::Verbs::get_verb_text</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;belongs_to_gv</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">trueverb</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">VW</span><span class="plain">))</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">trueverb</span><span class="plain">, </span><span class="string">"%W"</span><span class="plain">, </span><span class="identifier">Wordings::one_word</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">VW</span><span class="plain">)));</span>
<span class="identifier">HTMLFiles::open_para</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, 2, </span><span class="string">"hanging"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">k</span><span class="plain">++ == 0) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"="</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">"or"</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" &amp;quot;"</span><span class="plain">);</span>
<span class="functiontext">PL::Actions::Index::verb_definition</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">,</span>
<span class="identifier">Lexer::word_text</span><span class="plain">(</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;original_text</span><span class="plain">), </span><span class="identifier">trueverb</span><span class="plain">, </span><span class="identifier">EMPTY_WORDING</span><span class="plain">);</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"&amp;quot;"</span><span class="plain">);</span>
<span class="identifier">Index::link</span><span class="plain">(</span><span class="identifier">OUT</span><span class="plain">, </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;original_text</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;reversed</span><span class="plain">) </span><span class="identifier">WRITE</span><span class="plain">(</span><span class="string">" &lt;i&gt;reversed&lt;/i&gt;"</span><span class="plain">);</span>
<span class="identifier">HTML_CLOSE</span><span class="plain">(</span><span class="string">"p"</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">trueverb</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">gl</span><span class="plain"> = </span><span class="identifier">gl</span><span class="plain">-</span><span class="element">&gt;sorted_next_line</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function PL::Parsing::Lines::index_list_for_token is used in 5/gv (<a href="5-gv.html#SP14">&#167;14</a>).</p>
<hr class="tocbar">
<ul class="toc"><li><a href="5-gv.html">Back to 'Grammar Verbs'</a></li><li><a href="5-gt.html">Continue with 'Grammar Types'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</main>
</body>
</html>