1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/docs/core-module/3-nl.html
2019-10-02 23:04:15 +01:00

571 lines
58 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>3/rst</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 '3/nl' generated by 7-->
<ul class="crumbs"><li><a href="../webs.html">&#9733;</a></li><li><a href="index.html">core</a></li><li><a href="index.html#3">Chapter 3: Bridge to Words Module</a></li><li><b>Natural Languages</b></li></ul><p class="purpose">To manage definitions of natural languages, such as English or French, which may be used either to write Inform or to read the works it compiles.</p>
<ul class="toc"><li><a href="#SP1">&#167;1. Definitions</a></li><li><a href="#SP7">&#167;7. The bundle scan</a></li><li><a href="#SP10">&#167;10. Finding by name</a></li><li><a href="#SP11">&#167;11. Logging</a></li><li><a href="#SP12">&#167;12. Naming</a></li><li><a href="#SP13">&#167;13. Parsing</a></li><li><a href="#SP14">&#167;14. The natural language kind</a></li><li><a href="#SP15">&#167;15. The adaptive person</a></li><li><a href="#SP16">&#167;16. Choice of languages</a></li><li><a href="#SP17">&#167;17. Language code</a></li><li><a href="#SP18">&#167;18. Including language extensions</a></li><li><a href="#SP19">&#167;19. Including Preform syntax</a></li><li><a href="#SP20">&#167;20. Preform error handling</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>Inform can read and write text in multiple natural languages, though it
needs help to do so. Each natural language known to Inform comes from a
small resource folder called its "bundle", and also has an extension
associated with it: this includes English. Bundles for common languages
are included as part of the default distribution for Inform, but the
extension is only included for English.
</p>
<p class="inwebparagraph"><a id="SP3"></a><b>&#167;3. </b>Within the bundle folder is a file called <code class="display"><span class="extract">about.txt</span></code>, which sets numbered
fields to excerpts of text. The following are the field numbers:
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">NAME_IN_ENGLISH_LFIELD</span><span class="plain"> 1 </span> <span class="comment">e.g. "German"</span>
<span class="definitionkeyword">define</span> <span class="constant">NAME_NATIVE_LFIELD</span><span class="plain"> 2 </span> <span class="comment">e.g. "Deutsch"</span>
<span class="definitionkeyword">define</span> <span class="constant">CUE_NATIVE_LFIELD</span><span class="plain"> 3 </span> <span class="comment">e.g. "in deutscher Sprache"</span>
<span class="definitionkeyword">define</span> <span class="constant">ISO_639_CODE_LFIELD</span><span class="plain"> 4 </span> <span class="comment">e.g. "de": an ISO 639-1 code</span>
<span class="definitionkeyword">define</span> <span class="constant">TRANSLATOR_LFIELD</span><span class="plain"> 5 </span> <span class="comment">e.g. "Team GerX"</span>
<span class="definitionkeyword">define</span> <span class="constant">MAX_LANGUAGE_FIELDS</span><span class="plain"> 6 </span> <span class="comment">one more than the highest number above</span>
</pre>
<p class="inwebparagraph"><a id="SP4"></a><b>&#167;4. </b>Each natural language whose bundle can be located generates an instance
of the following structure.
</p>
<p class="inwebparagraph">Note that each NL automatically defines an instance of the kind "natural
language". For timing reasons, we first store the name of this instance &mdash;
say, "German language" &mdash; and only later create the instance.
</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">natural_language</span><span class="plain"> {</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">pathname</span><span class="plain"> *</span><span class="identifier">nl_bundle_path</span><span class="plain">; </span> <span class="comment">pathname of the bundle folder</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">instance_name</span><span class="plain">; </span> <span class="comment">instance name, e.g., "German language"</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">nl_instance</span><span class="plain">; </span> <span class="comment">instance, e.g., "German language"</span>
<span class="reserved">struct</span><span class="plain"> </span><span class="identifier">wording</span><span class="plain"> </span><span class="identifier">language_field</span><span class="plain">[</span><span class="constant">MAX_LANGUAGE_FIELDS</span><span class="plain">]; </span> <span class="comment">contents of the <code class="display"><span class="extract">about.txt</span></code> fields</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">extension_required</span><span class="plain">; </span> <span class="comment">do we need to Include the extension for this language?</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">adaptive_person</span><span class="plain">; </span> <span class="comment">which person (one of constants below) text subs are written from</span>
<span class="identifier">MEMORY_MANAGEMENT</span>
<span class="plain">} </span><span class="reserved">natural_language</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The structure natural_language is private to this section.</p>
<p class="inwebparagraph"><a id="SP5"></a><b>&#167;5. </b>The following defaults to English in practice:
</p>
<pre class="display">
<span class="reserved">natural_language</span><span class="plain"> *</span><span class="identifier">language_of_play</span><span class="plain"> = </span><span class="identifier">NULL</span><span class="plain">; </span> <span class="comment">the language read and typed by the player</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP6"></a><b>&#167;6. </b></p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">NATURAL_LANGUAGES_PRESENT</span>
</pre>
<p class="inwebparagraph"><a id="SP7"></a><b>&#167;7. The bundle scan. </b>Early in Inform's run we scan for installed language bundle folders. This is
done on demand (i.e., when we need to know something about languages). We
only want to do it once, and we must prevent it recursing:
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">bundle_scan_made</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">NaturalLanguages::scan</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">bundle_scan_made</span><span class="plain"> == </span><span class="identifier">FALSE</span><span class="plain">) {</span>
<span class="identifier">bundle_scan_made</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
&lt;<span class="cwebmacro">Perform the bundle scan</span> <span class="cwebmacronumber">7.1</span>&gt;<span class="plain">;</span>
&lt;<span class="cwebmacro">Process the bundles scanned in</span> <span class="cwebmacronumber">7.2</span>&gt;<span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function NaturalLanguages::scan is used in <a href="#SP10">&#167;10</a>, 4/its (<a href="4-its.html#SP7">&#167;7</a>).</p>
<p class="inwebparagraph"><a id="SP7_1"></a><b>&#167;7.1. </b>The rules for these are exactly the same as for extensions, or website
templates, so for example the materials folder takes priority. If we find
a bundle with the same name twice (e.g., if we find "German" in two
different locations), the first to be found wins out.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Perform the bundle scan</span> <span class="cwebmacronumber">7.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">for</span><span class="plain"> (</span><span class="reserved">int</span><span class="plain"> </span><span class="identifier">area</span><span class="plain">=0; </span><span class="identifier">area</span><span class="plain">&lt;</span><span class="constant">NO_FS_AREAS</span><span class="plain">; </span><span class="identifier">area</span><span class="plain">++)</span>
<span class="functiontext">NaturalLanguages::scan_bundles_from</span><span class="plain">(</span><span class="identifier">pathname_of_languages</span><span class="plain">[</span><span class="identifier">area</span><span class="plain">], </span><span class="identifier">AREA_NAME</span><span class="plain">[</span><span class="identifier">area</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="SP8"></a><b>&#167;8. </b>The following rather crudely loads a directory listing for the pathname
into a scratch string, then cuts it up into individual names.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">NaturalLanguages::scan_bundles_from</span><span class="plain">(</span><span class="identifier">pathname</span><span class="plain"> *</span><span class="identifier">P</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">origin</span><span class="plain">) {</span>
<span class="identifier">scan_directory</span><span class="plain"> *</span><span class="identifier">sd</span><span class="plain"> = </span><span class="identifier">Directories::open</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">sd</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">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">item</span><span class="plain">);</span>
<span class="reserved">while</span><span class="plain"> (</span><span class="identifier">Directories::next</span><span class="plain">(</span><span class="identifier">sd</span><span class="plain">, </span><span class="identifier">item</span><span class="plain">))</span>
&lt;<span class="cwebmacro">Act on an item in the bundle listing</span> <span class="cwebmacronumber">8.1</span>&gt;<span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">item</span><span class="plain">);</span>
<span class="identifier">Directories::close</span><span class="plain">(</span><span class="identifier">sd</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function NaturalLanguages::scan_bundles_from is used in <a href="#SP7_1">&#167;7.1</a>.</p>
<p class="inwebparagraph"><a id="SP8_1"></a><b>&#167;8.1. </b>We expect each such folder to contain only names of bundles, each of which
should be a single English word, without accents.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Act on an item in the bundle listing</span> <span class="cwebmacronumber">8.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">acceptable</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">LOOP_THROUGH_TEXT</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, </span><span class="identifier">item</span><span class="plain">) {</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">c</span><span class="plain"> = </span><span class="identifier">Str::get</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">c</span><span class="plain"> &lt; 32) || (</span><span class="identifier">c</span><span class="plain"> &gt; 126)) </span><span class="identifier">acceptable</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span> <span class="comment">contains non-ASCII</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">c</span><span class="plain"> == </span><span class="identifier">FOLDER_SEPARATOR</span><span class="plain">) { </span><span class="identifier">Str::put</span><span class="plain">(</span><span class="identifier">pos</span><span class="plain">, 0); </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">Str::len</span><span class="plain">(</span><span class="identifier">item</span><span class="plain">) == 0) </span><span class="identifier">acceptable</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">; </span> <span class="comment">i.e., an empty text</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">acceptable</span><span class="plain">) {</span>
<span class="reserved">natural_language</span><span class="plain"> *</span><span class="identifier">nl</span><span class="plain"> = </span><span class="functiontext">NaturalLanguages::get_nl</span><span class="plain">(</span><span class="identifier">item</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>&lt;<span class="cwebmacro">Create a new natural language structure</span> <span class="cwebmacronumber">8.1.1</span>&gt;<span class="plain">;</span>
<span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;nl_bundle_path</span><span class="plain"> = </span><span class="identifier">Pathnames::subfolder</span><span class="plain">(</span><span class="identifier">P</span><span class="plain">, </span><span class="identifier">item</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Found language bundle '%S' (%s)\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">item</span><span class="plain">, </span><span class="identifier">origin</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8">&#167;8</a>.</p>
<p class="inwebparagraph"><a id="SP8_1_1"></a><b>&#167;8.1.1. </b><code class="display">
&lt;<span class="cwebmacrodefn">Create a new natural language structure</span> <span class="cwebmacronumber">8.1.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">nl</span><span class="plain"> = </span><span class="identifier">CREATE</span><span class="plain">(</span><span class="reserved">natural_language</span><span class="plain">);</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">sentence_format</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">sentence_format</span><span class="plain">, </span><span class="string">"%S language"</span><span class="plain">, </span><span class="identifier">item</span><span class="plain">);</span>
<span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;instance_name</span><span class="plain"> = </span><span class="identifier">Feeds::feed_stream</span><span class="plain">(</span><span class="identifier">sentence_format</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">sentence_format</span><span class="plain">);</span>
<span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;nl_instance</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="element">&gt;extension_required</span><span class="plain"> = </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;adaptive_person</span><span class="plain"> = -1; </span> <span class="comment">i.e., none yet specified</span>
<span class="reserved">for</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">n</span><span class="plain">&lt;</span><span class="constant">MAX_LANGUAGE_FIELDS</span><span class="plain">; </span><span class="identifier">n</span><span class="plain">++) </span><span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;language_field</span><span class="plain">[</span><span class="identifier">n</span><span class="plain">] = </span><span class="identifier">EMPTY_WORDING</span><span class="plain">;</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP8_1">&#167;8.1</a>.</p>
<p class="inwebparagraph"><a id="SP7_2"></a><b>&#167;7.2. </b>At this point, the bundle scan is over. For each bundle we've found, we
read in the <code class="display"><span class="extract">about.txt</span></code> file and extract the excerpts.
</p>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Process the bundles scanned in</span> <span class="cwebmacronumber">7.2</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="reserved">natural_language</span><span class="plain"> *</span><span class="identifier">nl</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">nl</span><span class="plain">, </span><span class="reserved">natural_language</span><span class="plain">)</span>
&lt;<span class="cwebmacro">Read the about.txt file for the bundle</span> <span class="cwebmacronumber">7.2.1</span>&gt;<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_1"></a><b>&#167;7.2.1. </b>If we can't find the file, it doesn't matter except that all of the excerpts
remain empty. But we may as well tell the debugging log.
</p>
<pre class="definitions">
<span class="definitionkeyword">define</span> <span class="constant">MAX_BUNDLE_ABOUT_LINE_LENGTH</span><span class="plain"> 256 </span> <span class="comment">which is far more than necessary, really</span>
</pre>
<p class="macrodefinition"><code class="display">
&lt;<span class="cwebmacrodefn">Read the about.txt file for the bundle</span> <span class="cwebmacronumber">7.2.1</span>&gt; =
</code></p>
<pre class="displaydefn">
<span class="identifier">filename</span><span class="plain"> *</span><span class="identifier">about_file</span><span class="plain"> = </span><span class="identifier">Filenames::in_folder</span><span class="plain">(</span><span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;nl_bundle_path</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"about.txt"</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">TextFiles::read</span><span class="plain">(</span><span class="identifier">about_file</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">FALSE</span><span class="plain">, </span><span class="functiontext">NaturalLanguages::about_helper</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">FALSE</span><span class="plain">)</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Can't find about file: %f\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">about_file</span><span class="plain">);</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">This code is used in <a href="#SP7_2">&#167;7.2</a>.</p>
<p class="inwebparagraph"><a id="SP9"></a><b>&#167;9. </b>The format of the file is very simple. Each line is introduced by a number
from 1 to <code class="display"><span class="extract">MAX_LANGUAGE_FIELDS</span></code> minus one, and then contains text which
extends for the rest of the line.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">NaturalLanguages::about_helper</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">item_name</span><span class="plain">,</span>
<span class="identifier">text_file_position</span><span class="plain"> *</span><span class="identifier">tfp</span><span class="plain">, </span><span class="reserved">void</span><span class="plain"> *</span><span class="identifier">vnl</span><span class="plain">) {</span>
<span class="reserved">natural_language</span><span class="plain"> *</span><span class="identifier">nl</span><span class="plain"> = (</span><span class="reserved">natural_language</span><span class="plain"> *) </span><span class="identifier">vnl</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">Feeds::feed_stream</span><span class="plain">(</span><span class="identifier">item_name</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)) {</span>
<span class="identifier">vocabulary_entry</span><span class="plain"> *</span><span class="identifier">ve</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">W</span><span class="plain">));</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">field</span><span class="plain"> = -1;</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">ve</span><span class="plain">) &amp;&amp; (</span><span class="identifier">Vocabulary::test_vflags</span><span class="plain">(</span><span class="identifier">ve</span><span class="plain">, </span><span class="identifier">NUMBER_MC</span><span class="plain">)))</span>
<span class="identifier">field</span><span class="plain"> = </span><span class="identifier">Vocabulary::get_literal_number_value</span><span class="plain">(</span><span class="identifier">ve</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">field</span><span class="plain"> &gt;= 1) &amp;&amp; (</span><span class="identifier">field</span><span class="plain"> &lt; </span><span class="constant">MAX_LANGUAGE_FIELDS</span><span class="plain">)) {</span>
<span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;language_field</span><span class="plain">[</span><span class="identifier">field</span><span class="plain">] =</span>
<span class="identifier">Wordings::new</span><span class="plain">(</span><span class="identifier">Wordings::first_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">)+1, </span><span class="identifier">Wordings::last_wn</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">));</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Warning: couldn't read about.txt line: %S\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">item_name</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function NaturalLanguages::about_helper is used in <a href="#SP7_2_1">&#167;7.2.1</a>.</p>
<p class="inwebparagraph"><a id="SP10"></a><b>&#167;10. Finding by name. </b>Given the name of a natural language (e.g., "German") we find the
corresponding structure, if it exists. We perform this check case
insensitively.
</p>
<pre class="display">
<span class="reserved">natural_language</span><span class="plain"> *</span><span class="functiontext">NaturalLanguages::get_nl</span><span class="plain">(</span><span class="identifier">text_stream</span><span class="plain"> *</span><span class="identifier">name</span><span class="plain">) {</span>
<span class="functiontext">NaturalLanguages::scan</span><span class="plain">();</span>
<span class="reserved">natural_language</span><span class="plain"> *</span><span class="identifier">nl</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">nl</span><span class="plain">, </span><span class="reserved">natural_language</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">lname</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">lname</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">nl</span><span class="plain">-</span><span class="element">&gt;instance_name</span><span class="plain">)));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Str::eq_insensitive</span><span class="plain">(</span><span class="identifier">name</span><span class="plain">, </span><span class="identifier">lname</span><span class="plain">)) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">nl</span><span class="plain">;</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">lname</span><span class="plain">);</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="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function NaturalLanguages::get_nl is used in <a href="#SP8_1">&#167;8.1</a>, <a href="#SP16">&#167;16</a>.</p>
<p class="inwebparagraph"><a id="SP11"></a><b>&#167;11. Logging. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">NaturalLanguages::log</span><span class="plain">(</span><span class="reserved">natural_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">nl</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">) { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"&lt;null-language&gt;"</span><span class="plain">); }</span>
<span class="reserved">else</span><span class="plain"> { </span><span class="identifier">LOG</span><span class="plain">(</span><span class="string">"%+W"</span><span class="plain">, </span><span class="functiontext">NaturalLanguages::get_name</span><span class="plain">(</span><span class="identifier">nl</span><span class="plain">)); }</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function NaturalLanguages::log is used in 1/cm (<a href="1-cm.html#SP5">&#167;5</a>, <a href="1-cm.html#SP6_6">&#167;6.6</a>).</p>
<p class="inwebparagraph"><a id="SP12"></a><b>&#167;12. Naming. </b></p>
<pre class="display">
<span class="identifier">wording</span><span class="plain"> </span><span class="functiontext">NaturalLanguages::get_name</span><span class="plain">(</span><span class="reserved">natural_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">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="reserved">return</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">nl</span><span class="plain">-</span><span class="element">&gt;instance_name</span><span class="plain">));</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function NaturalLanguages::get_name is used in <a href="#SP11">&#167;11</a>, <a href="#SP18">&#167;18</a>.</p>
<p class="inwebparagraph"><a id="SP13"></a><b>&#167;13. Parsing. </b>The following matches the English-language name of a language: for example,
"French". It will only make a match if Inform has successfully found a
bundle for that language during its initial scan.
</p>
<pre class="display">
<span class="plain">&lt;</span><span class="identifier">natural</span><span class="plain">-</span><span class="identifier">language</span><span class="plain">&gt; </span><span class="identifier">internal</span><span class="plain"> {</span>
<span class="reserved">natural_language</span><span class="plain"> *</span><span class="identifier">nl</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">nl</span><span class="plain">, </span><span class="reserved">natural_language</span><span class="plain">)</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::match</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">Wordings::first_word</span><span class="plain">(</span><span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;instance_name</span><span class="plain">))) {</span>
<span class="plain">*</span><span class="identifier">XP</span><span class="plain"> = </span><span class="identifier">nl</span><span class="plain">; </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">FALSE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="inwebparagraph"><a id="SP14"></a><b>&#167;14. The natural language kind. </b>Inform has a kind built in called "natural language", whose values are
enumerated names: English language, French language, German language and so on.
When the kind is created, the following routine makes these instances. We do
this exactly as we would to create any other instance &mdash; we write a logical
proposition claiming its existence, then assert this to be true. It's an
interesting question whether the possibility of the game having been written
in German "belongs" in the model world, if in fact the game wasn't written
in German; but this is how we'll do it, anyway.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">NaturalLanguages::stock_nl_kind</span><span class="plain">(</span><span class="identifier">kind</span><span class="plain"> *</span><span class="identifier">K</span><span class="plain">) {</span>
<span class="reserved">natural_language</span><span class="plain"> *</span><span class="identifier">nl</span><span class="plain">;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">nl</span><span class="plain">, </span><span class="reserved">natural_language</span><span class="plain">) {</span>
<span class="reserved">pcalc_prop</span><span class="plain"> *</span><span class="identifier">prop</span><span class="plain"> =</span>
<span class="functiontext">Calculus::Propositions::Abstract::to_create_something</span><span class="plain">(</span><span class="identifier">K</span><span class="plain">, </span><span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;instance_name</span><span class="plain">);</span>
<span class="functiontext">Calculus::Propositions::Assert::assert_true</span><span class="plain">(</span><span class="identifier">prop</span><span class="plain">, </span><span class="identifier">CERTAIN_CE</span><span class="plain">);</span>
<span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;nl_instance</span><span class="plain"> = </span><span class="identifier">latest_instance</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function NaturalLanguages::stock_nl_kind appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP15"></a><b>&#167;15. The adaptive person. </b>The following is only relevant for the language of play, whose extension will
always be read in. That in turn is expected to contain a declaration like
this one:
</p>
<blockquote>
<p>The adaptive text viewpoint of the French language is second person singular.</p>
</blockquote>
<p class="inwebparagraph">The following routine picks up on the result of this declaration. (We cache
this because we need access to it very quickly when parsing text substitutions.)
</p>
<pre class="display">
<span class="reserved">int</span><span class="plain"> </span><span class="functiontext">NaturalLanguages::adaptive_person</span><span class="plain">(</span><span class="reserved">natural_language</span><span class="plain"> *</span><span class="identifier">nl</span><span class="plain">) {</span>
<span class="plain">#</span><span class="identifier">ifdef</span><span class="plain"> </span><span class="identifier">IF_MODULE</span>
<span class="reserved">if</span><span class="plain"> ((</span><span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;adaptive_person</span><span class="plain"> == -1) &amp;&amp; (</span><span class="identifier">P_adaptive_text_viewpoint</span><span class="plain">)) {</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">I</span><span class="plain"> = </span><span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;nl_instance</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="functiontext">World::Inferences::get_prop_state</span><span class="plain">(</span>
<span class="functiontext">Instances::as_subject</span><span class="plain">(</span><span class="identifier">I</span><span class="plain">), </span><span class="identifier">P_adaptive_text_viewpoint</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">ParseTree::is</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">, </span><span class="constant">CONSTANT_NT</span><span class="plain">)) {</span>
<span class="reserved">instance</span><span class="plain"> *</span><span class="identifier">V</span><span class="plain"> = </span><span class="identifier">ParseTree::get_constant_instance</span><span class="plain">(</span><span class="identifier">spec</span><span class="plain">);</span>
<span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;adaptive_person</span><span class="plain"> = </span><span class="functiontext">Instances::get_numerical_value</span><span class="plain">(</span><span class="identifier">V</span><span class="plain">)-1;</span>
<span class="plain">}</span>
<span class="plain">}</span>
<span class="plain">#</span><span class="identifier">endif</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;adaptive_person</span><span class="plain"> == -1) </span><span class="reserved">return</span><span class="plain"> </span><span class="identifier">FIRST_PERSON_PLURAL</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;adaptive_person</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function NaturalLanguages::adaptive_person appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP16"></a><b>&#167;16. Choice of languages. </b></p>
<pre class="display">
<span class="reserved">natural_language</span><span class="plain"> *</span><span class="functiontext">NaturalLanguages::English</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">natural_language</span><span class="plain"> *</span><span class="identifier">nl</span><span class="plain"> = </span><span class="functiontext">NaturalLanguages::get_nl</span><span class="plain">(</span><span class="identifier">I</span><span class="string">"english"</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">internal_error</span><span class="plain">(</span><span class="string">"unable to find English language bundle"</span><span class="plain">);</span>
<span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;extension_required</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="identifier">English_language</span><span class="plain"> = </span><span class="identifier">nl</span><span class="plain">;</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">nl</span><span class="plain">;</span>
<span class="plain">}</span>
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">NaturalLanguages::set_language_of_play</span><span class="plain">(</span><span class="reserved">natural_language</span><span class="plain"> *</span><span class="identifier">nl</span><span class="plain">) {</span>
<span class="identifier">language_of_play</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">nl</span><span class="plain">-</span><span class="element">&gt;extension_required</span><span class="plain"> = </span><span class="identifier">TRUE</span><span class="plain">;</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function NaturalLanguages::English is used in 4/its (<a href="4-its.html#SP7">&#167;7</a>).</p>
<p class="endnote">The function NaturalLanguages::set_language_of_play appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP17"></a><b>&#167;17. Language code. </b>This is used when we write the bibliographic data for the work of IF we're
making; this enables online databases like IFDB, and smart interpreters, to
detect the language of play for a story file without actually running it.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">NaturalLanguages::write_language_code</span><span class="plain">(</span><span class="identifier">OUTPUT_STREAM</span><span class="plain">, </span><span class="reserved">natural_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">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="reserved">if</span><span class="plain"> (</span><span class="identifier">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;language_field</span><span class="plain">[</span><span class="constant">ISO_639_CODE_LFIELD</span><span class="plain">]))</span>
<span class="identifier">WRITE</span><span class="plain">(</span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;language_field</span><span class="plain">[</span><span class="constant">ISO_639_CODE_LFIELD</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">"en"</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function NaturalLanguages::write_language_code appears nowhere else.</p>
<p class="inwebparagraph"><a id="SP18"></a><b>&#167;18. Including language extensions. </b>Most extensions are included with explicit Inform source text:
</p>
<blockquote>
<p>Include Locksmith by Emily Short.</p>
</blockquote>
<p class="inwebparagraph">But the Standard Rules are an exception &mdash; they're always included &mdash; and so
are the languages used in the source text and for play. Note that French
games, say, involve loading two language extensions: English Language, because
that's the language in which the SR are written, and French Language, because
that's the language of play.
</p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">NaturalLanguages::include_required</span><span class="plain">(</span><span class="reserved">void</span><span class="plain">) {</span>
<span class="reserved">natural_language</span><span class="plain"> *</span><span class="identifier">nl</span><span class="plain">;</span>
<span class="identifier">feed_t</span><span class="plain"> </span><span class="identifier">id</span><span class="plain"> = </span><span class="identifier">Feeds::begin</span><span class="plain">();</span>
<span class="reserved">int</span><span class="plain"> </span><span class="identifier">icount</span><span class="plain"> = 0;</span>
<span class="identifier">LOOP_OVER</span><span class="plain">(</span><span class="identifier">nl</span><span class="plain">, </span><span class="reserved">natural_language</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="element">&gt;extension_required</span><span class="plain">) {</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">icount</span><span class="plain">++ &gt; 0) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="string">". "</span><span class="plain">);</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="string">"Include %+W Language by "</span><span class="plain">, </span><span class="functiontext">NaturalLanguages::get_name</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">Wordings::nonempty</span><span class="plain">(</span><span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;language_field</span><span class="plain">[</span><span class="constant">TRANSLATOR_LFIELD</span><span class="plain">]))</span>
<span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="string">"%+W"</span><span class="plain">, </span><span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;language_field</span><span class="plain">[</span><span class="constant">TRANSLATOR_LFIELD</span><span class="plain">]);</span>
<span class="reserved">else</span><span class="plain"> </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="string">"Unknown Translator"</span><span class="plain">);</span>
<span class="identifier">Feeds::feed_stream</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">);</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">ParseTree::set_attachment_point_one_off</span><span class="plain">(</span><span class="identifier">language_extension_inclusion_point</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">Feeds::end</span><span class="plain">(</span><span class="identifier">id</span><span class="plain">);</span>
<span class="identifier">Sentences::break</span><span class="plain">(</span><span class="identifier">W</span><span class="plain">, </span><span class="identifier">NULL</span><span class="plain">);</span>
<span class="identifier">ParseTree::set_attachment_point_one_off</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 NaturalLanguages::include_required is used in 7/ss (<a href="7-ss.html#SP8">&#167;8</a>).</p>
<p class="inwebparagraph"><a id="SP19"></a><b>&#167;19. Including Preform syntax. </b>At present we do this only for English, but some day...
</p>
<pre class="display">
<span class="identifier">wording</span><span class="plain"> </span><span class="functiontext">NaturalLanguages::load_preform</span><span class="plain">(</span><span class="reserved">natural_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">nl</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">"can't load preform from null language"</span><span class="plain">);</span>
<span class="identifier">language_being_read_by_Preform</span><span class="plain"> = </span><span class="identifier">nl</span><span class="plain">;</span>
<span class="identifier">filename</span><span class="plain"> *</span><span class="identifier">preform_file</span><span class="plain"> = </span><span class="identifier">Filenames::in_folder</span><span class="plain">(</span><span class="identifier">nl</span><span class="plain">-</span><span class="element">&gt;nl_bundle_path</span><span class="plain">, </span><span class="identifier">I</span><span class="string">"Syntax.preform"</span><span class="plain">);</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"Reading language definition from &lt;%f&gt;\</span><span class="plain">n</span><span class="string">"</span><span class="plain">, </span><span class="identifier">preform_file</span><span class="plain">);</span>
<span class="reserved">return</span><span class="plain"> </span><span class="identifier">Preform::load_from_file</span><span class="plain">(</span><span class="identifier">preform_file</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function NaturalLanguages::load_preform is used in 4/its (<a href="4-its.html#SP7">&#167;7</a>).</p>
<p class="inwebparagraph"><a id="SP20"></a><b>&#167;20. Preform error handling. </b></p>
<pre class="display">
<span class="reserved">void</span><span class="plain"> </span><span class="functiontext">NaturalLanguages::preform_error</span><span class="plain">(</span><span class="identifier">word_assemblage</span><span class="plain"> </span><span class="identifier">base_text</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">production</span><span class="plain"> *</span><span class="identifier">pr</span><span class="plain">, </span><span class="reserved">char</span><span class="plain"> *</span><span class="identifier">message</span><span class="plain">) {</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pr</span><span class="plain">) {</span>
<span class="identifier">LOG</span><span class="plain">(</span><span class="string">"The production at fault is:\</span><span class="plain">n</span><span class="string">"</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="identifier">LOG</span><span class="plain">(</span><span class="string">"\</span><span class="plain">n</span><span class="string">"</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">nt</span><span class="plain"> == </span><span class="identifier">NULL</span><span class="plain">)</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(1, </span><span class="string">"(no nonterminal)"</span><span class="plain">);</span>
<span class="reserved">else</span>
<span class="identifier">Problems::quote_wide_text</span><span class="plain">(1, </span><span class="identifier">Vocabulary::get_exemplar</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">FALSE</span><span class="plain">));</span>
<span class="identifier">Problems::quote_text</span><span class="plain">(2, </span><span class="identifier">message</span><span class="plain">);</span>
<span class="identifier">Problems::Issue::handmade_problem</span><span class="plain">(</span><span class="identifier">_p_</span><span class="plain">(</span><span class="identifier">Untestable</span><span class="plain">));</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">WordAssemblages::nonempty</span><span class="plain">(</span><span class="identifier">base_text</span><span class="plain">)) {</span>
<span class="identifier">Problems::quote_wa</span><span class="plain">(5, &amp;</span><span class="identifier">base_text</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"I'm having difficulties conjugating the verb '%5'. "</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">TEMPORARY_TEXT</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">);</span>
<span class="reserved">if</span><span class="plain"> (</span><span class="identifier">pr</span><span class="plain">) {</span>
<span class="identifier">Problems::quote_number</span><span class="plain">(3, &amp;(</span><span class="identifier">pr</span><span class="plain">-&gt;</span><span class="identifier">match_number</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">Preform::write_ptoken</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="identifier">pt</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">next_ptoken</span><span class="plain">) </span><span class="identifier">WRITE_TO</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">, </span><span class="string">" "</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">Problems::quote_stream</span><span class="plain">(4, </span><span class="identifier">TEMP</span><span class="plain">);</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"There's a problem in Inform's linguistic grammar, which is probably "</span>
<span class="string">"set by a translation extension. The problem occurs in line %3 of "</span>
<span class="string">"%1 ('%4'): %2."</span><span class="plain">);</span>
<span class="plain">} </span><span class="reserved">else</span><span class="plain"> {</span>
<span class="identifier">Problems::issue_problem_segment</span><span class="plain">(</span>
<span class="string">"There's a problem in Inform's linguistic grammar, which is probably "</span>
<span class="string">"set by a translation extension. The problem occurs in the definition of "</span>
<span class="string">"%1: %2."</span><span class="plain">);</span>
<span class="plain">}</span>
<span class="identifier">Problems::issue_problem_end</span><span class="plain">();</span>
<span class="identifier">DISCARD_TEXT</span><span class="plain">(</span><span class="identifier">TEMP</span><span class="plain">);</span>
<span class="plain">}</span>
</pre>
<p class="inwebparagraph"></p>
<p class="endnote">The function NaturalLanguages::preform_error appears nowhere else.</p>
<hr class="tocbar">
<ul class="toc"><li><a href="3-rst.html">Back to 'Read Source Text'</a></li><li><a href="3-pd.html">Continue with 'Plural Dictionary'</a></li></ul><hr class="tocbar">
<!--End of weave-->
</body>
</html>