1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/inflections-module/2-np.html
2019-04-22 15:42:10 +01:00

392 lines
45 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>2/ld</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="inweb.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body>
<!--Weave of '2/np' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">inflections</a></li><li><a href="index.html#2">Chapter 2: Machinery</a></li><li><b>Non-Parsing Preform</b></li></ul><p class="purpose">Other uses for Preform grammar, including the generation of adaptive text, and word inflection.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Introduction</a></li><li><a href="#SP2">&#167;2. (a) Specifying generated text</a></li><li><a href="#SP5">&#167;5. (b) Specifying replacements</a></li><li><a href="#SP6">&#167;6. (c) Lexicon entry</a></li><li><a href="#SP7">&#167;7. (d) Making tries</a></li></ul><hr class="tocbar">
<p class="inwebparagraph"><a id="SP1"></a><b>&#167;1. Introduction. </b>Looked at more generally, Preform isn't just a parser syntax: it's a general-purpose way to specify
textual patterns, so we may as well take advantage of it for miscellaneous
other needs. There are altogether five non-parsing uses for Preform; in
order of complexity,
</p>
<p class="inwebparagraph"></p>
<ul class="items"><li>(a) Specifying text being generated by Inform;
</li></ul>
<ul class="items"><li>(b) Specifying replacements of one set of words by another;
</li></ul>
<ul class="items"><li>(c) Specifying miscellaneous entries for the lexicon in the index;
</li></ul>
<ul class="items"><li>(d) Saying how to build a trie which will detect patterns in a single word and
then modify it;
</li></ul>
<ul class="items"><li>(e) Saying how to conjugate a verb, that is, how to modify the wording of a
verb ("take", say) into all of its different forms (I take, he takes, it was
taken, I am taking, and so on). This we'll leave for later.
</li></ul>
<p class="inwebparagraph">Speed is not of the essence in any of these problems.
</p>
<p class="inwebparagraph"><a id="SP2"></a><b>&#167;2. (a) Specifying generated text. </b>Our main operation here is a "merge". This extracts the text from a production,
substituting the ingredient text in place of any <code class="display"><span class="extract">...</span></code> it finds. (Other
wildcards and nonterminals are ignored.) For example, merging the production
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">fried ... tomatoes</span>
</pre>
<p class="inwebparagraph">with "orange" results in "fried orange tomatoes".
</p>
<pre class="display">
<span class="identifier">word_assemblage</span><span class="plain"> </span><span class="functiontext">Preform::Nonparsing::merge</span><span class="plain">(</span><span class="identifier">nonterminal</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">pnum</span><span class="plain">, </span><span class="identifier">word_assemblage</span><span class="plain"> </span><span class="identifier">ingredient</span><span class="plain">) {</span>
<span class="identifier">production_list</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain"> = </span><span class="identifier">nt</span><span class="plain">-&gt;</span><span class="identifier">first_production_list</span><span class="plain">; </span><span class="identifier">pl</span><span class="plain">; </span><span class="identifier">pl</span><span class="plain"> = </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">next_production_list</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">N</span><span class="plain"> = 0;</span>
<span class="identifier">production</span><span class="plain"> *</span><span class="identifier">pr</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pr</span><span class="plain"> = </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">first_production</span><span class="plain">; </span><span class="identifier">pr</span><span class="plain">; </span><span class="identifier">pr</span><span class="plain"> = </span><span class="identifier">pr</span><span class="plain">-&gt;</span><span class="identifier">next_production</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">N</span><span class="plain"> == </span><span class="identifier">pnum</span><span class="plain">) {</span>
<span class="identifier">word_assemblage</span><span class="plain"> </span><span class="identifier">wa</span><span class="plain"> = </span><span class="identifier">WordAssemblages::lit_0</span><span class="plain">();</span>
<span class="identifier">ptoken</span><span class="plain"> *</span><span class="identifier">pt</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain"> = </span><span class="identifier">pr</span><span class="plain">-&gt;</span><span class="identifier">first_ptoken</span><span class="plain">; </span><span class="identifier">pt</span><span class="plain">; </span><span class="identifier">pt</span><span class="plain"> = </span><span class="identifier">pt</span><span class="plain">-&gt;</span><span class="identifier">next_ptoken</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain">-&gt;</span><span class="identifier">ptoken_category</span><span class="plain"> == </span><span class="identifier">FIXED_WORD_PTC</span><span class="plain">) {</span>
<span class="identifier">wa</span><span class="plain"> = </span><span class="identifier">WordAssemblages::join</span><span class="plain">(</span><span class="identifier">wa</span><span class="plain">, </span><span class="identifier">WordAssemblages::lit_1</span><span class="plain">(</span><span class="identifier">pt</span><span class="plain">-&gt;</span><span class="identifier">ve_pt</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">pt</span><span class="plain">-&gt;</span><span class="identifier">ptoken_category</span><span class="plain"> == </span><span class="identifier">MULTIPLE_WILDCARD_PTC</span><span class="plain">) {</span>
<span class="identifier">wa</span><span class="plain"> = </span><span class="identifier">WordAssemblages::join</span><span class="plain">(</span><span class="identifier">wa</span><span class="plain">, </span><span class="identifier">ingredient</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">wa</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="identifier">N</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">WordAssemblages::lit_0</span><span class="plain">(); </span> <span class="comment">give up, in other words</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Preform::Nonparsing::merge is used in <a href="#SP3">&#167;3</a>, <a href="#SP4">&#167;4</a>, 3/ga (<a href="3-ga.html#SP2">&#167;2</a>).</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Thus we can simply extract the wording by performing a merge with the empty
ingredient text:
</p>
<pre class="display">
<span class="identifier">word_assemblage</span><span class="plain"> </span><span class="functiontext">Preform::Nonparsing::wording</span><span class="plain">(</span><span class="identifier">nonterminal</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">pnum</span><span class="plain">) {</span>
<span class="reserved">return</span><span class="plain"> </span><span class="functiontext">Preform::Nonparsing::merge</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">pnum</span><span class="plain">, </span><span class="identifier">WordAssemblages::lit_0</span><span class="plain">());</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Preform::Nonparsing::wording appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>And here we take just one word:
</p>
<pre class="display">
<span class="identifier">vocabulary_entry</span><span class="plain"> *</span><span class="functiontext">Preform::Nonparsing::word</span><span class="plain">(</span><span class="identifier">nonterminal</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">pnum</span><span class="plain">) {</span>
<span class="identifier">word_assemblage</span><span class="plain"> </span><span class="identifier">wa</span><span class="plain"> = </span><span class="functiontext">Preform::Nonparsing::merge</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">pnum</span><span class="plain">, </span><span class="identifier">WordAssemblages::lit_0</span><span class="plain">());</span>
<span class="identifier">vocabulary_entry</span><span class="plain"> **</span><span class="identifier">words</span><span class="plain">;</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">num_words</span><span class="plain">;</span>
<span class="identifier">WordAssemblages::as_array</span><span class="plain">(&amp;</span><span class="identifier">wa</span><span class="plain">, &amp;</span><span class="identifier">words</span><span class="plain">, &amp;</span><span class="identifier">num_words</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">num_words</span><span class="plain"> == 1) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">words</span><span class="plain">[0];</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Preform::Nonparsing::word appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. (b) Specifying replacements. </b>The following looks for a word in one nonterminal and replaces it with the
corresponding word in another. If the word isn't found, it's left unchanged.
</p>
<pre class="display">
<span class="identifier">vocabulary_entry</span><span class="plain"> *</span><span class="functiontext">Preform::Nonparsing::replace_word</span><span class="plain">(</span><span class="identifier">vocabulary_entry</span><span class="plain"> *</span><span class="identifier">ve</span><span class="plain">,</span>
<span class="identifier">nonterminal</span><span class="plain"> *</span><span class="identifier">nt_from</span><span class="plain">, </span><span class="identifier">nonterminal</span><span class="plain"> *</span><span class="identifier">nt_to</span><span class="plain">) {</span>
<span class="identifier">production_list</span><span class="plain"> *</span><span class="identifier">pl_from</span><span class="plain">, *</span><span class="identifier">pl_to</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pl_from</span><span class="plain"> = </span><span class="identifier">nt_from</span><span class="plain">-&gt;</span><span class="identifier">first_production_list</span><span class="plain">,</span>
<span class="identifier">pl_to</span><span class="plain"> = </span><span class="identifier">nt_to</span><span class="plain">-&gt;</span><span class="identifier">first_production_list</span><span class="plain">;</span>
<span class="plain">((</span><span class="identifier">pl_from</span><span class="plain">) &amp;&amp; (</span><span class="identifier">pl_to</span><span class="plain">));</span>
<span class="identifier">pl_from</span><span class="plain"> = </span><span class="identifier">pl_from</span><span class="plain">-&gt;</span><span class="identifier">next_production_list</span><span class="plain">,</span>
<span class="identifier">pl_to</span><span class="plain"> = </span><span class="identifier">pl_to</span><span class="plain">-&gt;</span><span class="identifier">next_production_list</span><span class="plain">) {</span>
<span class="identifier">production</span><span class="plain"> *</span><span class="identifier">pr_from</span><span class="plain">, *</span><span class="identifier">pr_to</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pr_from</span><span class="plain"> = </span><span class="identifier">pl_from</span><span class="plain">-&gt;</span><span class="identifier">first_production</span><span class="plain">,</span>
<span class="identifier">pr_to</span><span class="plain"> = </span><span class="identifier">pl_to</span><span class="plain">-&gt;</span><span class="identifier">first_production</span><span class="plain">;</span>
<span class="plain">((</span><span class="identifier">pr_from</span><span class="plain">) &amp;&amp; (</span><span class="identifier">pr_to</span><span class="plain">));</span>
<span class="identifier">pr_from</span><span class="plain"> = </span><span class="identifier">pr_from</span><span class="plain">-&gt;</span><span class="identifier">next_production</span><span class="plain">,</span>
<span class="identifier">pr_to</span><span class="plain"> = </span><span class="identifier">pr_to</span><span class="plain">-&gt;</span><span class="identifier">next_production</span><span class="plain">) {</span>
<span class="identifier">ptoken</span><span class="plain"> *</span><span class="identifier">pt_from</span><span class="plain">, *</span><span class="identifier">pt_to</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pt_from</span><span class="plain"> = </span><span class="identifier">pr_from</span><span class="plain">-&gt;</span><span class="identifier">first_ptoken</span><span class="plain">,</span>
<span class="identifier">pt_to</span><span class="plain"> = </span><span class="identifier">pr_to</span><span class="plain">-&gt;</span><span class="identifier">first_ptoken</span><span class="plain">;</span>
<span class="plain">((</span><span class="identifier">pt_from</span><span class="plain">) &amp;&amp; (</span><span class="identifier">pt_to</span><span class="plain">));</span>
<span class="identifier">pt_from</span><span class="plain"> = </span><span class="identifier">pt_from</span><span class="plain">-&gt;</span><span class="identifier">next_ptoken</span><span class="plain">,</span>
<span class="identifier">pt_to</span><span class="plain"> = </span><span class="identifier">pt_to</span><span class="plain">-&gt;</span><span class="identifier">next_ptoken</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">pt_from</span><span class="plain">-&gt;</span><span class="identifier">ptoken_category</span><span class="plain"> == </span><span class="identifier">FIXED_WORD_PTC</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">pt_to</span><span class="plain">-&gt;</span><span class="identifier">ptoken_category</span><span class="plain"> == </span><span class="identifier">FIXED_WORD_PTC</span><span class="plain">)) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ve</span><span class="plain"> == </span><span class="identifier">pt_from</span><span class="plain">-&gt;</span><span class="identifier">ve_pt</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">pt_to</span><span class="plain">-&gt;</span><span class="identifier">ve_pt</span><span class="plain">;</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">ve</span><span class="plain">; </span> <span class="comment">no change, in other words</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Preform::Nonparsing::replace_word appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. (c) Lexicon entry. </b>This is only a convenience for putting particles into the Lexicon:
</p>
<pre class="display">
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">CORE_MODULE</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Preform::Nonparsing::enter_lexicon</span><span class="plain">(</span><span class="identifier">nonterminal</span><span class="plain"> *</span><span class="identifier">nt_from</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">pos</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">category</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">gloss</span><span class="plain">) {</span>
<span class="identifier">production_list</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain"> = </span><span class="identifier">nt_from</span><span class="plain">-&gt;</span><span class="identifier">first_production_list</span><span class="plain">; </span><span class="identifier">pl</span><span class="plain">; </span><span class="identifier">pl</span><span class="plain"> = </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">next_production_list</span><span class="plain">) {</span>
<span class="identifier">production</span><span class="plain"> *</span><span class="identifier">pr</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pr</span><span class="plain"> = </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">first_production</span><span class="plain">; </span><span class="identifier">pr</span><span class="plain">; </span><span class="identifier">pr</span><span class="plain"> = </span><span class="identifier">pr</span><span class="plain">-&gt;</span><span class="identifier">next_production</span><span class="plain">) {</span>
<span class="identifier">ptoken</span><span class="plain"> *</span><span class="identifier">pt</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pt</span><span class="plain"> = </span><span class="identifier">pr</span><span class="plain">-&gt;</span><span class="identifier">first_ptoken</span><span class="plain">; </span><span class="identifier">pt</span><span class="plain">; </span><span class="identifier">pt</span><span class="plain"> = </span><span class="identifier">pt</span><span class="plain">-&gt;</span><span class="identifier">next_ptoken</span><span class="plain">) {</span>
<span class="identifier">ptoken</span><span class="plain"> *</span><span class="identifier">alt</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">alt</span><span class="plain"> = </span><span class="identifier">pt</span><span class="plain">; </span><span class="identifier">alt</span><span class="plain">; </span><span class="identifier">alt</span><span class="plain"> = </span><span class="identifier">alt</span><span class="plain">-&gt;</span><span class="identifier">alternative_ptoken</span><span class="plain">) {</span>
<span class="identifier">vocabulary_entry</span><span class="plain"> *</span><span class="identifier">ve</span><span class="plain"> = </span><span class="identifier">alt</span><span class="plain">-&gt;</span><span class="identifier">ve_pt</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ve</span><span class="plain">) {</span>
<span class="identifier">Index::Lexicon::new_entry_with_details</span><span class="plain">(</span><span class="identifier">EMPTY_WORDING</span><span class="plain">, </span><span class="identifier">pos</span><span class="plain">,</span>
<span class="identifier">WordAssemblages::lit_1</span><span class="plain">(</span><span class="identifier">ve</span><span class="plain">), </span><span class="identifier">category</span><span class="plain">, </span><span class="identifier">gloss</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Preform::Nonparsing::enter_lexicon appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. (d) Making tries. </b>Properly speaking, we make "avinues". Note that we expect to make a different
avinue for each natural language; this matters so that we can pluralise words
correctly in both English and French in the same run of Inform, for example.
But we are going to need to use these avinues frequently, so we cache them once
created.
</p>
<pre class="display">
<span class="identifier">match_avinue</span><span class="plain"> *</span><span class="functiontext">Preform::Nonparsing::define_trie</span><span class="plain">(</span><span class="identifier">nonterminal</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">, </span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">end</span><span class="plain">, </span><span class="identifier">PREFORM_LANGUAGE_TYPE</span><span class="plain"> *</span><span class="identifier">nl</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nl</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">nl</span><span class="plain"> = </span><span class="identifier">English_language</span><span class="plain">;</span>
<span class="identifier">match_avinue</span><span class="plain"> *</span><span class="identifier">ave</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">;</span>
<span class="identifier">production_list</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain"> = </span><span class="identifier">nt</span><span class="plain">-&gt;</span><span class="identifier">first_production_list</span><span class="plain">; </span><span class="identifier">pl</span><span class="plain">; </span><span class="identifier">pl</span><span class="plain"> = </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">next_production_list</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">definition_language</span><span class="plain"> == </span><span class="identifier">nl</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">as_avinue</span><span class="plain">) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">as_avinue</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Construct a new avinue from this nonterminal</span> <span class="cwebmacronumber">7.1</span>&gt;<span class="plain">;</span>
<span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">as_avinue</span><span class="plain"> = </span><span class="identifier">ave</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">ave</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function Preform::Nonparsing::define_trie is used in <a href="#SP7_1_1_2">&#167;7.1.1.2</a>, 2/nc (<a href="2-nc.html#SP4_1_1">&#167;4.1.1</a>), 3/ai (<a href="3-ai.html#SP1">&#167;1</a>), 3/dcl (<a href="3-dcl.html#SP3">&#167;3</a>), 3/plr (<a href="3-plr.html#SP4">&#167;4</a>), 3/ga (<a href="3-ga.html#SP2">&#167;2</a>, <a href="3-ga.html#SP3">&#167;3</a>), 3/pp (<a href="3-pp.html#SP2">&#167;2</a>), 3/vc (<a href="3-vc.html#SP4_2_1">&#167;4.2.1</a>).</p>
<p class="inwebparagraph"><a id="SP7_1"></a><b>&#167;7.1. </b>The grammar for this nonterminal is either a "list grammar", meaning that it
lists other nonterminals which each define avinues, and we have to string those
together into one long avinue; or else it contains the actual content of a
single avinue.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Construct a new avinue from this nonterminal</span> <span class="cwebmacronumber">7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">list_grammar</span><span class="plain"> = </span><span class="identifier">NOT_APPLICABLE</span><span class="plain">; </span> <span class="comment">i.e., we don't know yet</span>
<span class="identifier">production</span><span class="plain"> *</span><span class="identifier">pr</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pr</span><span class="plain"> = </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">first_production</span><span class="plain">; </span><span class="identifier">pr</span><span class="plain">; </span><span class="identifier">pr</span><span class="plain"> = </span><span class="identifier">pr</span><span class="plain">-&gt;</span><span class="identifier">next_production</span><span class="plain">) {</span>
<span class="identifier">ptoken</span><span class="plain"> *</span><span class="identifier">first</span><span class="plain"> = </span><span class="identifier">pr</span><span class="plain">-&gt;</span><span class="identifier">first_ptoken</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">first</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="identifier">ptoken</span><span class="plain"> *</span><span class="identifier">second</span><span class="plain"> = </span><span class="identifier">first</span><span class="plain">-&gt;</span><span class="identifier">next_ptoken</span><span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">second</span><span class="plain">) &amp;&amp; (</span><span class="identifier">second</span><span class="plain">-&gt;</span><span class="identifier">next_ptoken</span><span class="plain">)) {</span>
<span class="identifier">Preform::log_production</span><span class="plain">(</span><span class="identifier">pr</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">);</span>
<span class="functiontext">Conjugation::trie_definition_error</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">pr</span><span class="plain">, </span><span class="string">"trie line with more than 2 words"</span><span class="plain">);</span>
<span class="plain">}</span>
&lt;<span class="cwebmacro">Consider the one- or two-token production in this nonterminal</span> <span class="cwebmacronumber">7.1.1</span>&gt;<span class="plain">;</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_1_1"></a><b>&#167;7.1.1. </b>Each production contains one or two tokens. There are four possibilities for
the production:
</p>
<p class="inwebparagraph"></p>
<pre class="display">
<span class="plain">(1) ... &lt;some-nonterminal&gt;</span>
<span class="plain">(2) &lt;some-nonterminal&gt; ...</span>
<span class="plain">(3) &lt;some-nonterminal&gt;</span>
<span class="plain">(4) pattern-word instructions-word</span>
</pre>
<p class="inwebparagraph">Cases (1), (2) and (3) are allowed only in list grammars; case (4) is allowed
only in content grammars. The <code class="display"><span class="extract">...</span></code> indicates whether the trie in the named
nonterminal will act on the start or end of a word &mdash; this is needed only to
override the normal convention.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Consider the one- or two-token production in this nonterminal</span> <span class="cwebmacronumber">7.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">this_end</span><span class="plain"> = </span><span class="identifier">end</span><span class="plain">;</span>
<span class="identifier">ptoken</span><span class="plain"> *</span><span class="identifier">entry</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">first</span><span class="plain">-&gt;</span><span class="identifier">ptoken_category</span><span class="plain"> == </span><span class="identifier">MULTIPLE_WILDCARD_PTC</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">second</span><span class="plain">) &amp;&amp; (</span><span class="identifier">second</span><span class="plain">-&gt;</span><span class="identifier">ptoken_category</span><span class="plain"> == </span><span class="identifier">NONTERMINAL_PTC</span><span class="plain">)) {</span>
<span class="identifier">entry</span><span class="plain"> = </span><span class="identifier">second</span><span class="plain">; </span><span class="identifier">this_end</span><span class="plain"> = </span><span class="identifier">TRIE_END</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">first</span><span class="plain">-&gt;</span><span class="identifier">ptoken_category</span><span class="plain"> == </span><span class="identifier">NONTERMINAL_PTC</span><span class="plain">) &amp;&amp;</span>
<span class="plain">(</span><span class="identifier">second</span><span class="plain">) &amp;&amp; (</span><span class="identifier">second</span><span class="plain">-&gt;</span><span class="identifier">ptoken_category</span><span class="plain"> == </span><span class="identifier">MULTIPLE_WILDCARD_PTC</span><span class="plain">)) {</span>
<span class="identifier">entry</span><span class="plain"> = </span><span class="identifier">first</span><span class="plain">; </span><span class="identifier">this_end</span><span class="plain"> = </span><span class="identifier">TRIE_START</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">first</span><span class="plain">-&gt;</span><span class="identifier">ptoken_category</span><span class="plain"> == </span><span class="identifier">NONTERMINAL_PTC</span><span class="plain">) &amp;&amp; (</span><span class="identifier">second</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)) {</span>
<span class="identifier">entry</span><span class="plain"> = </span><span class="identifier">first</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">entry</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">list_grammar</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) </span>&lt;<span class="cwebmacro">Throw problem for a mixed trie nonterminal</span> <span class="cwebmacronumber">7.1.1.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Recurse to make an avinue from the nonterminal named here, and add it to our result</span> <span class="cwebmacronumber">7.1.1.2</span>&gt;<span class="plain">;</span>
<span class="identifier">list_grammar</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="reserved">if</span><span class="plain"> (</span><span class="identifier">list_grammar</span><span class="plain"> == </span><span class="identifier">TRUE</span><span class="plain">) </span>&lt;<span class="cwebmacro">Throw problem for a mixed trie nonterminal</span> <span class="cwebmacronumber">7.1.1.1</span>&gt;<span class="plain">;</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">second</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="functiontext">Conjugation::trie_definition_error</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">pr</span><span class="plain">,</span>
<span class="string">"there should be two words here, a pattern and an instruction"</span><span class="plain">);</span>
&lt;<span class="cwebmacro">Add this pattern and instruction to the trie, creating it if we haven't already started one</span> <span class="cwebmacronumber">7.1.1.3</span>&gt;<span class="character">;</span>
<span class="identifier">list_grammar</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_1">&#167;7.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_1_1_1"></a><b>&#167;7.1.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Throw problem for a mixed trie nonterminal</span> <span class="cwebmacronumber">7.1.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="functiontext">Conjugation::trie_definition_error</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">pr</span><span class="plain">,</span>
<span class="string">"this should either be a list of other nonterminals, or a list of patterns "</span>
<span class="string">"and instructions, but not a mixture"</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_1_1">&#167;7.1.1</a> (twice).</p>
<p class="inwebparagraph"><a id="SP7_1_1_2"></a><b>&#167;7.1.1.2. </b><code class="display">
&lt;<span class="cwebmacrodefn">Recurse to make an avinue from the nonterminal named here, and add it to our result</span> <span class="cwebmacronumber">7.1.1.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">match_avinue</span><span class="plain"> *</span><span class="identifier">next_mt</span><span class="plain"> =</span>
<span class="identifier">Tries::duplicate_avinue</span><span class="plain">(</span><span class="functiontext">Preform::Nonparsing::define_trie</span><span class="plain">(</span><span class="identifier">entry</span><span class="plain">-&gt;</span><span class="identifier">nt_pt</span><span class="plain">, </span><span class="identifier">this_end</span><span class="plain">, </span><span class="identifier">nl</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ave</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">ave</span><span class="plain"> = </span><span class="identifier">next_mt</span><span class="plain">;</span>
<span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">match_avinue</span><span class="plain"> *</span><span class="identifier">m</span><span class="plain"> = </span><span class="identifier">ave</span><span class="plain">;</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">m</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">) </span><span class="identifier">m</span><span class="plain"> = </span><span class="identifier">m</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain">;</span>
<span class="identifier">m</span><span class="plain">-</span><span class="element">&gt;next</span><span class="plain"> = </span><span class="identifier">next_mt</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_1_1">&#167;7.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_1_1_3"></a><b>&#167;7.1.1.3. </b><code class="display">
&lt;<span class="cwebmacrodefn">Add this pattern and instruction to the trie, creating it if we haven't already started one</span> <span class="cwebmacronumber">7.1.1.3</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ave</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) </span><span class="identifier">ave</span><span class="plain"> = </span><span class="identifier">Tries::new_avinue</span><span class="plain">(</span><span class="identifier">end</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">, </span><span class="string">"%V"</span><span class="plain">, </span><span class="identifier">first</span><span class="plain">-&gt;</span><span class="identifier">ve_pt</span><span class="plain">);</span>
<span class="identifier">Tries::add_to_avinue</span><span class="plain">(</span><span class="identifier">ave</span><span class="plain">, </span><span class="identifier">from</span><span class="plain">, </span><span class="identifier">Vocabulary::get_exemplar</span><span class="plain">(</span><span class="identifier">second</span><span class="plain">-&gt;</span><span class="identifier">ve_pt</span><span class="plain">, </span><span class="identifier">FALSE</span><span class="plain">));</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">from</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_1_1">&#167;7.1.1</a>.</p>
<p class="inwebparagraph"><a id="SP8"></a><b>&#167;8. </b>The following may be useful for debugging:
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">Preform::Nonparsing::log_avinues</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="identifier">nonterminal</span><span class="plain"> *</span><span class="identifier">nt</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">nt</span><span class="plain">, </span><span class="identifier">nonterminal</span><span class="plain">) {</span>
<span class="identifier">production_list</span><span class="plain"> *</span><span class="identifier">pl</span><span class="plain">;</span>
<span class="reserved">for</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain"> = </span><span class="identifier">nt</span><span class="plain">-&gt;</span><span class="identifier">first_production_list</span><span class="plain">; </span><span class="identifier">pl</span><span class="plain">; </span><span class="identifier">pl</span><span class="plain"> = </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">next_production_list</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">as_avinue</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">\</span><span class="plain">n</span><span class="string">%V ($J)\</span><span class="plain">n</span><span class="string">%a"</span><span class="plain">,</span>
<span class="identifier">nt</span><span class="plain">-&gt;</span><span class="identifier">nonterminal_id</span><span class="plain">, </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">definition_language</span><span class="plain">, </span><span class="identifier">pl</span><span class="plain">-&gt;</span><span class="identifier">as_avinue</span><span class="plain">);</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 Preform::Nonparsing::log_avinues appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="2-ld.html">Back to 'Linguistic Definitions'</a></li><li><a href="2-tai.html">Continue with 'Tries and Inflections'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>