1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-06-26 04:00:43 +03:00

Improved Preform source

This commit is contained in:
Graham Nelson 2020-05-17 00:20:21 +01:00
parent 3ed31bef56
commit 4c86f53d74
46 changed files with 1476 additions and 1064 deletions

View file

@ -1,6 +1,6 @@
# Inform 7
v10.1.0-alpha.1+6Q46 'Krypton' (12 May 2020)
v10.1.0-alpha.1+6Q47 'Krypton' (17 May 2020)
## About Inform 7

View file

@ -1,3 +1,3 @@
Prerelease: alpha.1
Build Date: 12 May 2020
Build Number: 6Q46
Build Date: 17 May 2020
Build Number: 6Q47

View file

@ -155,10 +155,11 @@ this because we need access to it very quickly when parsing text substitutions.)
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="function-syntax">NaturalLanguages::load_preform</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">NaturalLanguages::load_preform</span></span>:<br/>Introduction to Semantics - <a href="4-its.html#SP7">&#167;7</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">inform_language</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">NaturalLanguages::load_preform</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">NaturalLanguages::load_preform</span></span>:<br/>Introduction to Semantics - <a href="4-its.html#SP7">&#167;7</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">inform_language</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">L</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"can't load preform from null language"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">preform_file</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Filenames::in</span><span class="plain-syntax">(</span><span class="identifier-syntax">Languages::path_to_bundle</span><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="plain-syntax">), </span><span class="identifier-syntax">I</span><span class="string-syntax">"Syntax.preform"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">LoadPreform::load_for_language</span><span class="plain-syntax">(</span><span class="identifier-syntax">preform_file</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">preform_file</span><span class="plain-syntax"> =</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Filenames::in</span><span class="plain-syntax">(</span><span class="identifier-syntax">Languages::path_to_bundle</span><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="plain-syntax">), </span><span class="identifier-syntax">I</span><span class="string-syntax">"Syntax.preform"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">LoadPreform::load</span><span class="plain-syntax">(</span><span class="identifier-syntax">preform_file</span><span class="plain-syntax">, </span><span class="identifier-syntax">L</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP7"></a><b>&#167;7. </b>Preform errors are handled here:

View file

@ -294,10 +294,8 @@ whole thing into a <span class="extract"><span class="extract-syntax">specificat
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Semantics::read_preform</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Semantics::read_preform</span></span>:<br/>Main Routine - <a href="1-mr.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">inform_language</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-its.html#SP7_1" class="named-paragraph-link"><span class="named-paragraph">Mark certain nonterminals to have their vocabularies numbered and flagged</span><span class="named-paragraph-number">7.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><a href="3-nl.html#SP6" class="function-link"><span class="function-syntax">NaturalLanguages::load_preform</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminals_declared</span><span class="plain-syntax"> = </span><span class="identifier-syntax">LoadPreform::parse</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"%d declarations read (%d words)\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">nonterminals_declared</span><span class="plain-syntax">, </span><span class="identifier-syntax">Wordings::length</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminals_declared</span><span class="plain-syntax"> = </span><a href="3-nl.html#SP6" class="function-link"><span class="function-syntax">NaturalLanguages::load_preform</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"%d declarations read\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">nonterminals_declared</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP7_1"></a><b>&#167;7.1. </b><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Mark certain nonterminals to have their vocabularies numbered and flagged</span><span class="named-paragraph-number">7.1</span></span><span class="comment-syntax"> =</span>

View file

@ -261,8 +261,7 @@ for use.
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Main::load_preform</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Main::load_preform</span></span>:<br/><a href="1-mn.html#SP2_2">&#167;2.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">inform_language</span><span class="plain-syntax"> *</span><span class="identifier-syntax">L</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">pathname</span><span class="plain-syntax"> *</span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-pth.html#SP4" class="function-link"><span class="function-syntax">Pathnames::down</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">path_to_inbuild</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"Tangled"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-fln.html#SP2" class="function-link"><span class="function-syntax">Filenames::in</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"Syntax.preform"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><a href="../words-module/4-lp.html#SP2" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP22" class="function-link"><span class="function-syntax">LoadPreform::parse</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP1" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2_6"></a><b>&#167;2.6. Target list. </b>This where we keep the list of targets, in which no copy occurs more than

View file

@ -100,8 +100,7 @@
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-pth.html#SP4" class="function-link"><span class="function-syntax">Pathnames::down</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"inflections-test"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-pth.html#SP4" class="function-link"><span class="function-syntax">Pathnames::down</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"Tangled"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-fln.html#SP2" class="function-link"><span class="function-syntax">Filenames::in</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">leaf</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><a href="../words-module/4-lp.html#SP2" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP22" class="function-link"><span class="function-syntax">LoadPreform::parse</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP1" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Main::load_other</span><span class="plain-syntax">(</span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">leaf</span><span class="plain-syntax">) {</span>
@ -109,8 +108,7 @@
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-pth.html#SP4" class="function-link"><span class="function-syntax">Pathnames::down</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"inflections-test"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-pth.html#SP4" class="function-link"><span class="function-syntax">Pathnames::down</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"Preform"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-fln.html#SP2" class="function-link"><span class="function-syntax">Filenames::in</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">leaf</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><a href="../words-module/4-lp.html#SP2" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP22" class="function-link"><span class="function-syntax">LoadPreform::parse</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP1" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Main::ignore</span><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">id</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">arg</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">state</span><span class="plain-syntax">) {</span>

View file

@ -86,8 +86,7 @@
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-pth.html#SP4" class="function-link"><span class="function-syntax">Pathnames::down</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"linguistics-test"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-pth.html#SP4" class="function-link"><span class="function-syntax">Pathnames::down</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"Tangled"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-fln.html#SP2" class="function-link"><span class="function-syntax">Filenames::in</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">leaf</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><a href="../words-module/4-lp.html#SP2" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP22" class="function-link"><span class="function-syntax">LoadPreform::parse</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP1" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Main::ignore</span><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">id</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">arg</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">state</span><span class="plain-syntax">) {</span>

View file

@ -82,8 +82,7 @@
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-pth.html#SP4" class="function-link"><span class="function-syntax">Pathnames::down</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"problems-test"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-pth.html#SP4" class="function-link"><span class="function-syntax">Pathnames::down</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"Tangled"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-fln.html#SP2" class="function-link"><span class="function-syntax">Filenames::in</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">leaf</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><a href="../words-module/4-lp.html#SP2" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP22" class="function-link"><span class="function-syntax">LoadPreform::parse</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP1" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Main::ignore</span><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">id</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">arg</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">state</span><span class="plain-syntax">) {</span>

View file

@ -224,7 +224,7 @@ include the Materials folder for any relevant project.
<p class="commentary firstcommentary"><a id="SP9"></a><b>&#167;9. </b>This function is called only from Preform...
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">PREFORM_LANGUAGE_FROM_NAME</span><span class="plain-syntax"> </span><a href="5-ls.html#SP9" class="function-link"><span class="function-syntax">Languages::Preform_find</span></a>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">PREFORM_LANGUAGE_FROM_NAME_WORDS_CALLBACK</span><span class="plain-syntax"> </span><a href="5-ls.html#SP9" class="function-link"><span class="function-syntax">Languages::Preform_find</span></a>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">inform_language</span><span class="plain-syntax"> *</span><span class="function-syntax">Languages::Preform_find</span><span class="plain-syntax">(</span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">) {</span>

View file

@ -857,7 +857,6 @@ for the extensions they refer to, in a post-processing phase.
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Projects::read_source_text_for</span><button class="popup" onclick="togglePopup('usagePopup24')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup24">Usage of <span class="code-font"><span class="function-syntax">Projects::read_source_text_for</span></span>:<br/>Project Bundle Manager - <a href="4-pbm.html#SP7">&#167;7</a><br/>Project File Manager - <a href="4-pfm.html#SP7">&#167;7</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">inform_project</span><span class="plain-syntax"> *</span><span class="identifier-syntax">proj</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="5-ls.html#SP8" class="function-link"><span class="function-syntax">Languages::read_Preform_definition</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">proj</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">language_of_syntax</span><span class="plain-syntax">, </span><span class="identifier-syntax">proj</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">search_list</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LoadPreform::set_language_of_syntax</span><span class="plain-syntax">(</span><span class="identifier-syntax">proj</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">language_of_syntax</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">Sentences::set_start_of_source</span><span class="plain-syntax">(</span><span class="identifier-syntax">sfsm</span><span class="plain-syntax">, -1);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">inclusions_heading</span><span class="plain-syntax">, *</span><span class="identifier-syntax">implicit_heading</span><span class="plain-syntax">;</span>

View file

@ -915,7 +915,11 @@ it would be too late.
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax"> = </span><span class="identifier-syntax">new</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LoadPreform::parse</span><span class="plain-syntax">(</span><span class="identifier-syntax">GET_RW</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;language-modifying-sentence&gt;</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">), </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">GET_RW</span><span class="plain-syntax">(</span><span class="function-syntax">&lt;language-modifying-sentence&gt;</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">wd</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">wd</span><span class="plain-syntax">, </span><span class="string-syntax">"%+W"</span><span class="plain-syntax">, </span><span class="identifier-syntax">Wordings::one_word</span><span class="plain-syntax">(</span><span class="identifier-syntax">Wordings::first_wn</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LoadPreform::parse_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">wd</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">DISCARD_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">wd</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="2-na.html#SP6" class="function-link"><span class="function-syntax">Annotations::write_int</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">new</span><span class="plain-syntax">, </span><span class="constant-syntax">sentence_unparsed_ANNOT</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-snt.html#SP6_9">&#167;6.9</a>.</li></ul>

View file

@ -80,8 +80,7 @@
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-pth.html#SP4" class="function-link"><span class="function-syntax">Pathnames::down</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"syntax-test"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-pth.html#SP4" class="function-link"><span class="function-syntax">Pathnames::down</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"Tangled"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-fln.html#SP2" class="function-link"><span class="function-syntax">Filenames::in</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">leaf</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><a href="../words-module/4-lp.html#SP2" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP22" class="function-link"><span class="function-syntax">LoadPreform::parse</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP1" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Main::ignore</span><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">id</span><span class="plain-syntax">, </span><span class="reserved-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">arg</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">state</span><span class="plain-syntax">) {</span>

View file

@ -109,7 +109,8 @@ which use this module:
<span class="plain-syntax"> </span><a href="3-lxr.html#SP13" class="function-link"><span class="function-syntax">Lexer::start</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><a href="2-vcb.html#SP2" class="function-link"><span class="function-syntax">Vocabulary::create_punctuation</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><a href="4-lp.html#SP20" class="function-link"><span class="function-syntax">LoadPreform::begin</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><a href="4-lp.html#SP6" class="function-link"><span class="function-syntax">LoadPreform::create_punctuation</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax"> </span><a href="4-nnt.html#SP1" class="function-link"><span class="function-syntax">Nonterminals::register</span></a><span class="plain-syntax">();</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">WordsModule::end</span><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>

View file

@ -88,7 +88,7 @@ is also normalised.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Word::compare_by_strcmp</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Word::compare_by_strcmp</span></span>:<br/>Basic Nonterminals - <a href="4-bn.html#SP7">&#167;7</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">w</span><span class="plain-syntax">, </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Word::compare_by_strcmp</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Word::compare_by_strcmp</span></span>:<br/>Basic Nonterminals - <a href="4-bn.html#SP8">&#167;8</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">w</span><span class="plain-syntax">, </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wide::cmp</span><span class="plain-syntax">(</span><a href="3-lxr.html#SP20" class="function-link"><span class="function-syntax">Lexer::word_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">w</span><span class="plain-syntax">), </span><span class="identifier-syntax">t</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Word::compare_raw_by_strcmp</span><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">w</span><span class="plain-syntax">, </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
@ -140,7 +140,7 @@ tell us something.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Word::unexpectedly_upper_case</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">Word::unexpectedly_upper_case</span></span>:<br/>Word Assemblages - <a href="2-wa.html#SP11">&#167;11</a><br/>Preform - <a href="4-prf.html#SP3">&#167;3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Word::unexpectedly_upper_case</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">Word::unexpectedly_upper_case</span></span>:<br/>Word Assemblages - <a href="2-wa.html#SP11">&#167;11</a><br/>Preform - <a href="4-prf.html#SP3">&#167;3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">wn</span><span class="plain-syntax">&lt;1) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">compare_word</span><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">-1, </span><span class="identifier-syntax">FULLSTOP_V</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">compare_word</span><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">-1, </span><span class="identifier-syntax">PARBREAK_V</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>

View file

@ -265,7 +265,7 @@ structure:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="function-syntax">Vocabulary::get_exemplar</span><button class="popup" onclick="togglePopup('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <span class="code-font"><span class="function-syntax">Vocabulary::get_exemplar</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP26">&#167;26</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ve</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">raw</span><span class="plain-syntax">) {</span>
<span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="function-syntax">Vocabulary::get_exemplar</span><button class="popup" onclick="togglePopup('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <span class="code-font"><span class="function-syntax">Vocabulary::get_exemplar</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP16">&#167;16</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ve</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">raw</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">raw</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">ve</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">raw_exemplar</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">else</span><span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">ve</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">exemplar</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
@ -285,7 +285,7 @@ if it every turns out to parse as a literal number:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Vocabulary::get_literal_number_value</span><button class="popup" onclick="togglePopup('usagePopup9')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup9">Usage of <span class="code-font"><span class="function-syntax">Vocabulary::get_literal_number_value</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP24_1_1">&#167;24.1.1</a>, <a href="4-lp.html#SP24_1_3">&#167;24.1.3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP5">&#167;5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ve</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Vocabulary::get_literal_number_value</span><button class="popup" onclick="togglePopup('usagePopup9')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup9">Usage of <span class="code-font"><span class="function-syntax">Vocabulary::get_literal_number_value</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP14_1_1">&#167;14.1.1</a>, <a href="4-lp.html#SP14_1_3">&#167;14.1.3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ve</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">ve</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">literal_number_value</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Vocabulary::set_literal_number_value</span><span class="plain-syntax">(</span><span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ve</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">val</span><span class="plain-syntax">) {</span>
@ -327,7 +327,7 @@ we get to set and test them:
<span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Vocabulary::test_vflags</span><span class="plain-syntax">(</span><span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">ve</span><span class="plain-syntax">, </span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ve</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">flags</span><span class="plain-syntax">) &amp; </span><span class="identifier-syntax">t</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Vocabulary::test_flags</span><button class="popup" onclick="togglePopup('usagePopup10')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup10">Usage of <span class="code-font"><span class="function-syntax">Vocabulary::test_flags</span></span>:<br/>Wordings - <a href="3-wrd.html#SP16">&#167;16</a><br/>Loading Preform - <a href="4-lp.html#SP24_1_1">&#167;24.1.1</a>, <a href="4-lp.html#SP24_1_3">&#167;24.1.3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP5">&#167;5</a>, <a href="4-bn.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax">, </span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Vocabulary::test_flags</span><button class="popup" onclick="togglePopup('usagePopup10')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup10">Usage of <span class="code-font"><span class="function-syntax">Vocabulary::test_flags</span></span>:<br/>Wordings - <a href="3-wrd.html#SP16">&#167;16</a><br/>Loading Preform - <a href="4-lp.html#SP14_1_1">&#167;14.1.1</a>, <a href="4-lp.html#SP14_1_3">&#167;14.1.3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP6">&#167;6</a>, <a href="4-bn.html#SP7">&#167;7</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax">, </span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><a href="3-lxr.html#SP20" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">wn</span><span class="plain-syntax">)-&gt;</span><span class="element-syntax">flags</span><span class="plain-syntax">) &amp; </span><span class="identifier-syntax">t</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
@ -468,7 +468,7 @@ codes for any number, any text, or any I6 inclusion.
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">no_vocabulary_entries</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="function-syntax">Vocabulary::entry_for_text</span><button class="popup" onclick="togglePopup('usagePopup15')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup15">Usage of <span class="code-font"><span class="function-syntax">Vocabulary::entry_for_text</span></span>:<br/><a href="2-vcb.html#SP2">&#167;2</a>, <a href="2-vcb.html#SP3">&#167;3</a><br/>Loading Preform - <a href="4-lp.html#SP20">&#167;20</a>, <a href="4-lp.html#SP21">&#167;21</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">text</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="function-syntax">Vocabulary::entry_for_text</span><button class="popup" onclick="togglePopup('usagePopup15')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup15">Usage of <span class="code-font"><span class="function-syntax">Vocabulary::entry_for_text</span></span>:<br/><a href="2-vcb.html#SP2">&#167;2</a>, <a href="2-vcb.html#SP3">&#167;3</a><br/>Nonterminals - <a href="4-nnt.html#SP2">&#167;2</a>, <a href="4-nnt.html#SP4">&#167;4</a><br/>Loading Preform - <a href="4-lp.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">text</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">new_entry</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">hash_code</span><span class="plain-syntax"> = </span><a href="2-vcb.html#SP13" class="function-link"><span class="function-syntax">Vocabulary::hash_code_from_word</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">text</span><span class="plain-syntax">), </span><span class="identifier-syntax">val</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">f</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>

View file

@ -109,7 +109,7 @@ with the corresponding ID back again.
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="3-fds.html#SP4" class="function-link"><span class="function-syntax">Feeds::feed_text_full</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">text</span><span class="plain-syntax">, </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="function-syntax">Feeds::feed_text_punctuated</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">Feeds::feed_text_punctuated</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP3">&#167;3</a>, <a href="4-lp.html#SP22">&#167;22</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">text</span><span class="plain-syntax">, </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pmarks</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="function-syntax">Feeds::feed_text_punctuated</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">Feeds::feed_text_punctuated</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP2">&#167;2</a>, <a href="4-lp.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">text</span><span class="plain-syntax">, </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pmarks</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><a href="3-fds.html#SP4" class="function-link"><span class="function-syntax">Feeds::feed_text_full</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">text</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">, </span><span class="identifier-syntax">pmarks</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
@ -119,7 +119,7 @@ function, written two ways:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="function-syntax">Feeds::feed_C_string_full</span><button class="popup" onclick="togglePopup('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <span class="code-font"><span class="function-syntax">Feeds::feed_C_string_full</span></span>:<br/><a href="3-fds.html#SP3">&#167;3</a><br/>Loading Preform - <a href="4-lp.html#SP25_1">&#167;25.1</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">text</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">expand</span><span class="plain-syntax">, </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nonstandard</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="function-syntax">Feeds::feed_C_string_full</span><button class="popup" onclick="togglePopup('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <span class="code-font"><span class="function-syntax">Feeds::feed_C_string_full</span></span>:<br/><a href="3-fds.html#SP3">&#167;3</a><br/>Loading Preform - <a href="4-lp.html#SP15_1">&#167;15.1</a></span></button><span class="plain-syntax">(</span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">text</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">expand</span><span class="plain-syntax">, </span><span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nonstandard</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="3-fds.html#SP4_1" class="named-paragraph-link"><span class="named-paragraph">Set up the lexer</span><span class="named-paragraph-number">4.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">text</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] != </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">last_cr</span><span class="plain-syntax">, </span><span class="identifier-syntax">cr</span><span class="plain-syntax">, </span><span class="identifier-syntax">next_cr</span><span class="plain-syntax">;</span>

View file

@ -497,7 +497,7 @@ distinguished. We'll do this with the letters <span class="extract"><span class=
<p class="commentary firstcommentary"><a id="SP20"></a><b>&#167;20. Access functions. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="function-syntax">Lexer::word</span><button class="popup" onclick="togglePopup('usagePopup10')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup10">Usage of <span class="code-font"><span class="function-syntax">Lexer::word</span></span>:<br/>Vocabulary - <a href="2-vcb.html#SP6">&#167;6</a>, <a href="2-vcb.html#SP10">&#167;10</a>, <a href="2-vcb.html#SP11">&#167;11</a>, <a href="2-vcb.html#SP16">&#167;16</a><br/>Word Assemblages - <a href="2-wa.html#SP4">&#167;4</a>, <a href="2-wa.html#SP9">&#167;9</a>, <a href="2-wa.html#SP10">&#167;10</a>, <a href="2-wa.html#SP11">&#167;11</a><br/>Numbered Words - <a href="2-nw.html#SP1">&#167;1</a><br/>Wordings - <a href="3-wrd.html#SP8">&#167;8</a>, <a href="3-wrd.html#SP18">&#167;18</a>, <a href="3-wrd.html#SP19">&#167;19</a>, <a href="3-wrd.html#SP20">&#167;20</a><br/>Text From Files - <a href="3-tff.html#SP4">&#167;4</a><br/>Loading Preform - <a href="4-lp.html#SP17">&#167;17</a>, <a href="4-lp.html#SP22">&#167;22</a>, <a href="4-lp.html#SP22_2">&#167;22.2</a>, <a href="4-lp.html#SP22_3">&#167;22.3</a>, <a href="4-lp.html#SP24_1_1">&#167;24.1.1</a>, <a href="4-lp.html#SP24_1_3">&#167;24.1.3</a>, <a href="4-lp.html#SP25_2">&#167;25.2</a><br/>The Optimiser - <a href="4-to.html#SP4">&#167;4</a>, <a href="4-to.html#SP5">&#167;5</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2_3_3_3">&#167;1.2.1.2.3.3.3</a>, <a href="4-prf.html#SP3">&#167;3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP5">&#167;5</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="function-syntax">Lexer::word</span><button class="popup" onclick="togglePopup('usagePopup10')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup10">Usage of <span class="code-font"><span class="function-syntax">Lexer::word</span></span>:<br/>Vocabulary - <a href="2-vcb.html#SP6">&#167;6</a>, <a href="2-vcb.html#SP10">&#167;10</a>, <a href="2-vcb.html#SP11">&#167;11</a>, <a href="2-vcb.html#SP16">&#167;16</a><br/>Word Assemblages - <a href="2-wa.html#SP4">&#167;4</a>, <a href="2-wa.html#SP9">&#167;9</a>, <a href="2-wa.html#SP10">&#167;10</a>, <a href="2-wa.html#SP11">&#167;11</a><br/>Numbered Words - <a href="2-nw.html#SP1">&#167;1</a><br/>Wordings - <a href="3-wrd.html#SP8">&#167;8</a>, <a href="3-wrd.html#SP18">&#167;18</a>, <a href="3-wrd.html#SP19">&#167;19</a>, <a href="3-wrd.html#SP20">&#167;20</a><br/>Text From Files - <a href="3-tff.html#SP4">&#167;4</a><br/>Loading Preform - <a href="4-lp.html#SP7">&#167;7</a>, <a href="4-lp.html#SP7_2">&#167;7.2</a>, <a href="4-lp.html#SP7_3">&#167;7.3</a>, <a href="4-lp.html#SP14_1_1">&#167;14.1.1</a>, <a href="4-lp.html#SP14_1_3">&#167;14.1.3</a>, <a href="4-lp.html#SP15_2">&#167;15.2</a><br/>The Optimiser - <a href="4-to.html#SP4">&#167;4</a>, <a href="4-to.html#SP5">&#167;5</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2_3_3_3">&#167;1.2.1.2.3.3.3</a>, <a href="4-prf.html#SP3">&#167;3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP1">&#167;1</a>, <a href="4-bn.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">lw_array</span><span class="plain-syntax">[</span><span class="identifier-syntax">wn</span><span class="plain-syntax">].</span><span class="element-syntax">lw_identity</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
@ -528,7 +528,7 @@ distinguished. We'll do this with the letters <span class="extract"><span class=
<span class="plain-syntax"> </span><span class="identifier-syntax">lw_array</span><span class="plain-syntax">[</span><span class="identifier-syntax">wn</span><span class="plain-syntax">].</span><span class="element-syntax">lw_source</span><span class="plain-syntax"> = </span><span class="identifier-syntax">sl</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="function-syntax">Lexer::word_raw_text</span><button class="popup" onclick="togglePopup('usagePopup14')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup14">Usage of <span class="code-font"><span class="function-syntax">Lexer::word_raw_text</span></span>:<br/>Vocabulary - <a href="2-vcb.html#SP3">&#167;3</a><br/>Numbered Words - <a href="2-nw.html#SP1">&#167;1</a>, <a href="2-nw.html#SP2">&#167;2</a>, <a href="2-nw.html#SP4">&#167;4</a>, <a href="2-nw.html#SP5">&#167;5</a>, <a href="2-nw.html#SP6">&#167;6</a>, <a href="2-nw.html#SP7">&#167;7</a><br/>Wordings - <a href="3-wrd.html#SP16">&#167;16</a>, <a href="3-wrd.html#SP22_3">&#167;22.3</a>, <a href="3-wrd.html#SP22_4">&#167;22.4</a><br/>Loading Preform - <a href="4-lp.html#SP25_1">&#167;25.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax">) {</span>
<span class="identifier-syntax">wchar_t</span><span class="plain-syntax"> *</span><span class="function-syntax">Lexer::word_raw_text</span><button class="popup" onclick="togglePopup('usagePopup14')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup14">Usage of <span class="code-font"><span class="function-syntax">Lexer::word_raw_text</span></span>:<br/>Vocabulary - <a href="2-vcb.html#SP3">&#167;3</a><br/>Numbered Words - <a href="2-nw.html#SP1">&#167;1</a>, <a href="2-nw.html#SP2">&#167;2</a>, <a href="2-nw.html#SP4">&#167;4</a>, <a href="2-nw.html#SP5">&#167;5</a>, <a href="2-nw.html#SP6">&#167;6</a>, <a href="2-nw.html#SP7">&#167;7</a><br/>Wordings - <a href="3-wrd.html#SP16">&#167;16</a>, <a href="3-wrd.html#SP22_3">&#167;22.3</a>, <a href="3-wrd.html#SP22_4">&#167;22.4</a><br/>Loading Preform - <a href="4-lp.html#SP15_1">&#167;15.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">wn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">lw_array</span><span class="plain-syntax">[</span><span class="identifier-syntax">wn</span><span class="plain-syntax">].</span><span class="element-syntax">lw_rawtext</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>

View file

@ -117,11 +117,11 @@ if the wording is empty.
<p class="commentary firstcommentary"><a id="SP6"></a><b>&#167;6. Construction. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::new</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Wordings::new</span></span>:<br/><a href="3-wrd.html#SP10">&#167;10</a><br/>Lexer - <a href="3-lxr.html#SP26">&#167;26</a>, <a href="3-lxr.html#SP26_3">&#167;26.3</a>, <a href="3-lxr.html#SP30">&#167;30</a><br/>Feeds - <a href="3-fds.html#SP2">&#167;2</a><br/>Loading Preform - <a href="4-lp.html#SP22_3">&#167;22.3</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2">&#167;1.2.1.2</a>, <a href="4-prf.html#SP1_2_1_2_3_3_5">&#167;1.2.1.2.3.3.5</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3_1">&#167;1.2.1.2.3.3.3.1</a>, <a href="4-prf.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">A</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">B</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::new</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Wordings::new</span></span>:<br/><a href="3-wrd.html#SP10">&#167;10</a><br/>Lexer - <a href="3-lxr.html#SP26">&#167;26</a>, <a href="3-lxr.html#SP26_3">&#167;26.3</a>, <a href="3-lxr.html#SP30">&#167;30</a><br/>Feeds - <a href="3-fds.html#SP2">&#167;2</a><br/>Loading Preform - <a href="4-lp.html#SP7_3">&#167;7.3</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2">&#167;1.2.1.2</a>, <a href="4-prf.html#SP1_2_1_2_3_3_5">&#167;1.2.1.2.3.3.5</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3_1">&#167;1.2.1.2.3.3.3.1</a>, <a href="4-prf.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">A</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">B</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="reserved-syntax">wording</span><span class="plain-syntax">) { </span><span class="identifier-syntax">A</span><span class="plain-syntax">, </span><span class="identifier-syntax">B</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::one_word</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">Wordings::one_word</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP22">&#167;22</a>, <a href="4-lp.html#SP22_1">&#167;22.1</a>, <a href="4-lp.html#SP25">&#167;25</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2_3_3">&#167;1.2.1.2.3.3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">A</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::one_word</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">Wordings::one_word</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP7_1">&#167;7.1</a>, <a href="4-lp.html#SP15">&#167;15</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2_3_3">&#167;1.2.1.2.3.3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">A</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> (</span><span class="reserved-syntax">wording</span><span class="plain-syntax">) { </span><span class="identifier-syntax">A</span><span class="plain-syntax">, </span><span class="identifier-syntax">A</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">}</span>
</pre>
@ -145,7 +145,7 @@ by moving <span class="extract"><span class="extract-syntax">A</span></span> pas
<p class="commentary firstcommentary"><a id="SP8"></a><b>&#167;8. Reading. </b></p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::length</span><button class="popup" onclick="togglePopup('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <span class="code-font"><span class="function-syntax">Wordings::length</span></span>:<br/><a href="3-wrd.html#SP9">&#167;9</a>, <a href="3-wrd.html#SP14">&#167;14</a>, <a href="3-wrd.html#SP21">&#167;21</a><br/>Word Assemblages - <a href="2-wa.html#SP4">&#167;4</a>, <a href="2-wa.html#SP10">&#167;10</a>, <a href="2-wa.html#SP11">&#167;11</a><br/>Lexer - <a href="3-lxr.html#SP30">&#167;30</a><br/>Loading Preform - <a href="4-lp.html#SP25_2">&#167;25.2</a><br/>The Optimiser - <a href="4-to.html#SP5">&#167;5</a><br/>Preform - <a href="4-prf.html#SP1">&#167;1</a>, <a href="4-prf.html#SP1_2_1">&#167;1.2.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::length</span><button class="popup" onclick="togglePopup('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <span class="code-font"><span class="function-syntax">Wordings::length</span></span>:<br/><a href="3-wrd.html#SP9">&#167;9</a>, <a href="3-wrd.html#SP14">&#167;14</a>, <a href="3-wrd.html#SP21">&#167;21</a><br/>Word Assemblages - <a href="2-wa.html#SP4">&#167;4</a>, <a href="2-wa.html#SP10">&#167;10</a>, <a href="2-wa.html#SP11">&#167;11</a><br/>Lexer - <a href="3-lxr.html#SP30">&#167;30</a><br/>Loading Preform - <a href="4-lp.html#SP15_2">&#167;15.2</a><br/>The Optimiser - <a href="4-to.html#SP5">&#167;5</a><br/>Preform - <a href="4-prf.html#SP1">&#167;1</a>, <a href="4-prf.html#SP1_2_1">&#167;1.2.1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-wrd.html#SP12" class="function-link"><span class="function-syntax">Wordings::empty</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">.</span><span class="identifier-syntax">word_B</span><span class="plain-syntax"> - </span><span class="identifier-syntax">W</span><span class="plain-syntax">.</span><span class="element-syntax">word_A</span><span class="plain-syntax"> + </span><span class="constant-syntax">1</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
@ -161,11 +161,11 @@ by moving <span class="extract"><span class="extract-syntax">A</span></span> pas
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">n</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::first_wn</span><button class="popup" onclick="togglePopup('usagePopup6')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup6">Usage of <span class="code-font"><span class="function-syntax">Wordings::first_wn</span></span>:<br/><a href="3-wrd.html#SP18">&#167;18</a>, <a href="3-wrd.html#SP21">&#167;21</a>, <a href="3-wrd.html#SP22_3">&#167;22.3</a>, <a href="3-wrd.html#SP22_4">&#167;22.4</a><br/>Vocabulary - <a href="2-vcb.html#SP16">&#167;16</a><br/>Word Assemblages - <a href="2-wa.html#SP9">&#167;9</a>, <a href="2-wa.html#SP10">&#167;10</a>, <a href="2-wa.html#SP11">&#167;11</a><br/>Lexer - <a href="3-lxr.html#SP26">&#167;26</a>, <a href="3-lxr.html#SP30">&#167;30</a><br/>Loading Preform - <a href="4-lp.html#SP17">&#167;17</a>, <a href="4-lp.html#SP22">&#167;22</a>, <a href="4-lp.html#SP25_2">&#167;25.2</a><br/>The Optimiser - <a href="4-to.html#SP4">&#167;4</a>, <a href="4-to.html#SP5">&#167;5</a><br/>Preform - <a href="4-prf.html#SP1_2">&#167;1.2</a>, <a href="4-prf.html#SP1_2_1_2_2">&#167;1.2.1.2.2</a>, <a href="4-prf.html#SP1_2_1_2_3_1">&#167;1.2.1.2.3.1</a>, <a href="4-prf.html#SP1_2_1_2_3_3">&#167;1.2.1.2.3.3</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3_1">&#167;1.2.1.2.3.3.3.1</a><br/>Basic Nonterminals - <a href="4-bn.html#SP1">&#167;1</a>, <a href="4-bn.html#SP2">&#167;2</a>, <a href="4-bn.html#SP5">&#167;5</a>, <a href="4-bn.html#SP6">&#167;6</a>, <a href="4-bn.html#SP7">&#167;7</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::first_wn</span><button class="popup" onclick="togglePopup('usagePopup6')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup6">Usage of <span class="code-font"><span class="function-syntax">Wordings::first_wn</span></span>:<br/><a href="3-wrd.html#SP18">&#167;18</a>, <a href="3-wrd.html#SP21">&#167;21</a>, <a href="3-wrd.html#SP22_3">&#167;22.3</a>, <a href="3-wrd.html#SP22_4">&#167;22.4</a><br/>Vocabulary - <a href="2-vcb.html#SP16">&#167;16</a><br/>Word Assemblages - <a href="2-wa.html#SP9">&#167;9</a>, <a href="2-wa.html#SP10">&#167;10</a>, <a href="2-wa.html#SP11">&#167;11</a><br/>Lexer - <a href="3-lxr.html#SP26">&#167;26</a>, <a href="3-lxr.html#SP30">&#167;30</a><br/>Loading Preform - <a href="4-lp.html#SP15_2">&#167;15.2</a><br/>The Optimiser - <a href="4-to.html#SP4">&#167;4</a>, <a href="4-to.html#SP5">&#167;5</a><br/>Preform - <a href="4-prf.html#SP1_2">&#167;1.2</a>, <a href="4-prf.html#SP1_2_1_2_2">&#167;1.2.1.2.2</a>, <a href="4-prf.html#SP1_2_1_2_3_1">&#167;1.2.1.2.3.1</a>, <a href="4-prf.html#SP1_2_1_2_3_3">&#167;1.2.1.2.3.3</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3_1">&#167;1.2.1.2.3.3.3.1</a><br/>Basic Nonterminals - <a href="4-bn.html#SP1">&#167;1</a>, <a href="4-bn.html#SP2">&#167;2</a>, <a href="4-bn.html#SP3">&#167;3</a>, <a href="4-bn.html#SP6">&#167;6</a>, <a href="4-bn.html#SP7">&#167;7</a>, <a href="4-bn.html#SP8">&#167;8</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">.</span><span class="element-syntax">word_A</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::last_wn</span><button class="popup" onclick="togglePopup('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <span class="code-font"><span class="function-syntax">Wordings::last_wn</span></span>:<br/><a href="3-wrd.html#SP18">&#167;18</a>, <a href="3-wrd.html#SP21">&#167;21</a>, <a href="3-wrd.html#SP22_1">&#167;22.1</a>, <a href="3-wrd.html#SP22_2">&#167;22.2</a><br/>Word Assemblages - <a href="2-wa.html#SP11">&#167;11</a><br/>Text From Files - <a href="3-tff.html#SP5">&#167;5</a><br/>Loading Preform - <a href="4-lp.html#SP22">&#167;22</a>, <a href="4-lp.html#SP22_3">&#167;22.3</a>, <a href="4-lp.html#SP24_1_1">&#167;24.1.1</a>, <a href="4-lp.html#SP24_1_3">&#167;24.1.3</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2_2">&#167;1.2.1.2.2</a>, <a href="4-prf.html#SP1_2_1_2_3_3">&#167;1.2.1.2.3.3</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3">&#167;1.2.1.2.3.3.3</a>, <a href="4-prf.html#SP1_2_1_2_3_3_5">&#167;1.2.1.2.3.3.5</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3_1">&#167;1.2.1.2.3.3.3.1</a>, <a href="4-prf.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::last_wn</span><button class="popup" onclick="togglePopup('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <span class="code-font"><span class="function-syntax">Wordings::last_wn</span></span>:<br/><a href="3-wrd.html#SP18">&#167;18</a>, <a href="3-wrd.html#SP21">&#167;21</a>, <a href="3-wrd.html#SP22_1">&#167;22.1</a>, <a href="3-wrd.html#SP22_2">&#167;22.2</a><br/>Word Assemblages - <a href="2-wa.html#SP11">&#167;11</a><br/>Text From Files - <a href="3-tff.html#SP5">&#167;5</a><br/>Loading Preform - <a href="4-lp.html#SP7">&#167;7</a>, <a href="4-lp.html#SP7_3">&#167;7.3</a>, <a href="4-lp.html#SP14_1_1">&#167;14.1.1</a>, <a href="4-lp.html#SP14_1_3">&#167;14.1.3</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2_2">&#167;1.2.1.2.2</a>, <a href="4-prf.html#SP1_2_1_2_3_3">&#167;1.2.1.2.3.3</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3">&#167;1.2.1.2.3.3.3</a>, <a href="4-prf.html#SP1_2_1_2_3_3_5">&#167;1.2.1.2.3.3.5</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3_1">&#167;1.2.1.2.3.3.3.1</a>, <a href="4-prf.html#SP2">&#167;2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">.</span><span class="identifier-syntax">word_B</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
@ -191,7 +191,7 @@ wordings.
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::trim_first_word</span><button class="popup" onclick="togglePopup('usagePopup8')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup8">Usage of <span class="code-font"><span class="function-syntax">Wordings::trim_first_word</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP25_2">&#167;25.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::trim_first_word</span><button class="popup" onclick="togglePopup('usagePopup8')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup8">Usage of <span class="code-font"><span class="function-syntax">Wordings::trim_first_word</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP15_2">&#167;15.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><a href="3-wrd.html#SP12" class="function-link"><span class="function-syntax">Wordings::empty</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">EMPTY_WORDING</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">.</span><span class="element-syntax">word_A</span><span class="plain-syntax">++;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">W</span><span class="plain-syntax">.</span><span class="identifier-syntax">word_A</span><span class="plain-syntax"> &gt; </span><span class="identifier-syntax">W</span><span class="plain-syntax">.</span><span class="identifier-syntax">word_B</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="constant-syntax">EMPTY_WORDING</span><span class="plain-syntax">;</span>
@ -246,7 +246,7 @@ wordings.
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::nonempty</span><button class="popup" onclick="togglePopup('usagePopup11')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup11">Usage of <span class="code-font"><span class="function-syntax">Wordings::nonempty</span></span>:<br/><a href="3-wrd.html#SP11">&#167;11</a>, <a href="3-wrd.html#SP14">&#167;14</a><br/>Word Assemblages - <a href="2-wa.html#SP11">&#167;11</a><br/>Identifiers - <a href="3-idn.html#SP3">&#167;3</a><br/>Loading Preform - <a href="4-lp.html#SP13">&#167;13</a>, <a href="4-lp.html#SP25_2">&#167;25.2</a><br/>Basic Nonterminals - <a href="4-bn.html#SP6">&#167;6</a>, <a href="4-bn.html#SP7">&#167;7</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Wordings::nonempty</span><button class="popup" onclick="togglePopup('usagePopup11')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup11">Usage of <span class="code-font"><span class="function-syntax">Wordings::nonempty</span></span>:<br/><a href="3-wrd.html#SP11">&#167;11</a>, <a href="3-wrd.html#SP14">&#167;14</a><br/>Word Assemblages - <a href="2-wa.html#SP11">&#167;11</a><br/>Identifiers - <a href="3-idn.html#SP3">&#167;3</a><br/>Loading Preform - <a href="4-lp.html#SP15_2">&#167;15.2</a>, <a href="4-lp.html#SP17">&#167;17</a><br/>Basic Nonterminals - <a href="4-bn.html#SP7">&#167;7</a>, <a href="4-bn.html#SP8">&#167;8</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">W</span><span class="plain-syntax">.</span><span class="identifier-syntax">word_A</span><span class="plain-syntax"> &gt;= </span><span class="constant-syntax">0</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">W</span><span class="plain-syntax">.</span><span class="identifier-syntax">word_B</span><span class="plain-syntax"> &gt;= </span><span class="identifier-syntax">W</span><span class="plain-syntax">.</span><span class="element-syntax">word_A</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>

View file

@ -108,7 +108,7 @@ by the Inform compiler modules; all of the rest are defined rather like
</p>
<p class="commentary firstcommentary"><a id="SP2"></a><b>&#167;2. </b>Preform grammar is stored in a text file which is read by Inform early in
its run: see <a href="4-lp.html#SP2" class="internal">LoadPreform::load</a>. In principle, different natural language
its run: see <a href="4-lp.html#SP1" class="internal">LoadPreform::load</a>. In principle, different natural language
definitions can be made: thus, French translators could supply a French-localised
Preform grammar. In practice this whole area of Inform needs more work before
it can really advance. Still, the principle is that the user can therefore
@ -185,8 +185,62 @@ with result 2.
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;race-jersey&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">yellow</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">polkadot</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">green</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">white</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5"></a><b>&#167;5. </b>So far, the only ingredients of Preform syntax have been nonterminals and
fixed words, but Preform also has "wildcards". For example, in
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;competitor&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">man</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">with</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">on</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">his</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">...</span>
</pre>
<p class="commentary">would match, for example, "man with number 17 on his back", or "man with a
chip on his shoulder". <span class="extract"><span class="Preform-extract-syntax">...</span></span> matches any non-empty wording, and the text
actually matched is recorded for any successful match. Wordings like this
are numbered upwards from 1 to a maximum of 4, and are usually retrieved by
whatever part of Inform requested the parse, using the <span class="extract"><span class="Preform-extract-syntax">GET_RW</span></span> macro. For
example:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">TEXT GET_RW(&lt;competitor&gt;, 1) GET_RW(&lt;competitor&gt;, 2)</span>
<span class="plain-syntax">man with number 17 on his back number 17 back</span>
<span class="plain-syntax">man with a chip on his shoulder a chip shoulder</span>
</pre>
<p class="commentary">A few internal nonterminals also generate word ranges, using <span class="extract"><span class="extract-syntax">PUT_RW</span></span> to do so,
and word ranges can also be inherited up from one nonterminal to another with
<span class="extract"><span class="extract-syntax">INHERIT_RANGES</span></span>: see <a href="4-lp.html" class="internal">Loading Preform</a> for definitions of these macros.
</p>
<p class="commentary">There are in fact several different wildcards:
</p>
<ul class="items"><li>(a) <span class="extract"><span class="extract-syntax">...</span></span> matches any non-empty text, as shown above.
</li><li>(b) <span class="extract"><span class="extract-syntax">***</span></span> matches any text, including possibly the empty text.
</li><li>(c) <span class="extract"><span class="extract-syntax">......</span></span> matches any non-empty text in which brackets are used in a
balanced way &mdash; thus they would match "alpha beta gamma" or "alpha (the
Greek letter)", but not "alpha (the" or "Greek letter)".
</li><li>(d) <span class="extract"><span class="extract-syntax">###</span></span> matches any single word, counting words as the lexer does.
</li></ul>
<p class="commentary">It is also possible to use braces to widen ranges. For example,
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;competitor&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">man</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">with</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{...</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">on</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">his</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">...}</span>
</pre>
<p class="commentary">groups together anything matching <span class="extract"><span class="Preform-extract-syntax">... on his ...</span></span> into a single range. There
need not even be a wildcard inside the braces:
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;competitor&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{man}</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">with</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{...</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">on</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">his</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">...}</span>
</pre>
<p class="commentary">works fine, and makes two ranges, the first of which is always just "man".
</p>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="3-idn.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-wm.html">1</a></li><li class="progresschapter"><a href="2-vcb.html">2</a></li><li class="progresschapter"><a href="3-lxr.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresscurrent">ap</li><li class="progresssection"><a href="4-lp.html">lp</a></li><li class="progresssection"><a href="4-to.html">to</a></li><li class="progresssection"><a href="4-prf.html">prf</a></li><li class="progresssection"><a href="4-bn.html">bn</a></li><li class="progressnext"><a href="4-lp.html">&#10095;</a></li></ul></div>
<ul class="progressbar"><li class="progressprev"><a href="3-idn.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-wm.html">1</a></li><li class="progresschapter"><a href="2-vcb.html">2</a></li><li class="progresschapter"><a href="3-lxr.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresscurrent">ap</li><li class="progresssection"><a href="4-nnt.html">nnt</a></li><li class="progresssection"><a href="4-lp.html">lp</a></li><li class="progresssection"><a href="4-to.html">to</a></li><li class="progresssection"><a href="4-prf.html">prf</a></li><li class="progresssection"><a href="4-bn.html">bn</a></li><li class="progressnext"><a href="4-nnt.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>

View file

@ -59,9 +59,26 @@
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../compiler.html">Shared Modules</a></li><li><a href="index.html">words</a></li><li><a href="index.html#4">Chapter 4: Parsing</a></li><li><b>Basic Nonterminals</b></li></ul></div>
<p class="purpose">A handful of bare minimum Preform syntax.</p>
<ul class="toc"><li><a href="4-bn.html#SP1">&#167;1. Text positions</a></li><li><a href="4-bn.html#SP3">&#167;3. Balancing</a></li><li><a href="4-bn.html#SP5">&#167;5. Literal numbers</a></li><li><a href="4-bn.html#SP6">&#167;6. Literal text</a></li></ul><hr class="tocbar">
<ul class="toc"><li><a href="4-bn.html#SP1">&#167;1. Nonterminal names</a></li><li><a href="4-bn.html#SP2">&#167;2. Text positions</a></li><li><a href="4-bn.html#SP4">&#167;4. Balancing</a></li><li><a href="4-bn.html#SP6">&#167;6. Literal numbers</a></li><li><a href="4-bn.html#SP7">&#167;7. Literal text</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1"></a><b>&#167;1. Text positions. </b>A useful nonterminal which matches no text, but detects the position:
<p class="commentary firstcommentary"><a id="SP1"></a><b>&#167;1. Nonterminal names. </b>This is a typical internal nonterminal being defined, though it's a bit more
meta than most &mdash; it's a nonterminal which matches against the name of any
nonterminal. (This is used only to parse inclusion requests for the debugging
log.)
</p>
<p class="commentary">Note that we use the <span class="extract"><span class="extract-syntax">internal 1</span></span> to signal that a correct match must have
exactly one word.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;preform-nonterminal&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</span><span class="plain-syntax"> = </span><a href="4-nnt.html#SP7" class="function-link"><span class="function-syntax">Nonterminals::detect</span></a><span class="plain-syntax">(</span><a href="3-lxr.html#SP20" class="function-link"><span class="function-syntax">Lexer::word</span></a><span class="plain-syntax">(</span><a href="3-wrd.html#SP8" class="function-link"><span class="function-syntax">Wordings::first_wn</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)));</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">nt</span><span class="plain-syntax">) { *</span><span class="identifier-syntax">XP</span><span class="plain-syntax"> = </span><span class="identifier-syntax">nt</span><span class="plain-syntax">; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2"></a><b>&#167;2. Text positions. </b>A useful nonterminal which matches no text, but detects the position:
</p>
<pre class="displayed-code all-displayed-code code-font">
@ -71,7 +88,7 @@
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2"></a><b>&#167;2. </b>And another convenience:
<p class="commentary firstcommentary"><a id="SP3"></a><b>&#167;3. </b>And another convenience:
</p>
<pre class="displayed-code all-displayed-code code-font">
@ -81,8 +98,8 @@
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3"></a><b>&#167;3. Balancing. </b>The following matches any text in which braces and brackets are correctly
paired.
<p class="commentary firstcommentary"><a id="SP4"></a><b>&#167;4. Balancing. </b>The following regular (not internal!) nonterminal matches any text in which
braces and brackets are correctly paired.
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
@ -90,7 +107,7 @@ paired.
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">......</span>
</pre>
<ul class="endnotetexts"><li>This is <a href="4-prf.html" class="internal">Preform grammar</a>, not regular C code.</li></ul>
<p class="commentary firstcommentary"><a id="SP4"></a><b>&#167;4. </b>Inform contains relatively few syntaxes where commas are actually required,
<p class="commentary firstcommentary"><a id="SP5"></a><b>&#167;5. </b>Inform contains relatively few syntaxes where commas are actually required,
though they can optionally be used in many lists, as here:
</p>
@ -107,7 +124,7 @@ that the comma matches only if not in brackets.
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">......</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">,</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">......</span>
</pre>
<ul class="endnotetexts"><li>This is <a href="4-prf.html" class="internal">Preform grammar</a>, not regular C code.</li></ul>
<p class="commentary firstcommentary"><a id="SP5"></a><b>&#167;5. Literal numbers. </b>(Inform itself doesn't use this, but has alternatives for cardinals and
<p class="commentary firstcommentary"><a id="SP6"></a><b>&#167;6. Literal numbers. </b>(Inform itself doesn't use this, but has alternatives for cardinals and
ordinals within the VM-representable range.)
</p>
@ -121,40 +138,44 @@ ordinals within the VM-representable range.)
<span class="Preform-plain-syntax">}</span>
</pre>
<ul class="endnotetexts"><li>This is <a href="4-prf.html" class="internal">Preform grammar</a>, not regular C code.</li></ul>
<p class="commentary firstcommentary"><a id="SP6"></a><b>&#167;6. Literal text. </b>Text is "with substitutions" if it contains square brackets, used in Inform
<p class="commentary firstcommentary"><a id="SP7"></a><b>&#167;7. Literal text. </b>Text is "with substitutions" if it contains square brackets, used in Inform
for interpolations called "text substitutions".
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-function-syntax">&lt;quoted-text&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">internal</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">1</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">if</span><span class="Preform-plain-syntax"> ((</span><a href="3-wrd.html#SP12" class="function-link"><span class="Preform-function-syntax">Wordings::nonempty</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">)) &amp;&amp; (</span><a href="2-vcb.html#SP10" class="function-link"><span class="Preform-function-syntax">Vocabulary::test_flags</span></a><span class="Preform-plain-syntax">(</span><a href="3-wrd.html#SP8" class="function-link"><span class="Preform-function-syntax">Wordings::first_wn</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">), </span><span class="Preform-constant-syntax">TEXT_MC</span><span class="Preform-plain-syntax">+</span><span class="Preform-constant-syntax">TEXTWITHSUBS_MC</span><span class="Preform-plain-syntax">))) {</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">if</span><span class="Preform-plain-syntax"> ((</span><a href="3-wrd.html#SP12" class="function-link"><span class="Preform-function-syntax">Wordings::nonempty</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">)) &amp;&amp;</span>
<span class="Preform-plain-syntax"> (</span><a href="2-vcb.html#SP10" class="function-link"><span class="Preform-function-syntax">Vocabulary::test_flags</span></a><span class="Preform-plain-syntax">(</span><a href="3-wrd.html#SP8" class="function-link"><span class="Preform-function-syntax">Wordings::first_wn</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">), </span><span class="Preform-constant-syntax">TEXT_MC</span><span class="Preform-plain-syntax">+</span><span class="Preform-constant-syntax">TEXTWITHSUBS_MC</span><span class="Preform-plain-syntax">))) {</span>
<span class="Preform-plain-syntax"> *</span><span class="Preform-identifier-syntax">X</span><span class="Preform-plain-syntax"> = </span><a href="3-wrd.html#SP8" class="function-link"><span class="Preform-function-syntax">Wordings::first_wn</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">); </span><span class="Preform-reserved-syntax">return</span><span class="Preform-plain-syntax"> </span><span class="Preform-identifier-syntax">TRUE</span><span class="Preform-plain-syntax">;</span>
<span class="Preform-plain-syntax"> }</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">return</span><span class="Preform-plain-syntax"> </span><span class="Preform-identifier-syntax">FALSE</span><span class="Preform-plain-syntax">;</span>
<span class="Preform-plain-syntax">}</span>
<span class="Preform-function-syntax">&lt;quoted-text-with-subs&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">internal</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">1</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">if</span><span class="Preform-plain-syntax"> ((</span><a href="3-wrd.html#SP12" class="function-link"><span class="Preform-function-syntax">Wordings::nonempty</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">)) &amp;&amp; (</span><a href="2-vcb.html#SP10" class="function-link"><span class="Preform-function-syntax">Vocabulary::test_flags</span></a><span class="Preform-plain-syntax">(</span><a href="3-wrd.html#SP8" class="function-link"><span class="Preform-function-syntax">Wordings::first_wn</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">), </span><span class="Preform-constant-syntax">TEXTWITHSUBS_MC</span><span class="Preform-plain-syntax">))) {</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">if</span><span class="Preform-plain-syntax"> ((</span><a href="3-wrd.html#SP12" class="function-link"><span class="Preform-function-syntax">Wordings::nonempty</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">)) &amp;&amp;</span>
<span class="Preform-plain-syntax"> (</span><a href="2-vcb.html#SP10" class="function-link"><span class="Preform-function-syntax">Vocabulary::test_flags</span></a><span class="Preform-plain-syntax">(</span><a href="3-wrd.html#SP8" class="function-link"><span class="Preform-function-syntax">Wordings::first_wn</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">), </span><span class="Preform-constant-syntax">TEXTWITHSUBS_MC</span><span class="Preform-plain-syntax">))) {</span>
<span class="Preform-plain-syntax"> *</span><span class="Preform-identifier-syntax">X</span><span class="Preform-plain-syntax"> = </span><a href="3-wrd.html#SP8" class="function-link"><span class="Preform-function-syntax">Wordings::first_wn</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">); </span><span class="Preform-reserved-syntax">return</span><span class="Preform-plain-syntax"> </span><span class="Preform-identifier-syntax">TRUE</span><span class="Preform-plain-syntax">;</span>
<span class="Preform-plain-syntax"> }</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">return</span><span class="Preform-plain-syntax"> </span><span class="Preform-identifier-syntax">FALSE</span><span class="Preform-plain-syntax">;</span>
<span class="Preform-plain-syntax">}</span>
<span class="Preform-function-syntax">&lt;quoted-text-without-subs&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">internal</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">1</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">if</span><span class="Preform-plain-syntax"> ((</span><a href="3-wrd.html#SP12" class="function-link"><span class="Preform-function-syntax">Wordings::nonempty</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">)) &amp;&amp; (</span><a href="2-vcb.html#SP10" class="function-link"><span class="Preform-function-syntax">Vocabulary::test_flags</span></a><span class="Preform-plain-syntax">(</span><a href="3-wrd.html#SP8" class="function-link"><span class="Preform-function-syntax">Wordings::first_wn</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">), </span><span class="Preform-constant-syntax">TEXT_MC</span><span class="Preform-plain-syntax">))) {</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">if</span><span class="Preform-plain-syntax"> ((</span><a href="3-wrd.html#SP12" class="function-link"><span class="Preform-function-syntax">Wordings::nonempty</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">)) &amp;&amp;</span>
<span class="Preform-plain-syntax"> (</span><a href="2-vcb.html#SP10" class="function-link"><span class="Preform-function-syntax">Vocabulary::test_flags</span></a><span class="Preform-plain-syntax">(</span><a href="3-wrd.html#SP8" class="function-link"><span class="Preform-function-syntax">Wordings::first_wn</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">), </span><span class="Preform-constant-syntax">TEXT_MC</span><span class="Preform-plain-syntax">))) {</span>
<span class="Preform-plain-syntax"> *</span><span class="Preform-identifier-syntax">X</span><span class="Preform-plain-syntax"> = </span><a href="3-wrd.html#SP8" class="function-link"><span class="Preform-function-syntax">Wordings::first_wn</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">); </span><span class="Preform-reserved-syntax">return</span><span class="Preform-plain-syntax"> </span><span class="Preform-identifier-syntax">TRUE</span><span class="Preform-plain-syntax">;</span>
<span class="Preform-plain-syntax"> }</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">return</span><span class="Preform-plain-syntax"> </span><span class="Preform-identifier-syntax">FALSE</span><span class="Preform-plain-syntax">;</span>
<span class="Preform-plain-syntax">}</span>
</pre>
<ul class="endnotetexts"><li>This is <a href="4-prf.html" class="internal">Preform grammar</a>, not regular C code.</li></ul>
<p class="commentary firstcommentary"><a id="SP7"></a><b>&#167;7. </b>For finicky technical reasons the easiest way to detect an empty piece
<p class="commentary firstcommentary"><a id="SP8"></a><b>&#167;8. </b>For finicky technical reasons the easiest way to detect an empty piece
of text <span class="extract"><span class="Preform-extract-syntax">""</span></span> is to provide a nonterminal matching it:
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-function-syntax">&lt;empty-text&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">internal</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">1</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">{</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">if</span><span class="Preform-plain-syntax"> ((</span><a href="3-wrd.html#SP12" class="function-link"><span class="Preform-function-syntax">Wordings::nonempty</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">)) &amp;&amp; (</span><a href="2-nw.html#SP2" class="function-link"><span class="Preform-function-syntax">Word::compare_by_strcmp</span></a><span class="Preform-plain-syntax">(</span><a href="3-wrd.html#SP8" class="function-link"><span class="Preform-function-syntax">Wordings::first_wn</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">), </span><span class="Preform-identifier-syntax">L</span><span class="Preform-string-syntax">"\"\""</span><span class="Preform-plain-syntax">))) {</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">if</span><span class="Preform-plain-syntax"> ((</span><a href="3-wrd.html#SP12" class="function-link"><span class="Preform-function-syntax">Wordings::nonempty</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">)) &amp;&amp;</span>
<span class="Preform-plain-syntax"> (</span><a href="2-nw.html#SP2" class="function-link"><span class="Preform-function-syntax">Word::compare_by_strcmp</span></a><span class="Preform-plain-syntax">(</span><a href="3-wrd.html#SP8" class="function-link"><span class="Preform-function-syntax">Wordings::first_wn</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">), </span><span class="Preform-identifier-syntax">L</span><span class="Preform-string-syntax">"\"\""</span><span class="Preform-plain-syntax">))) {</span>
<span class="Preform-plain-syntax"> *</span><span class="Preform-identifier-syntax">X</span><span class="Preform-plain-syntax"> = </span><a href="3-wrd.html#SP8" class="function-link"><span class="Preform-function-syntax">Wordings::first_wn</span></a><span class="Preform-plain-syntax">(</span><span class="Preform-identifier-syntax">W</span><span class="Preform-plain-syntax">); </span><span class="Preform-reserved-syntax">return</span><span class="Preform-plain-syntax"> </span><span class="Preform-identifier-syntax">TRUE</span><span class="Preform-plain-syntax">;</span>
<span class="Preform-plain-syntax"> }</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">return</span><span class="Preform-plain-syntax"> </span><span class="Preform-identifier-syntax">FALSE</span><span class="Preform-plain-syntax">;</span>
@ -162,7 +183,7 @@ of text <span class="extract"><span class="Preform-extract-syntax">""</span></sp
</pre>
<ul class="endnotetexts"><li>This is <a href="4-prf.html" class="internal">Preform grammar</a>, not regular C code.</li></ul>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="4-prf.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-wm.html">1</a></li><li class="progresschapter"><a href="2-vcb.html">2</a></li><li class="progresschapter"><a href="3-lxr.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresssection"><a href="4-ap.html">ap</a></li><li class="progresssection"><a href="4-lp.html">lp</a></li><li class="progresssection"><a href="4-to.html">to</a></li><li class="progresssection"><a href="4-prf.html">prf</a></li><li class="progresscurrent">bn</li><li class="progressnextoff">&#10095;</li></ul></div>
<ul class="progressbar"><li class="progressprev"><a href="4-prf.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-wm.html">1</a></li><li class="progresschapter"><a href="2-vcb.html">2</a></li><li class="progresschapter"><a href="3-lxr.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresssection"><a href="4-ap.html">ap</a></li><li class="progresssection"><a href="4-nnt.html">nnt</a></li><li class="progresssection"><a href="4-lp.html">lp</a></li><li class="progresssection"><a href="4-to.html">to</a></li><li class="progresssection"><a href="4-prf.html">prf</a></li><li class="progresscurrent">bn</li><li class="progressnextoff">&#10095;</li></ul></div>
</nav><!--End of weave-->
</main>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,360 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Nonterminals</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
var popup = document.getElementById(material_id);
popup.classList.toggle("show");
}
</script>
<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
MathJax = {
tex: {
inlineMath: '$', '$'], ['\\(', '\\)'
},
svg: {
fontCache: 'global'
}
};
</script>
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Preform-Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body class="commentary-font">
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-assets/Inform.png" height=72">
</a></h1>
<ul><li><a href="../compiler.html">compiler tools</a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul><h2>Compiler Webs</h2><ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul><h2>Inbuild Modules</h2><ul>
<li><a href="../supervisor-module/index.html">supervisor</a></li>
</ul><h2>Inform7 Modules</h2><ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../problems-module/index.html">problems</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul><h2>Inter Modules</h2><ul>
<li><a href="../bytecode-module/index.html">bytecode</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../codegen-module/index.html">codegen</a></li>
</ul><h2>Shared Modules</h2><ul>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="index.html"><span class="selectedlink">words</span></a></li>
<li><a href="../html-module/index.html">html</a></li>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'Nonterminals' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../compiler.html">Shared Modules</a></li><li><a href="index.html">words</a></li><li><a href="index.html#4">Chapter 4: Parsing</a></li><li><b>Nonterminals</b></li></ul></div>
<p class="purpose">The angle-bracketed terms appearing in Preform grammar.</p>
<ul class="toc"><li><a href="4-nnt.html#SP1">&#167;1. How nonterminals are stored</a></li><li><a href="4-nnt.html#SP9">&#167;9. Word ranges in a nonterminal</a></li><li><a href="4-nnt.html#SP10">&#167;10. Other results</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1"></a><b>&#167;1. How nonterminals are stored. </b>Each different nonterminal defined in the <span class="extract"><span class="extract-syntax">Syntax.preform</span></span> code read in,
such as &lt;any-integer&gt;, is going to correspond to a global variable in the
program reading it in, such as <span class="extract"><span class="extract-syntax">any_integer_NTM</span></span>. On the face of it, this is
impossible. How can what happens at run-time affect what variables are named
at compile time?
</p>
<p class="commentary">The answer is that the <a href="../../../inweb/docs/index.html" class="internal">inweb</a> literate programming tool looks through the
complete source code, sees the Preform nonterminals described in it, and
inserts declarations of the corresponding variables into the "tangled" form
of the source code sent to a C compiler to make the actual program. (This is
a feature of <a href="../../../inweb/docs/index.html" class="internal">inweb</a> available only for programs written in InC.)
</p>
<p class="commentary">In particular, the tangler of <span class="extract"><span class="extract-syntax">inweb</span></span> replaces the <span class="extract"><span class="extract-syntax">[[nonterminals]]</span></span> below with
invocations of the <span class="extract"><span class="extract-syntax">REGISTER_NONTERMINAL</span></span> and <span class="extract"><span class="extract-syntax">INTERNAL_NONTERMINAL</span></span> macros.
For example, it inserts the C line:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">INTERNAL_NONTERMINAL</span><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"&lt;any-integer&gt;"</span><span class="plain-syntax">, </span><span class="identifier-syntax">any_integer_NTM</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
</pre>
<p class="commentary">since this is an "internal" nonterminal; and the macro will then expand
to code which sets up <span class="extract"><span class="extract-syntax">any_integer_NTM</span></span> &mdash; see below.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Nonterminals::register</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Nonterminals::register</span></span>:<br/>Words Module - <a href="1-wm.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> The following is not valid C, but causes Inweb to insert lines which are</span>
<span class="plain-syntax"> [[</span><span class="identifier-syntax">nonterminals</span><span class="plain-syntax">]];</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> Back to regular C now</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">marked_internal</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">internal_definition</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">))</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"internal nonterminal has no definition function"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP2"></a><b>&#167;2. </b>So, then, <a href="../../../inweb/docs/index.html" class="internal">inweb</a> tangles out code which uses the <span class="extract"><span class="extract-syntax">REGISTER_NONTERMINAL</span></span>
macro for any standard nonterminal, and also tangles a compositor function for
it; the name of which is the nonterminal's name with a <span class="extract"><span class="extract-syntax">C</span></span> suffix. For example,
suppose <a href="../../../inweb/docs/index.html" class="internal">inweb</a> sees the following in the web it is tangling:
</p>
<pre class="Preform-displayed-code all-displayed-code code-font">
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;competitor&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">::=</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">the</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">pacemaker</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> 1</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;ordinal-number&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">runner</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">|</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> R[1]</span>
<span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">runner</span><span class="Preform-plain-syntax"> </span><span class="Preform-constant-syntax">no</span><span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax">&lt;cardinal-number&gt;</span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==&gt;</span><span class="Preform-plain-syntax"> R[1]</span>
</pre>
<p class="commentary">It then tangles this macro usage into <a href="4-nnt.html#SP1" class="internal">Nonterminals::register</a> above:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">REGISTER_NONTERMINAL</span><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"&lt;competitor&gt;"</span><span class="plain-syntax">, </span><span class="identifier-syntax">competitor_NTM</span><span class="plain-syntax">);</span>
</pre>
<p class="commentary">And it also tangles matching declarations for:
</p>
<ul class="items"><li>(a) the global variable <span class="extract"><span class="extract-syntax">competitor_NTM</span></span>, of type <span class="extract"><span class="extract-syntax">nonterminal *</span></span>;
</li><li>(b) the "compositor function" <span class="extract"><span class="extract-syntax">competitor_NTMC</span></span>, which is a function to
deal with what happens when a successful match is made against the grammar &mdash;
this incorporates the material which <a href="../../../inweb/docs/index.html" class="internal">inweb</a> finds to the right of the <span class="extract"><span class="extract-syntax">==&gt;</span></span>
markers in the Preform definition.
</li></ul>
<p class="commentary">But if we left things at that, we would find ourselves at run-time with
a null variable, a function not called from anywhere, and an instance
somewhere in memory of a nonterminal read in from Preform syntax and
called <span class="extract"><span class="extract-syntax">"&lt;competitor&gt;"</span></span>, but which has no apparent connection to either
the function or the variable. We clearly need to join these together.
</p>
<p class="commentary">And so the <span class="extract"><span class="extract-syntax">REGISTER_NONTERMINAL</span></span> macro expands to code which initialises the
variable to the nonterminal having its name, and then connects that to the
compositor function:
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="identifier-syntax">REGISTER_NONTERMINAL</span><span class="plain-syntax">(</span><span class="identifier-syntax">quotedname</span><span class="plain-syntax">, </span><span class="identifier-syntax">identifier</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">identifier</span><span class="plain-syntax"> = </span><a href="4-nnt.html#SP8" class="function-link"><span class="function-syntax">Nonterminals::find</span></a><span class="plain-syntax">(</span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">quotedname</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">identifier</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">result_compositor</span><span class="plain-syntax"> = </span><span class="identifier-syntax">identifier</span><span class="plain-syntax">##</span><span class="identifier-syntax">C</span><span class="plain-syntax">;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3"></a><b>&#167;3. </b>For example, this might expand to:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="identifier-syntax">competitor_NTM</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Nonterminals</span><span class="plain-syntax">::</span><span class="identifier-syntax">find</span><span class="plain-syntax">(</span><span class="identifier-syntax">Vocabulary</span><span class="plain-syntax">::</span><span class="identifier-syntax">entry_for_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">L</span><span class="string-syntax">"&lt;competitor&gt;"</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">competitor_NTM</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">result_compositor</span><span class="plain-syntax"> = </span><span class="identifier-syntax">competitor_NTMC</span><span class="plain-syntax">;</span>
</pre>
<p class="commentary">Note that it is absolutely necessary that <span class="extract"><span class="extract-syntax">Nonterminals::find</span></span> does
return a nonterminal. But we can be sure that it does, since the function creates
a nonterminal object of that name even if one does not already exist.
</p>
<p class="commentary firstcommentary"><a id="SP4"></a><b>&#167;4. </b>The position for internal nonterminals (i.e. those defined by a function
written by the programmer, not by Preform grammar lines) is similar:
</p>
<ul class="items"><li>(a) again there is a global variable, say <span class="extract"><span class="extract-syntax">any_integer_NTM</span></span>, of type <span class="extract"><span class="extract-syntax">nonterminal *</span></span>;
</li><li>(b) but now there is no compositor, and instead there is a function <span class="extract"><span class="extract-syntax">any_integer_NTMR</span></span>
which actually performs the parse directly.
</li></ul>
<p class="commentary">The <span class="extract"><span class="extract-syntax">INTERNAL_NONTERMINAL</span></span> macro similarly initialises and connects these
declarations. <span class="extract"><span class="extract-syntax">min</span></span> and <span class="extract"><span class="extract-syntax">max</span></span> are conveniences for speedy parsing, and supply
the minimum and maximum number of words that the nonterminal can match; these
are needed because the Preform optimiser can't see inside <span class="extract"><span class="extract-syntax">any_integer_NTMR</span></span> to
calculate those bounds for itself. <span class="extract"><span class="extract-syntax">max</span></span> can be infinity, in which case we
use the constant <span class="extract"><span class="extract-syntax">INFINITE_WORD_COUNT</span></span> for it.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">INFINITE_WORD_COUNT</span><span class="plain-syntax"> </span><span class="constant-syntax">1000000000</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">INTERNAL_NONTERMINAL</span><span class="plain-syntax">(</span><span class="identifier-syntax">quotedname</span><span class="plain-syntax">, </span><span class="identifier-syntax">identifier</span><span class="plain-syntax">, </span><span class="identifier-syntax">min</span><span class="plain-syntax">, </span><span class="identifier-syntax">max</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">identifier</span><span class="plain-syntax"> = </span><a href="4-nnt.html#SP8" class="function-link"><span class="function-syntax">Nonterminals::find</span></a><span class="plain-syntax">(</span><a href="2-vcb.html#SP15" class="function-link"><span class="function-syntax">Vocabulary::entry_for_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">quotedname</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">identifier</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">min_nt_words</span><span class="plain-syntax"> = </span><span class="identifier-syntax">min</span><span class="plain-syntax">; </span><span class="identifier-syntax">identifier</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">max_nt_words</span><span class="plain-syntax"> = </span><span class="identifier-syntax">max</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">identifier</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">internal_definition</span><span class="plain-syntax"> = </span><span class="identifier-syntax">identifier</span><span class="plain-syntax">##</span><span class="identifier-syntax">R</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">identifier</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">marked_internal</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5"></a><b>&#167;5. </b>So, then, the following rather lengthy class declaration shows what goes
into a nonterminal. Note that nonterminals are uniquely identifiable by their
names: there can be only one called, say, &lt;any-integer&gt;. This is why its
textual name is referred to as an "ID".
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nonterminal_id</span><span class="plain-syntax">; </span><span class="comment-syntax"> e.g. </span><span class="extract"><span class="extract-syntax">"&lt;any-integer&gt;"</span></span>
<span class="plain-syntax"> </span><span class="comment-syntax"> For internal nonterminals</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">marked_internal</span><span class="plain-syntax">; </span><span class="comment-syntax"> has, or will be given, an internal definition...</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">internal_definition</span><span class="plain-syntax">)(</span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *</span><span class="identifier-syntax">result</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> **</span><span class="identifier-syntax">result_p</span><span class="plain-syntax">); </span><span class="comment-syntax"> ...this one</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">voracious</span><span class="plain-syntax">; </span><span class="comment-syntax"> if true, scans whole rest of word range</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> For regular nonterminals</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">production_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">first_production_list</span><span class="plain-syntax">; </span><span class="comment-syntax"> if not internal, this defines it</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> (*</span><span class="identifier-syntax">result_compositor</span><span class="plain-syntax">)(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> *</span><span class="identifier-syntax">r</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> **</span><span class="identifier-syntax">rp</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> *</span><span class="identifier-syntax">inters</span><span class="plain-syntax">, </span><span class="reserved-syntax">void</span><span class="plain-syntax"> **</span><span class="identifier-syntax">inter_ps</span><span class="plain-syntax">, </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> *</span><span class="identifier-syntax">interW</span><span class="plain-syntax">, </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">multiplicitous</span><span class="plain-syntax">; </span><span class="comment-syntax"> if true, matches are alternative syntax tree readings</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> Storage for most recent correct match</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">range_result</span><span class="plain-syntax">[</span><span class="constant-syntax">MAX_RANGES_PER_PRODUCTION</span><span class="plain-syntax">]; </span><span class="comment-syntax"> storage for word ranges matched</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> Optimiser data</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">optimised_in_this_pass</span><span class="plain-syntax">; </span><span class="comment-syntax"> have the following been worked out yet?</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">min_nt_words</span><span class="plain-syntax">, </span><span class="identifier-syntax">max_nt_words</span><span class="plain-syntax">; </span><span class="comment-syntax"> for speed</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">range_requirement</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal_req</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">nt_req_bit</span><span class="plain-syntax">; </span><span class="comment-syntax"> which hashing category the words belong to, or </span>\(-1\)<span class="comment-syntax"> if none</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">number_words_by_production</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">unsigned</span><span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">flag_words_in_production</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="comment-syntax"> For debugging only</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">watched</span><span class="plain-syntax">; </span><span class="comment-syntax"> watch goings-on to the debugging log</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal_tries</span><span class="plain-syntax">; </span><span class="comment-syntax"> for statistics collected in instrumented mode</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal_matches</span><span class="plain-syntax">; </span><span class="comment-syntax"> ditto</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure nonterminal is accessed in 4/lp, 4/to, 4/prf and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP6"></a><b>&#167;6. </b>A few notes on this are in order:
</p>
<ul class="items"><li>(a) As noted above, every nonterminal is either "internal" or "regular". If
internal, it is defined by a function; if regular, it is defined by lines
of grammar (called "productions") and a compositor function.
</li><li>(b) A few internal nonterminals are "voracious". These are given the entire
word range for their productions to eat, and encouraged to eat as much as they
like, returning a word number to show how far they got. While this effect
could be duplicated with non-voracious nonterminals, that would be quite a bit
slower, since it would have to test every possible word range.
</li><li>(c) A few regular nonterminals are "multiplicitous". These composite their
results in a way special to the Inform compiler's syntax tree, by stacking
them up as alternative possible readings of the same text. Ordinarily, the
result of parsing text against a nonterminal is that the first grammar line
matching that text determines the meaning, but for a multiplicitous nonterminal,
every line matching the text determines one of perhaps many possible meanings.
</li><li>(d) The optimisation data helps the parser to reject non-matching text quickly.
For example, if the optimiser can determine that &lt;competitor&gt; only ever matches
texts of between 3 and 7 words in length, it can quickly reject any run of
words outside that range. (However: note that a maximum of 0 means that the
maximum and minimum word counts are disregarded.) The other fields are harder
to explain &mdash; see <a href="4-to.html" class="internal">The Optimiser</a>.
</li></ul>
<p class="commentary firstcommentary"><a id="SP7"></a><b>&#167;7. </b>So, then, as noted above, nonterminals are identified by their name-words.
The following is not especially fast but doesn't need to be: it's used only
when Preform grammar is parsed, not when Inform text is parsed.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="function-syntax">Nonterminals::detect</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">Nonterminals::detect</span></span>:<br/><a href="4-nnt.html#SP8">&#167;8</a><br/>Basic Nonterminals - <a href="4-bn.html#SP1">&#167;1</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name_word</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">name_word</span><span class="plain-syntax"> == </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">nonterminal_id</span><span class="plain-syntax">)</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8"></a><b>&#167;8. </b>And the following always returns one, creating it if necessary:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="function-syntax">Nonterminals::find</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">Nonterminals::find</span></span>:<br/><a href="4-nnt.html#SP2">&#167;2</a>, <a href="4-nnt.html#SP4">&#167;4</a><br/>Loading Preform - <a href="4-lp.html#SP7_2">&#167;7.2</a>, <a href="4-lp.html#SP7_3">&#167;7.3</a>, <a href="4-lp.html#SP16">&#167;16</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">vocabulary_entry</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name_word</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</span><span class="plain-syntax"> = </span><a href="4-nnt.html#SP7" class="function-link"><span class="function-syntax">Nonterminals::detect</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">name_word</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">nt</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">nonterminal_id</span><span class="plain-syntax"> = </span><span class="identifier-syntax">name_word</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">marked_internal</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">; </span><span class="comment-syntax"> by default, nonterminals are regular</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">internal_definition</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">voracious</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="constant-syntax">MAX_RANGES_PER_PRODUCTION</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++)</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">range_result</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="constant-syntax">EMPTY_WORDING</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">first_production_list</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">result_compositor</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">multiplicitous</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">optimised_in_this_pass</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">min_nt_words</span><span class="plain-syntax"> = </span><span class="constant-syntax">1</span><span class="plain-syntax">; </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">max_nt_words</span><span class="plain-syntax"> = </span><span class="constant-syntax">INFINITE_WORD_COUNT</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">nt_req_bit</span><span class="plain-syntax"> = -1;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">number_words_by_production</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">flag_words_in_production</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">watched</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">nonterminal_tries</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">nonterminal_matches</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">nt</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9"></a><b>&#167;9. Word ranges in a nonterminal. </b>We now need to define the macros <span class="extract"><span class="extract-syntax">GET_RW</span></span> and <span class="extract"><span class="extract-syntax">PUT_RW</span></span>, which get and set
the results of a successful match against a nonterminal (see <a href="4-ap.html" class="internal">About Preform</a>
for more on this).
</p>
<p class="commentary">We do so by giving each nonterminal a small array of <span class="extract"><span class="extract-syntax">wording</span></span>s, which are
lightweight structures incurring little time or space overhead. The fact that
they are attached to the NT itself, rather than, say, being placed on a
parsing stack of some kind, makes them faster to access, but is possible only
because the parser never backtracks. Similarly, results word ranges are
overwritten if a nonterminal calls itself directly or indirectly: that is, the
inner one's results are wiped out by the outer one. But this is no problem,
since we never extract word-ranges from grammar which is recursive.
</p>
<p class="commentary">Word range 0 is reserved in case we ever need it for the entire text matched
by the nonterminal, though at present we don't need that.
</p>
<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">MAX_RANGES_PER_PRODUCTION</span><span class="plain-syntax"> </span><span class="constant-syntax">5</span><span class="plain-syntax"> </span><span class="comment-syntax"> in fact, one less than this, since range 0 is reserved</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">GET_RW</span><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">N</span><span class="plain-syntax">) (</span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">range_result</span><span class="plain-syntax">[</span><span class="identifier-syntax">N</span><span class="plain-syntax">])</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">PUT_RW</span><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="identifier-syntax">N</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">) { </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">range_result</span><span class="plain-syntax">[</span><span class="identifier-syntax">N</span><span class="plain-syntax">] = </span><span class="identifier-syntax">W</span><span class="plain-syntax">; }</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">INHERIT_RANGES</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">, </span><span class="identifier-syntax">to</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=1; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="constant-syntax">MAX_RANGES_PER_PRODUCTION</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) </span><span class="comment-syntax"> not copying range 0</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">to</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">range_result</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">range_result</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">];</span>
<span class="plain-syntax">}</span>
<span class="definition-keyword">define</span> <span class="identifier-syntax">CLEAR_RW</span><span class="plain-syntax">(</span><span class="identifier-syntax">from</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;</span><span class="constant-syntax">MAX_RANGES_PER_PRODUCTION</span><span class="plain-syntax">; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) </span><span class="comment-syntax"> including range 0</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">range_result</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">] = </span><span class="constant-syntax">EMPTY_WORDING</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP10"></a><b>&#167;10. Other results. </b>The parser records the result of the most recently matched nonterminal in the
following global variables &mdash; which, unlike word ranges, are not attached to
any single NT.
</p>
<p class="commentary"><a href="../../../inweb/docs/index.html" class="internal">inweb</a> translates the notation <span class="extract"><span class="extract-syntax">&lt;&lt;r&gt;&gt;</span></span> and <span class="extract"><span class="extract-syntax">&lt;&lt;rp&gt;&gt;</span></span> to these variable names:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">most_recent_result</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="comment-syntax"> the variable which </span><span class="extract"><span class="extract-syntax">inweb</span></span><span class="comment-syntax"> writes </span><span class="extract"><span class="extract-syntax">&lt;&lt;r&gt;&gt;</span></span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> *</span><span class="identifier-syntax">most_recent_result_p</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="comment-syntax"> the variable which </span><span class="extract"><span class="extract-syntax">inweb</span></span><span class="comment-syntax"> writes </span><span class="extract"><span class="extract-syntax">&lt;&lt;rp&gt;&gt;</span></span>
</pre>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="4-ap.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-wm.html">1</a></li><li class="progresschapter"><a href="2-vcb.html">2</a></li><li class="progresschapter"><a href="3-lxr.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresssection"><a href="4-ap.html">ap</a></li><li class="progresscurrent">nnt</li><li class="progresssection"><a href="4-lp.html">lp</a></li><li class="progresssection"><a href="4-to.html">to</a></li><li class="progresssection"><a href="4-prf.html">prf</a></li><li class="progresssection"><a href="4-bn.html">bn</a></li><li class="progressnext"><a href="4-lp.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>

View file

@ -187,7 +187,7 @@ an internal NT, or try all possible productions for an external one.
<span class="plain-syntax"> </span><span class="reserved-syntax">production_list</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pl</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">first_production_list</span><span class="plain-syntax">; </span><span class="identifier-syntax">pl</span><span class="plain-syntax">; </span><span class="identifier-syntax">pl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pl</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_production_list</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="constant-syntax">NATURAL_LANGUAGE_WORDS_TYPE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nl</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pl</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">definition_language</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">language_of_source_text</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">language_of_source_text</span><span class="plain-syntax"> == </span><span class="identifier-syntax">nl</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">primary_Preform_language</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) || (</span><span class="identifier-syntax">primary_Preform_language</span><span class="plain-syntax"> == </span><span class="identifier-syntax">nl</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">production</span><span class="plain-syntax"> *</span><span class="identifier-syntax">pr</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">last_v</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="identifier-syntax">pr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pl</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">first_production</span><span class="plain-syntax">; </span><span class="identifier-syntax">pr</span><span class="plain-syntax">; </span><span class="identifier-syntax">pr</span><span class="plain-syntax"> = </span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">next_production</span><span class="plain-syntax">) {</span>
@ -202,7 +202,7 @@ an internal NT, or try all possible productions for an external one.
<span class="plain-syntax"> } </span><span class="reserved-syntax">else</span><span class="plain-syntax"> {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ptraci</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"production in %V: "</span><span class="plain-syntax">, </span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">nonterminal_id</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-lp.html#SP14" class="function-link"><span class="function-syntax">LoadPreform::log_production</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pr</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-lp.html#SP18" class="function-link"><span class="function-syntax">LoadPreform::log_production</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pr</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">": &lt;%W&gt; violates "</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-to.html#SP16" class="function-link"><span class="function-syntax">Optimiser::log_range_requirement</span></a><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">production_req</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"\n"</span><span class="plain-syntax">);</span>
@ -236,7 +236,7 @@ text against a production.
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">ptraci</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOG_INDENT</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="named-paragraph-container code-font"><a href="4-prf.html#SP1_2_1_1" class="named-paragraph-link"><span class="named-paragraph">Log the production match number</span><span class="named-paragraph-number">1.2.1.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><a href="4-lp.html#SP14" class="function-link"><span class="function-syntax">LoadPreform::log_production</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pr</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">); </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="4-lp.html#SP18" class="function-link"><span class="function-syntax">LoadPreform::log_production</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">pr</span><span class="plain-syntax">, </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">); </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"\n"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> }</span>
<span class="plain-syntax"> #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">INSTRUMENTED_PREFORM</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">pr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">production_tries</span><span class="plain-syntax">++;</span>
@ -712,7 +712,7 @@ last word in the input text.
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="4-to.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-wm.html">1</a></li><li class="progresschapter"><a href="2-vcb.html">2</a></li><li class="progresschapter"><a href="3-lxr.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresssection"><a href="4-ap.html">ap</a></li><li class="progresssection"><a href="4-lp.html">lp</a></li><li class="progresssection"><a href="4-to.html">to</a></li><li class="progresscurrent">prf</li><li class="progresssection"><a href="4-bn.html">bn</a></li><li class="progressnext"><a href="4-bn.html">&#10095;</a></li></ul></div>
<ul class="progressbar"><li class="progressprev"><a href="4-to.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-wm.html">1</a></li><li class="progresschapter"><a href="2-vcb.html">2</a></li><li class="progresschapter"><a href="3-lxr.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresssection"><a href="4-ap.html">ap</a></li><li class="progresssection"><a href="4-nnt.html">nnt</a></li><li class="progresssection"><a href="4-lp.html">lp</a></li><li class="progresssection"><a href="4-to.html">to</a></li><li class="progresscurrent">prf</li><li class="progresssection"><a href="4-bn.html">bn</a></li><li class="progressnext"><a href="4-bn.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>

View file

@ -91,7 +91,7 @@ changed that.
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">first_round_of_nt_optimisation_made</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Optimiser::optimise_counts</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Optimiser::optimise_counts</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP22">&#167;22</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Optimiser::optimise_counts</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Optimiser::optimise_counts</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP7">&#167;7</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">void</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax"> *</span><span class="identifier-syntax">nt</span><span class="plain-syntax">;</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">, </span><span class="reserved-syntax">nonterminal</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><a href="4-to.html#SP16" class="function-link"><span class="function-syntax">Optimiser::clear_rreq</span></a><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">nonterminal_req</span><span class="plain-syntax">));</span>
@ -706,7 +706,7 @@ must be found in X/Y, so:
<span class="plain-syntax"> </span><span class="identifier-syntax">req</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">FS_req</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">; </span><span class="identifier-syntax">req</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">FW_req</span><span class="plain-syntax"> = </span><span class="constant-syntax">0</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Optimiser::log_range_requirement</span><button class="popup" onclick="togglePopup('usagePopup23')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup23">Usage of <span class="code-font"><span class="function-syntax">Optimiser::log_range_requirement</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP13">&#167;13</a><br/>Preform - <a href="4-prf.html#SP1_2">&#167;1.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">range_requirement</span><span class="plain-syntax"> *</span><span class="identifier-syntax">req</span><span class="plain-syntax">) {</span>
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Optimiser::log_range_requirement</span><button class="popup" onclick="togglePopup('usagePopup23')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup23">Usage of <span class="code-font"><span class="function-syntax">Optimiser::log_range_requirement</span></span>:<br/>Loading Preform - <a href="4-lp.html#SP17">&#167;17</a><br/>Preform - <a href="4-prf.html#SP1_2">&#167;1.2</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">range_requirement</span><span class="plain-syntax"> *</span><span class="identifier-syntax">req</span><span class="plain-syntax">) {</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">req</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">DW_req</span><span class="plain-syntax">) { </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">" DW: %08x"</span><span class="plain-syntax">, </span><span class="identifier-syntax">req</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">DW_req</span><span class="plain-syntax">); }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">req</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">DS_req</span><span class="plain-syntax">) { </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">" DS: %08x"</span><span class="plain-syntax">, </span><span class="identifier-syntax">req</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">DS_req</span><span class="plain-syntax">); }</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">req</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">CW_req</span><span class="plain-syntax">) { </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">" CW: %08x"</span><span class="plain-syntax">, </span><span class="identifier-syntax">req</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">CW_req</span><span class="plain-syntax">); }</span>
@ -759,7 +759,7 @@ infinity.
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprev"><a href="4-lp.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-wm.html">1</a></li><li class="progresschapter"><a href="2-vcb.html">2</a></li><li class="progresschapter"><a href="3-lxr.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresssection"><a href="4-ap.html">ap</a></li><li class="progresssection"><a href="4-lp.html">lp</a></li><li class="progresscurrent">to</li><li class="progresssection"><a href="4-prf.html">prf</a></li><li class="progresssection"><a href="4-bn.html">bn</a></li><li class="progressnext"><a href="4-prf.html">&#10095;</a></li></ul></div>
<ul class="progressbar"><li class="progressprev"><a href="4-lp.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-wm.html">1</a></li><li class="progresschapter"><a href="2-vcb.html">2</a></li><li class="progresschapter"><a href="3-lxr.html">3</a></li><li class="progresscurrentchapter">4</li><li class="progresssection"><a href="4-ap.html">ap</a></li><li class="progresssection"><a href="4-nnt.html">nnt</a></li><li class="progresssection"><a href="4-lp.html">lp</a></li><li class="progresscurrent">to</li><li class="progresssection"><a href="4-prf.html">prf</a></li><li class="progresssection"><a href="4-bn.html">bn</a></li><li class="progressnext"><a href="4-prf.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>

View file

@ -132,8 +132,8 @@ think it means. In our example,
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="function-syntax">Lexer::word</span><span class="plain-syntax">(27) == </span><span class="identifier-syntax">COMMA_V</span><span class="plain-syntax"> </span><span class="comment-syntax"> the comma between "went" and "the"</span>
</pre>
<p class="commentary">See <a href="2-vcb.html#SP2" class="internal">Vocabulary::create_punctuation</a>, and also <a href="4-lp.html#SP20" class="internal">LoadPreform::begin</a>, where
further punctuation marks are created in order to parse Preform syntax &mdash;
<p class="commentary">See <a href="2-vcb.html#SP2" class="internal">Vocabulary::create_punctuation</a>, and also <a href="4-lp.html#SP6" class="internal">LoadPreform::create_punctuation</a>,
where further punctuation marks are created in order to parse Preform syntax &mdash;
there are exotica such as <span class="extract"><span class="extract-syntax">COLONCOLONEQUALS_V</span></span> there, for "::=".
</p>

View file

@ -147,6 +147,11 @@
<spon class="sectiontitle">About Preform</span></a> -
<span class="sectionpurpose">A brief guide to Preform and how to use it.</span></p>
</li>
<li>
<p class="sectionentry"><a href="4-nnt.html">
<spon class="sectiontitle">Nonterminals</span></a> -
<span class="sectionpurpose">The angle-bracketed terms appearing in Preform grammar.</span></p>
</li>
<li>
<p class="sectionentry"><a href="4-lp.html">
<spon class="sectiontitle">Loading Preform</span></a> -

View file

@ -107,8 +107,7 @@ function togglePopup(material_id) {
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-pth.html#SP4" class="function-link"><span class="function-syntax">Pathnames::down</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"words-test"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="identifier-syntax">P</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-pth.html#SP4" class="function-link"><span class="function-syntax">Pathnames::down</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"Tangled"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">S</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-fln.html#SP2" class="function-link"><span class="function-syntax">Filenames::in</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">P</span><span class="plain-syntax">, </span><span class="identifier-syntax">I</span><span class="string-syntax">"Syntax.preform"</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><a href="../words-module/4-lp.html#SP2" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP22" class="function-link"><span class="function-syntax">LoadPreform::parse</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">, </span><span class="constant-syntax">FALSE</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><a href="../words-module/4-lp.html#SP1" class="function-link"><span class="function-syntax">LoadPreform::load</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">S</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">filename</span><span class="plain-syntax"> *</span><span class="identifier-syntax">F</span><span class="plain-syntax"> = </span><a href="../../../inweb/docs/foundation-module/3-fln.html#SP3" class="function-link"><span class="function-syntax">Filenames::from_text</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">arg</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="reserved-syntax">source_file</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sf</span><span class="plain-syntax"> = </span><a href="../words-module/3-tff.html#SP3" class="function-link"><span class="function-syntax">TextFromFiles::feed_into_lexer</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">F</span><span class="plain-syntax">, </span><span class="constant-syntax">NULL_GENERAL_POINTER</span><span class="plain-syntax">);</span>

View file

@ -170,8 +170,7 @@ for use.
void Main::load_preform(inform_language *L) {
pathname *P = Pathnames::down(path_to_inbuild, I"Tangled");
filename *S = Filenames::in(P, I"Syntax.preform");
wording W = LoadPreform::load(S);
LoadPreform::parse(W, FALSE);
LoadPreform::load(S, NULL);
}
@h Target list.

View file

@ -146,7 +146,7 @@ void Languages::read_Preform_definition(inform_language *L, linked_list *S) {
@ This function is called only from Preform...
@d PREFORM_LANGUAGE_FROM_NAME Languages::Preform_find
@d PREFORM_LANGUAGE_FROM_NAME_WORDS_CALLBACK Languages::Preform_find
=
inform_language *Languages::Preform_find(text_stream *name) {

View file

@ -697,7 +697,6 @@ for the extensions they refer to, in a post-processing phase.
=
void Projects::read_source_text_for(inform_project *proj) {
Languages::read_Preform_definition(proj->language_of_syntax, proj->search_list);
LoadPreform::set_language_of_syntax(proj->language_of_syntax);
Sentences::set_start_of_source(sfsm, -1);
parse_node *inclusions_heading, *implicit_heading;

View file

@ -87,10 +87,11 @@ int NaturalLanguages::adaptive_person(inform_language *L) {
At present we do this only for English, but some day...
=
wording NaturalLanguages::load_preform(inform_language *L) {
int NaturalLanguages::load_preform(inform_language *L) {
if (L == NULL) internal_error("can't load preform from null language");
filename *preform_file = Filenames::in(Languages::path_to_bundle(L), I"Syntax.preform");
return LoadPreform::load_for_language(preform_file, L);
filename *preform_file =
Filenames::in(Languages::path_to_bundle(L), I"Syntax.preform");
return LoadPreform::load(preform_file, L);
}
@ Preform errors are handled here:

View file

@ -208,10 +208,8 @@ whole thing into a |specification| for the rest of Inform to use.
=
void Semantics::read_preform(inform_language *L) {
@<Mark certain nonterminals to have their vocabularies numbered and flagged@>;
wording W = NaturalLanguages::load_preform(L);
int nonterminals_declared = LoadPreform::parse(W, FALSE);
LOG("%d declarations read (%d words)\n", nonterminals_declared, Wordings::length(W));
int nonterminals_declared = NaturalLanguages::load_preform(L);
LOG("%d declarations read\n", nonterminals_declared);
}
@<Mark certain nonterminals to have their vocabularies numbered and flagged@> =

View file

@ -58,8 +58,7 @@ void Main::load(text_stream *leaf) {
P = Pathnames::down(P, I"inflections-test");
P = Pathnames::down(P, I"Tangled");
filename *S = Filenames::in(P, leaf);
wording W = LoadPreform::load(S);
LoadPreform::parse(W, FALSE);
LoadPreform::load(S, NULL);
}
void Main::load_other(text_stream *leaf) {
@ -67,8 +66,7 @@ void Main::load_other(text_stream *leaf) {
P = Pathnames::down(P, I"inflections-test");
P = Pathnames::down(P, I"Preform");
filename *S = Filenames::in(P, leaf);
wording W = LoadPreform::load(S);
LoadPreform::parse(W, FALSE);
LoadPreform::load(S, NULL);
}
void Main::ignore(int id, text_stream *arg, void *state) {

View file

@ -45,8 +45,7 @@ void Main::load(text_stream *leaf) {
P = Pathnames::down(P, I"linguistics-test");
P = Pathnames::down(P, I"Tangled");
filename *S = Filenames::in(P, leaf);
wording W = LoadPreform::load(S);
LoadPreform::parse(W, FALSE);
LoadPreform::load(S, NULL);
}
void Main::ignore(int id, text_stream *arg, void *state) {

View file

@ -40,8 +40,7 @@ void Main::load(text_stream *leaf) {
P = Pathnames::down(P, I"problems-test");
P = Pathnames::down(P, I"Tangled");
filename *S = Filenames::in(P, leaf);
wording W = LoadPreform::load(S);
LoadPreform::parse(W, FALSE);
LoadPreform::load(S, NULL);
}
void Main::ignore(int id, text_stream *arg, void *state) {

View file

@ -677,7 +677,11 @@ it would be too late.
@<Detect a Preform grammar inclusion and sneakily act upon it@> =
current_sentence = new;
LoadPreform::parse(GET_RW(<language-modifying-sentence>, 1), TRUE);
wording W = GET_RW(<language-modifying-sentence>, 1);
TEMPORARY_TEXT(wd);
WRITE_TO(wd, "%+W", Wordings::one_word(Wordings::first_wn(W)));
LoadPreform::parse_text(wd);
DISCARD_TEXT(wd);
Annotations::write_int(new, sentence_unparsed_ANNOT, FALSE);
@ Some tools using this module will want to push simple error messages out to

View file

@ -38,8 +38,7 @@ void Main::load(text_stream *leaf) {
P = Pathnames::down(P, I"syntax-test");
P = Pathnames::down(P, I"Tangled");
filename *S = Filenames::in(P, leaf);
wording W = LoadPreform::load(S);
LoadPreform::parse(W, FALSE);
LoadPreform::load(S, NULL);
}
void Main::ignore(int id, text_stream *arg, void *state) {

View file

@ -51,7 +51,8 @@ void WordsModule::start(void) {
Lexer::start();
Vocabulary::create_punctuation();
LoadPreform::begin();
LoadPreform::create_punctuation();
Nonterminals::register();
}
void WordsModule::end(void) {

View file

@ -106,3 +106,47 @@ with result 2.
<race-jersey> ::=
yellow | polkadot | green | white
=
@ So far, the only ingredients of Preform syntax have been nonterminals and
fixed words, but Preform also has "wildcards". For example, in
= (text as Preform)
<competitor> ::=
man with ... on his ...
=
would match, for example, "man with number 17 on his back", or "man with a
chip on his shoulder". |...| matches any non-empty wording, and the text
actually matched is recorded for any successful match. Wordings like this
are numbered upwards from 1 to a maximum of 4, and are usually retrieved by
whatever part of Inform requested the parse, using the |GET_RW| macro. For
example:
= (text)
TEXT GET_RW(<competitor>, 1) GET_RW(<competitor>, 2)
man with number 17 on his back number 17 back
man with a chip on his shoulder a chip shoulder
=
A few internal nonterminals also generate word ranges, using |PUT_RW| to do so,
and word ranges can also be inherited up from one nonterminal to another with
|INHERIT_RANGES|: see //Loading Preform// for definitions of these macros.
There are in fact several different wildcards:
(a) |...| matches any non-empty text, as shown above.
(b) |***| matches any text, including possibly the empty text.
(c) |......| matches any non-empty text in which brackets are used in a
balanced way -- thus they would match "alpha beta gamma" or "alpha (the
Greek letter)", but not "alpha (the" or "Greek letter)".
(d) |###| matches any single word, counting words as the lexer does.
It is also possible to use braces to widen ranges. For example,
= (text as Preform)
<competitor> ::=
man with {... on his ...}
=
groups together anything matching |... on his ...| into a single range. There
need not even be a wildcard inside the braces:
= (text as Preform)
<competitor> ::=
{man} with {... on his ...}
=
works fine, and makes two ranges, the first of which is always just "man".

View file

@ -2,6 +2,22 @@
A handful of bare minimum Preform syntax.
@h Nonterminal names.
This is a typical internal nonterminal being defined, though it's a bit more
meta than most -- it's a nonterminal which matches against the name of any
nonterminal. (This is used only to parse inclusion requests for the debugging
log.)
Note that we use the |internal 1| to signal that a correct match must have
exactly one word.
=
<preform-nonterminal> internal 1 {
nonterminal *nt = Nonterminals::detect(Lexer::word(Wordings::first_wn(W)));
if (nt) { *XP = nt; return TRUE; }
return FALSE;
}
@h Text positions.
A useful nonterminal which matches no text, but detects the position:
@ -22,8 +38,8 @@ A useful nonterminal which matches no text, but detects the position:
}
@h Balancing.
The following matches any text in which braces and brackets are correctly
paired.
The following regular (not internal!) nonterminal matches any text in which
braces and brackets are correctly paired.
=
<balanced-text> ::=
@ -60,21 +76,24 @@ for interpolations called "text substitutions".
=
<quoted-text> internal 1 {
if ((Wordings::nonempty(W)) && (Vocabulary::test_flags(Wordings::first_wn(W), TEXT_MC+TEXTWITHSUBS_MC))) {
if ((Wordings::nonempty(W)) &&
(Vocabulary::test_flags(Wordings::first_wn(W), TEXT_MC+TEXTWITHSUBS_MC))) {
*X = Wordings::first_wn(W); return TRUE;
}
return FALSE;
}
<quoted-text-with-subs> internal 1 {
if ((Wordings::nonempty(W)) && (Vocabulary::test_flags(Wordings::first_wn(W), TEXTWITHSUBS_MC))) {
if ((Wordings::nonempty(W)) &&
(Vocabulary::test_flags(Wordings::first_wn(W), TEXTWITHSUBS_MC))) {
*X = Wordings::first_wn(W); return TRUE;
}
return FALSE;
}
<quoted-text-without-subs> internal 1 {
if ((Wordings::nonempty(W)) && (Vocabulary::test_flags(Wordings::first_wn(W), TEXT_MC))) {
if ((Wordings::nonempty(W)) &&
(Vocabulary::test_flags(Wordings::first_wn(W), TEXT_MC))) {
*X = Wordings::first_wn(W); return TRUE;
}
return FALSE;
@ -85,7 +104,8 @@ of text |""| is to provide a nonterminal matching it:
=
<empty-text> internal 1 {
if ((Wordings::nonempty(W)) && (Word::compare_by_strcmp(Wordings::first_wn(W), L"\"\""))) {
if ((Wordings::nonempty(W)) &&
(Word::compare_by_strcmp(Wordings::first_wn(W), L"\"\""))) {
*X = Wordings::first_wn(W); return TRUE;
}
return FALSE;

View file

@ -3,28 +3,28 @@
To read in structural definitions of natural language written in the
meta-language Preform.
@h Introduction.
@h Reading Preform syntax from a file or text.
The parser reads source text against a specific language only, if
|language_of_source_text| is set; or, if it isn't, from any language.
|primary_Preform_language| is set; or, if it isn't, from any language.
@default NATURAL_LANGUAGE_WORDS_TYPE void
=
NATURAL_LANGUAGE_WORDS_TYPE *language_of_source_text = NULL;
NATURAL_LANGUAGE_WORDS_TYPE *primary_Preform_language = NULL;
void LoadPreform::set_language_of_syntax(NATURAL_LANGUAGE_WORDS_TYPE *L) {
language_of_source_text = L;
int LoadPreform::load(filename *F, NATURAL_LANGUAGE_WORDS_TYPE *L) {
primary_Preform_language = L;
return LoadPreform::parse(LoadPreform::feed_from_Preform_file(F), L);
}
@h Reading Preform syntax from a file.
@ We simply feed the lines one at a time. Preform is parsed with the same
lexer as is used for Inform itself, but using the following set of characters
as word-breaking punctuation marks:
@d PREFORM_PUNCTUATION_MARKS L"{}[]_^?&\\"
=
wording LoadPreform::load_for_language(filename *F, NATURAL_LANGUAGE_WORDS_TYPE *L) {
LoadPreform::set_language_to_parse(L);
return LoadPreform::load(F);
}
wording LoadPreform::load(filename *F) {
wording LoadPreform::feed_from_Preform_file(filename *F) {
feed_t id = Feeds::begin();
if (TextFiles::read(F, FALSE,
NULL, FALSE, LoadPreform::load_helper, NULL, NULL) == FALSE)
@ -32,101 +32,186 @@ wording LoadPreform::load(filename *F) {
return Feeds::end(id);
}
@ We simply feed the lines one at a time. Preform is parsed with the regular
lexer, using the following set of characters as word-breaking punctuation marks:
@d PREFORM_PUNCTUATION_MARKS L"{}[]_^?&\\"
=
void LoadPreform::load_helper(text_stream *item_name,
text_file_position *tfp, void *vnl) {
void LoadPreform::load_helper(text_stream *item_name, text_file_position *tfp,
void *unused_state) {
WRITE_TO(item_name, "\n");
Feeds::feed_text_punctuated(item_name, PREFORM_PUNCTUATION_MARKS);
}
@h Implementation.
We must first clarify how word ranges, once matched in the parser, will be
stored. Within each production, word ranges are numbered upwards from 1. Thus:
= (text as InC)
man with ... on his ...
@ It is also possible to load additional Preform declarations from source
text in Inform, and when that happens, the following is called:
=
would, if it matched successfully, generate two word ranges, numbered 1 and 2.
These are stored in memory belonging to the nonterminal; they are usually, but
not always, then retrieved by whatever part of Inform requested the parse,
using the |GET_RW| macro rather than a function call for speed. It's rare,
but a few internal nonterminals also generate word ranges: they use the
corresponding |PUT_RW| macro to do so. Lastly, we can pass word ranges up
from one nonterminal to another, with |INHERIT_RANGES|.
This form of storage incurs very little time or space overhead, and is possible
only because the parser never backtracks. But it also follows that word ranges
are overwritten if a nonterminal calls itself directly or indirectly: that is,
the inner one's results are wiped out by the outer one. But this is no problem,
since we never extract word-ranges from grammar which is recursive.
Word range 0 is reserved in case we ever need it for the entire text matched
by the nonterminal, but at present we don't need that.
@d MAX_RANGES_PER_PRODUCTION 5 /* in fact, one less than this, since range 0 is reserved */
@d GET_RW(nt, N) (nt->range_result[N])
@d PUT_RW(nt, N, W) { nt->range_result[N] = W; }
@d INHERIT_RANGES(from, to) {
for (int i=1; i<MAX_RANGES_PER_PRODUCTION; i++) /* not copying range 0 */
to->range_result[i] = from->range_result[i];
}
@d CLEAR_RW(from) {
for (int i=0; i<MAX_RANGES_PER_PRODUCTION; i++) /* including range 0 */
from->range_result[i] = EMPTY_WORDING;
int LoadPreform::parse_text(text_stream *wd) {
wording W = Feeds::feed_text_punctuated(wd, PREFORM_PUNCTUATION_MARKS);
return LoadPreform::parse(W, primary_Preform_language);
}
@ So here's the nonterminal structure. There are a few further complications
for speed reasons:
@ Either way, then, all that remains is to write //LoadPreform::parse//. But
before we can get to that, we have to create the...
(a) The minimum and maximum number of words which could ever be a match are
precalculated. For example, if Preform can tell that N will only a run of
between 3 and 7 words inclusive, then it can quickly reject any run of words
outside that range. |INFINITE_WORD_COUNT| is taken as the maximum if N
could in principle match text of any length. (However: note that a maximum of
0 means that the maximum and minimum word counts are disregarded.)
@h Reserved words in Preform.
The ideal tool with which to parse Preform definitions would be Preform, but
then how would we define the grammar required? So we will have to do this
by hand, and in particular, we have to define Preform's syntactic punctuation
marks explicitly. These are, in effect, the reserved words of the Preform
notational language. (Note the absence of the |==>| marker: that's stripped
out by //inweb// and never reaches the |Syntax.preform| file.)
(b) A few internal nonterminals are "voracious". These are given the entire
word range for their productions to eat, and encouraged to eat as much as
they like, returning a word number to show how far they got. While this
effect could be duplicated with suitable grammar and non-voracious nonterminals,
it would be quite a bit slower, since it would have to test every possible
word range.
The bare letters K and L are snuck in here for convenience. They aren't
actually used by anything in //words//, but are used for kind variables in
//kinds//.
=
vocabulary_entry *AMPERSAND_V;
vocabulary_entry *BACKSLASH_V;
vocabulary_entry *CARET_V;
vocabulary_entry *COLONCOLONEQUALS_V;
vocabulary_entry *QUESTIONMARK_V;
vocabulary_entry *QUOTEQUOTE_V;
vocabulary_entry *SIXDOTS_V;
vocabulary_entry *THREEASTERISKS_V;
vocabulary_entry *THREEDOTS_V;
vocabulary_entry *THREEHASHES_V;
vocabulary_entry *UNDERSCORE_V;
vocabulary_entry *language_V;
vocabulary_entry *internal_V;
vocabulary_entry *CAPITAL_K_V;
vocabulary_entry *CAPITAL_L_V;
@ =
void LoadPreform::create_punctuation(void) {
AMPERSAND_V = Vocabulary::entry_for_text(L"&");
BACKSLASH_V = Vocabulary::entry_for_text(L"\\");
CARET_V = Vocabulary::entry_for_text(L"^");
COLONCOLONEQUALS_V = Vocabulary::entry_for_text(L":" ":=");
QUESTIONMARK_V = Vocabulary::entry_for_text(L"?");
QUOTEQUOTE_V = Vocabulary::entry_for_text(L"\"\"");
SIXDOTS_V = Vocabulary::entry_for_text(L"......");
THREEASTERISKS_V = Vocabulary::entry_for_text(L"***");
THREEDOTS_V = Vocabulary::entry_for_text(L"...");
THREEHASHES_V = Vocabulary::entry_for_text(L"###");
UNDERSCORE_V = Vocabulary::entry_for_text(L"_");
language_V = Vocabulary::entry_for_text(L"language");
internal_V = Vocabulary::entry_for_text(L"internal");
CAPITAL_K_V = Vocabulary::entry_for_text(L"k");
CAPITAL_L_V = Vocabulary::entry_for_text(L"l");
}
@h Parsing Preform.
The syntax of the |Syntax.preform| is, fortunately, very simple. At any given
time, we are parsing definitions for a given natural language |L|: for example,
English.
Note that Preform can contain comments in square brackets; but that the Lexer
has already removed any such.
=
int LoadPreform::parse(wording W, NATURAL_LANGUAGE_WORDS_TYPE *L) {
NATURAL_LANGUAGE_WORDS_TYPE *current_natural_language = L;
int nonterminals_declared = 0;
LOOP_THROUGH_WORDING(wn, W) {
if (Lexer::word(wn) == PARBREAK_V) continue;
if ((Wordings::last_wn(W) >= wn+1) && (Lexer::word(wn) == language_V))
@<Parse a definition language switch@>
else if ((Wordings::last_wn(W) >= wn+1) && (Lexer::word(wn+1) == internal_V))
@<Parse an internal nonterminal declaration@>
else if ((Wordings::last_wn(W) >= wn+2) && (Lexer::word(wn+1) == COLONCOLONEQUALS_V))
@<Parse a regular nonterminal declaration@>
else
internal_error("syntax error in Preform declarations");
}
Optimiser::optimise_counts();
return nonterminals_declared;
}
@ We either switch to an existing natural language, or create a new one.
@<Parse a definition language switch@> =
TEMPORARY_TEXT(lname);
WRITE_TO(lname, "%W", Wordings::one_word(wn+1));
NATURAL_LANGUAGE_WORDS_TYPE *nl = NULL;
#ifdef PREFORM_LANGUAGE_FROM_NAME_WORDS_CALLBACK
nl = PREFORM_LANGUAGE_FROM_NAME_WORDS_CALLBACK(lname);
#endif
if (nl == NULL) {
LOG("Missing: %S\n", lname);
internal_error("tried to define for missing language");
}
DISCARD_TEXT(lname);
current_natural_language = nl;
wn++;
@ Internal declarations appear as single lines in |Syntax.preform|.
@<Parse an internal nonterminal declaration@> =
nonterminal *nt = Nonterminals::find(Lexer::word(wn));
if (nt->first_production_list) internal_error("internal is defined");
nt->marked_internal = TRUE;
wn++;
nonterminals_declared++;
@ Regular declarations are much longer and continue until the end of the text,
or until we reach a paragraph break. The body of such a declaration is a list
of productions divided by stroke symbols.
@<Parse a regular nonterminal declaration@> =
nonterminal *nt = Nonterminals::find(Lexer::word(wn));
production_list *pl;
@<Find or create the production list for this language@>;
wn += 2;
int pc = 0;
while (TRUE) {
int x = wn;
while ((x <= Wordings::last_wn(W)) && (Lexer::word(x) != STROKE_V) &&
(Lexer::word(x) != PARBREAK_V)) x++;
if (wn < x) {
production *pr = LoadPreform::new_production(Wordings::new(wn, x-1), nt, pc++);
wn = x;
@<Place the new production within the production list@>;
}
if ((wn > Wordings::last_wn(W)) || (Lexer::word(x) == PARBREAK_V)) break; /* reached end */
wn++; /* advance past the stroke and continue */
}
wn--;
nonterminals_declared++;
@<Find or create the production list for this language@> =
for (pl = nt->first_production_list; pl; pl = pl->next_production_list)
if (pl->definition_language == current_natural_language)
break;
if (pl == NULL) {
pl = CREATE(production_list);
pl->definition_language = current_natural_language;
pl->first_production = NULL;
pl->as_avinue = NULL;
@<Place the new production list within the nonterminal@>;
}
@<Place the new production list within the nonterminal@> =
if (nt->first_production_list == NULL) nt->first_production_list = pl;
else {
production_list *p = nt->first_production_list;
while ((p) && (p->next_production_list)) p = p->next_production_list;
p->next_production_list = pl;
}
@<Place the new production within the production list@> =
if (pl->first_production == NULL) pl->first_production = pr;
else {
production *p = pl->first_production;
while ((p) && (p->next_production)) p = p->next_production;
p->next_production = pr;
}
@
@d MAX_RESULTS_PER_PRODUCTION 10
@d INFINITE_WORD_COUNT 1000000000
=
typedef struct nonterminal {
struct vocabulary_entry *nonterminal_id; /* e.g. |"<cardinal-number>"| */
int voracious; /* if true, scans whole rest of word range */
int multiplicitous;
int marked_internal; /* has, or will be given, an internal definition... */
int (*internal_definition)(wording W, int *result, void **result_p); /* ...this one */
struct production_list *first_production_list; /* if not internal, this defines it */
int (*result_compositor)(int *r, void **rp, int *inters, void **inter_ps, wording *interW, wording W);
struct wording range_result[MAX_RANGES_PER_PRODUCTION]; /* storage for word ranges matched */
int optimised_in_this_pass; /* have the following been worked out yet? */
int min_nt_words, max_nt_words; /* for speed */
struct range_requirement nonterminal_req;
int nt_req_bit; /* which hashing category the words belong to, or $-1$ if none */
int number_words_by_production;
unsigned int flag_words_in_production;
int watched; /* watch goings-on to the debugging log */
int nonterminal_tries; /* used only in instrumented mode */
int nonterminal_matches; /* ditto */
CLASS_DEFINITION
} nonterminal;
@ Each (external) nonterminal is then defined by lists of productions:
potentially one for each language, though only English is required to define
@ -262,20 +347,6 @@ typedef struct ptoken {
CLASS_DEFINITION
} ptoken;
@ The parser records the result of the most recently matched nonterminal in the
following global variables:
=
int most_recent_result = 0; /* this is the variable which |inweb| writes |<<r>>| */
void *most_recent_result_p = NULL; /* this is the variable which |inweb| writes |<<rp>>| */
@ Preform's aim is to purge the Inform source code of all English vocabulary,
but we do still the letters "K" and "L", to define the wording of kind constructors.
=
vocabulary_entry *CAPITAL_K_V;
vocabulary_entry *CAPITAL_L_V;
@ Preform can run in an instrumented mode, which collects statistics on the
usage of syntax it sees, but there's a performance hit for this. So it's
enabled only if the constant |INSTRUMENTED_PREFORM| defined to |TRUE|: here's
@ -295,332 +366,7 @@ typedef struct range_requirement {
int no_req_bits = 0;
@h Logging.
Descending these wheels within wheels:
=
void LoadPreform::log(void) {
int detailed = FALSE;
nonterminal *nt;
LOOP_OVER(nt, nonterminal) {
#ifdef INSTRUMENTED_PREFORM
LOG("%d/%d: ", nt->nonterminal_matches, nt->nonterminal_tries);
#endif
LOG("%V: ", nt->nonterminal_id);
Optimiser::log_range_requirement(&(nt->nonterminal_req));
LOG("\n");
if (nt->internal_definition) LOG(" (internal)\n");
else {
production_list *pl;
for (pl = nt->first_production_list; pl; pl = pl->next_production_list) {
LOG(" $J:\n", pl->definition_language);
production *pr;
for (pr = pl->first_production; pr; pr = pr->next_production) {
LOG(" "); LoadPreform::log_production(pr, detailed);
#ifdef INSTRUMENTED_PREFORM
LOG(" %d/%d: ", pr->production_matches, pr->production_tries);
if (Wordings::nonempty(pr->sample_text)) LOG("<%W>", pr->sample_text);
#endif
LOG(" ==> ");
Optimiser::log_range_requirement(&(pr->production_req));
LOG("\n");
}
}
}
LOG(" min %d, max %d\n\n", nt->min_nt_words, nt->max_nt_words);
}
LOG("%d req bits.\n", no_req_bits);
}
@ =
void LoadPreform::log_production(production *pr, int detailed) {
if (pr->first_ptoken == NULL) LOG("<empty-production>");
ptoken *pt;
for (pt = pr->first_ptoken; pt; pt = pt->next_ptoken) {
LoadPreform::log_ptoken(pt, detailed);
LOG(" ");
}
}
@ =
void LoadPreform::log_ptoken(ptoken *pt, int detailed) {
if ((detailed) && (pt->ptoken_position != 0)) LOG("(@%d)", pt->ptoken_position);
if ((detailed) && (pt->strut_number >= 0)) LOG("(S%d)", pt->strut_number);
if (pt->disallow_unexpected_upper) LOG("_");
if (pt->negated_ptoken) LOG("^");
if (pt->range_starts >= 0) { LOG("{"); if (detailed) LOG("%d:", pt->range_starts); }
ptoken *alt;
for (alt = pt; alt; alt = alt->alternative_ptoken) {
if (alt->nt_pt) {
LOG("%V", alt->nt_pt->nonterminal_id);
if (detailed) LOG("=%d", alt->result_index);
} else {
LOG("%V", alt->ve_pt);
}
if (alt->alternative_ptoken) LOG("/");
}
if (pt->range_ends >= 0) { if (detailed) LOG(":%d", pt->range_ends); LOG("}"); }
}
@ A less detailed form used in linguistic problem messages:
=
void LoadPreform::write_ptoken(OUTPUT_STREAM, ptoken *pt) {
if (pt->disallow_unexpected_upper) WRITE("_");
if (pt->negated_ptoken) WRITE("^");
if (pt->range_starts >= 0) WRITE("{");
ptoken *alt;
for (alt = pt; alt; alt = alt->alternative_ptoken) {
if (alt->nt_pt) {
WRITE("%V", alt->nt_pt->nonterminal_id);
} else {
WRITE("%V", alt->ve_pt);
}
if (alt->alternative_ptoken) WRITE("/");
}
if (pt->range_ends >= 0) WRITE("}");
}
@ This is a typical internal nonterminal being defined. It's used only to parse
inclusion requests for the debugging log. Note that we use the "1" to signal
that a correct match must have exactly one word.
=
<preform-nonterminal> internal 1 {
nonterminal *nt = LoadPreform::detect_nonterminal(Lexer::word(Wordings::first_wn(W)));
if (nt) { *XP = nt; return TRUE; }
return FALSE;
}
@ To use which, the debugging log code needs:
=
void LoadPreform::watch(nonterminal *nt, int state) {
nt->watched = state;
}
@h Building grammar.
So, to begin. Since we can't use Preform to parse Preform, we have to define
its syntactic tokens by hand:
=
vocabulary_entry *AMPERSAND_V;
vocabulary_entry *BACKSLASH_V;
vocabulary_entry *CARET_V;
vocabulary_entry *COLONCOLONEQUALS_V;
vocabulary_entry *QUESTIONMARK_V;
vocabulary_entry *QUOTEQUOTE_V;
vocabulary_entry *SIXDOTS_V;
vocabulary_entry *THREEASTERISKS_V;
vocabulary_entry *THREEDOTS_V;
vocabulary_entry *THREEHASHES_V;
vocabulary_entry *UNDERSCORE_V;
vocabulary_entry *language_V;
vocabulary_entry *internal_V;
@ And off we go.
=
void LoadPreform::begin(void) {
CAPITAL_K_V = Vocabulary::entry_for_text(L"k");
CAPITAL_L_V = Vocabulary::entry_for_text(L"l");
AMPERSAND_V = Vocabulary::entry_for_text(L"&");
BACKSLASH_V = Vocabulary::entry_for_text(L"\\");
CARET_V = Vocabulary::entry_for_text(L"^");
COLONCOLONEQUALS_V = Vocabulary::entry_for_text(L":" ":=");
QUESTIONMARK_V = Vocabulary::entry_for_text(L"?");
QUOTEQUOTE_V = Vocabulary::entry_for_text(L"\"\"");
SIXDOTS_V = Vocabulary::entry_for_text(L"......");
THREEASTERISKS_V = Vocabulary::entry_for_text(L"***");
THREEDOTS_V = Vocabulary::entry_for_text(L"...");
THREEHASHES_V = Vocabulary::entry_for_text(L"###");
UNDERSCORE_V = Vocabulary::entry_for_text(L"_");
language_V = Vocabulary::entry_for_text(L"language");
internal_V = Vocabulary::entry_for_text(L"internal");
@<Register the internal and source-code-referred-to nonterminals@>;
}
@ The tangler of |inweb| replaces the |[[nonterminals]]| below with
invocations of the |REGISTER_NONTERMINAL| and |INTERNAL_NONTERMINAL| macros.
@<Register the internal and source-code-referred-to nonterminals@> =
[[nonterminals]];
nonterminal *nt;
LOOP_OVER(nt, nonterminal)
if ((nt->marked_internal) && (nt->internal_definition == NULL))
internal_error("internal undefined");
@ These macros connect nonterminals with their mentions in the Inform source
code, and with the compositor routines compiled for them by |inweb|. It invokes
|REGISTER_NONTERMINAL| if it has compiled Preform productions for a nonterminal,
and compiled a compositor routine; the name of which is the nonterminal's name
with a |C| suffix. If it found an internal nonterminal, it invokes
|INTERNAL_NONTERMINAL|, and compiles a routine whose name has the suffix |R|
as the definition.
@d REGISTER_NONTERMINAL(quotedname, identifier)
identifier = LoadPreform::find_nonterminal(Vocabulary::entry_for_text(quotedname));
identifier->result_compositor = identifier##C;
@d INTERNAL_NONTERMINAL(quotedname, identifier, min, max)
identifier = LoadPreform::find_nonterminal(Vocabulary::entry_for_text(quotedname));
identifier->min_nt_words = min; identifier->max_nt_words = max;
identifier->internal_definition = identifier##R;
identifier->marked_internal = TRUE;
@ Parsing Preform is exactly what Preform would do elegantly, but of course,
for chicken-and-egg reasons, we need to do the job by hand. Fortunately the
syntax is very simple.
=
NATURAL_LANGUAGE_WORDS_TYPE *language_being_read_by_Preform = NULL;
void LoadPreform::set_language_to_parse(NATURAL_LANGUAGE_WORDS_TYPE *L) {
language_being_read_by_Preform = L;
}
int LoadPreform::parse(wording W, int break_first) {
if (break_first) {
TEMPORARY_TEXT(wd);
WRITE_TO(wd, "%+W", Wordings::one_word(Wordings::first_wn(W)));
W = Feeds::feed_text_punctuated(wd, PREFORM_PUNCTUATION_MARKS);
DISCARD_TEXT(wd);
}
int nonterminals_declared = 0;
LOOP_THROUGH_WORDING(wn, W) {
if (Lexer::word(wn) == PARBREAK_V) continue;
#ifdef PREFORM_LANGUAGE_FROM_NAME
if ((Wordings::last_wn(W) >= wn+1) && (Lexer::word(wn) == language_V)) {
@<Parse a definition language switch@>;
continue;
}
#endif
if ((Wordings::last_wn(W) >= wn+1) && (Lexer::word(wn+1) == internal_V)) {
@<Parse an internal nonterminal declaration@>;
nonterminals_declared++;
continue;
}
if ((Wordings::last_wn(W) >= wn+2) && (Lexer::word(wn+1) == COLONCOLONEQUALS_V)) {
@<Parse an external nonterminal declaration@>;
nonterminals_declared++;
continue;
}
internal_error("language definition failed");
}
Optimiser::optimise_counts();
return nonterminals_declared;
}
@ We either switch to an existing natural language, or create a new one.
@<Parse a definition language switch@> =
TEMPORARY_TEXT(lname);
WRITE_TO(lname, "%W", Wordings::one_word(wn+1));
NATURAL_LANGUAGE_WORDS_TYPE *nl = PREFORM_LANGUAGE_FROM_NAME(lname);
if (nl == NULL) {
LOG("Missing: %S\n", lname);
internal_error("tried to define for missing language");
}
DISCARD_TEXT(lname);
language_being_read_by_Preform = nl;
wn++;
@<Parse an internal nonterminal declaration@> =
nonterminal *nt = LoadPreform::find_nonterminal(Lexer::word(wn));
if (nt->first_production_list) internal_error("internal is defined");
nt->marked_internal = TRUE;
wn++;
@ The declaration continues until the end of the text, or until we reach a
paragraph break. Internally, it's a list of productions divided by stroke symbols.
@<Parse an external nonterminal declaration@> =
nonterminal *nt = LoadPreform::find_nonterminal(Lexer::word(wn));
production_list *pl;
@<Find or create the production list for this language@>;
wn += 2;
int pc = 0;
while (TRUE) {
int x = wn;
while ((x <= Wordings::last_wn(W)) && (Lexer::word(x) != STROKE_V) && (Lexer::word(x) != PARBREAK_V)) x++;
if (wn < x) {
production *pr = LoadPreform::new_production(Wordings::new(wn, x-1), nt, pc++);
wn = x;
@<Place the new production within the production list@>;
}
if ((wn > Wordings::last_wn(W)) || (Lexer::word(x) == PARBREAK_V)) break; /* reached end */
wn++; /* advance past the stroke and continue */
}
wn--;
@<Find or create the production list for this language@> =
for (pl = nt->first_production_list; pl; pl = pl->next_production_list)
if (pl->definition_language == language_being_read_by_Preform)
break;
if (pl == NULL) {
pl = CREATE(production_list);
pl->definition_language = language_being_read_by_Preform;
pl->first_production = NULL;
pl->as_avinue = NULL;
@<Place the new production list within the nonterminal@>;
}
@<Place the new production list within the nonterminal@> =
if (nt->first_production_list == NULL) nt->first_production_list = pl;
else {
production_list *p = nt->first_production_list;
while ((p) && (p->next_production_list)) p = p->next_production_list;
p->next_production_list = pl;
}
@<Place the new production within the production list@> =
if (pl->first_production == NULL) pl->first_production = pr;
else {
production *p = pl->first_production;
while ((p) && (p->next_production)) p = p->next_production;
p->next_production = pr;
}
@ Nonterminals are identified by their name-words:
=
nonterminal *LoadPreform::detect_nonterminal(vocabulary_entry *ve) {
nonterminal *nt;
LOOP_OVER(nt, nonterminal)
if (ve == nt->nonterminal_id)
return nt;
return NULL;
}
nonterminal *LoadPreform::find_nonterminal(vocabulary_entry *ve) {
nonterminal *nt = LoadPreform::detect_nonterminal(ve);
if (nt) return nt;
nt = CREATE(nonterminal);
nt->nonterminal_id = ve;
nt->voracious = FALSE;
nt->multiplicitous = FALSE;
nt->optimised_in_this_pass = FALSE;
nt->min_nt_words = 1; nt->max_nt_words = INFINITE_WORD_COUNT;
nt->nt_req_bit = -1;
nt->first_production_list = NULL;
nt->marked_internal = FALSE;
nt->internal_definition = NULL;
nt->result_compositor = NULL;
nt->number_words_by_production = FALSE;
nt->flag_words_in_production = 0;
for (int i=0; i<MAX_RANGES_PER_PRODUCTION; i++)
nt->range_result[i] = EMPTY_WORDING;
nt->watched = FALSE;
nt->nonterminal_tries = 0; nt->nonterminal_matches = 0;
return nt;
}
@ We now descend to the creation of productions for (external) nonterminals.
@ -806,7 +552,7 @@ ptoken *LoadPreform::new_ptoken(vocabulary_entry *ve, int unescaped, nonterminal
wchar_t *p = Vocabulary::get_exemplar(ve, FALSE);
if ((unescaped) && (p) && (p[0] == '<') && (p[Wide::len(p)-1] == '>')) {
pt->nt_pt = LoadPreform::find_nonterminal(ve);
pt->nt_pt = Nonterminals::find(ve);
pt->ptoken_category = NONTERMINAL_PTC;
} else {
pt->ve_pt = ve;
@ -829,3 +575,96 @@ ptoken *LoadPreform::new_ptoken(vocabulary_entry *ve, int unescaped, nonterminal
return pt;
}
@h Logging.
Descending these wheels within wheels:
=
void LoadPreform::log(void) {
int detailed = FALSE;
nonterminal *nt;
LOOP_OVER(nt, nonterminal) {
#ifdef INSTRUMENTED_PREFORM
LOG("%d/%d: ", nt->nonterminal_matches, nt->nonterminal_tries);
#endif
LOG("%V: ", nt->nonterminal_id);
Optimiser::log_range_requirement(&(nt->nonterminal_req));
LOG("\n");
if (nt->internal_definition) LOG(" (internal)\n");
else {
production_list *pl;
for (pl = nt->first_production_list; pl; pl = pl->next_production_list) {
LOG(" $J:\n", pl->definition_language);
production *pr;
for (pr = pl->first_production; pr; pr = pr->next_production) {
LOG(" "); LoadPreform::log_production(pr, detailed);
#ifdef INSTRUMENTED_PREFORM
LOG(" %d/%d: ", pr->production_matches, pr->production_tries);
if (Wordings::nonempty(pr->sample_text)) LOG("<%W>", pr->sample_text);
#endif
LOG(" ==> ");
Optimiser::log_range_requirement(&(pr->production_req));
LOG("\n");
}
}
}
LOG(" min %d, max %d\n\n", nt->min_nt_words, nt->max_nt_words);
}
LOG("%d req bits.\n", no_req_bits);
}
@ =
void LoadPreform::log_production(production *pr, int detailed) {
if (pr->first_ptoken == NULL) LOG("<empty-production>");
ptoken *pt;
for (pt = pr->first_ptoken; pt; pt = pt->next_ptoken) {
LoadPreform::log_ptoken(pt, detailed);
LOG(" ");
}
}
@ =
void LoadPreform::log_ptoken(ptoken *pt, int detailed) {
if ((detailed) && (pt->ptoken_position != 0)) LOG("(@%d)", pt->ptoken_position);
if ((detailed) && (pt->strut_number >= 0)) LOG("(S%d)", pt->strut_number);
if (pt->disallow_unexpected_upper) LOG("_");
if (pt->negated_ptoken) LOG("^");
if (pt->range_starts >= 0) { LOG("{"); if (detailed) LOG("%d:", pt->range_starts); }
ptoken *alt;
for (alt = pt; alt; alt = alt->alternative_ptoken) {
if (alt->nt_pt) {
LOG("%V", alt->nt_pt->nonterminal_id);
if (detailed) LOG("=%d", alt->result_index);
} else {
LOG("%V", alt->ve_pt);
}
if (alt->alternative_ptoken) LOG("/");
}
if (pt->range_ends >= 0) { if (detailed) LOG(":%d", pt->range_ends); LOG("}"); }
}
@ A less detailed form used in linguistic problem messages:
=
void LoadPreform::write_ptoken(OUTPUT_STREAM, ptoken *pt) {
if (pt->disallow_unexpected_upper) WRITE("_");
if (pt->negated_ptoken) WRITE("^");
if (pt->range_starts >= 0) WRITE("{");
ptoken *alt;
for (alt = pt; alt; alt = alt->alternative_ptoken) {
if (alt->nt_pt) {
WRITE("%V", alt->nt_pt->nonterminal_id);
} else {
WRITE("%V", alt->ve_pt);
}
if (alt->alternative_ptoken) WRITE("/");
}
if (pt->range_ends >= 0) WRITE("}");
}
@ To use which, the debugging log code needs:
=
void LoadPreform::watch(nonterminal *nt, int state) {
nt->watched = state;
}

View file

@ -0,0 +1,248 @@
[Nonterminals::] Nonterminals.
The angle-bracketed terms appearing in Preform grammar.
@h How nonterminals are stored.
Each different nonterminal defined in the |Syntax.preform| code read in,
such as <any-integer>, is going to correspond to a global variable in the
program reading it in, such as |any_integer_NTM|. On the face of it, this is
impossible. How can what happens at run-time affect what variables are named
at compile time?
The answer is that the //inweb// literate programming tool looks through the
complete source code, sees the Preform nonterminals described in it, and
inserts declarations of the corresponding variables into the "tangled" form
of the source code sent to a C compiler to make the actual program. (This is
a feature of //inweb// available only for programs written in InC.)
In particular, the tangler of |inweb| replaces the |[[nonterminals]]| below with
invocations of the |REGISTER_NONTERMINAL| and |INTERNAL_NONTERMINAL| macros.
For example, it inserts the C line:
= (text as C)
INTERNAL_NONTERMINAL(L"<any-integer>", any_integer_NTM, 1, 1);
=
since this is an "internal" nonterminal; and the macro will then expand
to code which sets up |any_integer_NTM| -- see below.
=
void Nonterminals::register(void) {
/* The following is not valid C, but causes Inweb to insert lines which are */
[[nonterminals]];
/* Back to regular C now */
nonterminal *nt;
LOOP_OVER(nt, nonterminal)
if ((nt->marked_internal) && (nt->internal_definition == NULL))
internal_error("internal nonterminal has no definition function");
}
@ So, then, //inweb// tangles out code which uses the |REGISTER_NONTERMINAL|
macro for any standard nonterminal, and also tangles a compositor function for
it; the name of which is the nonterminal's name with a |C| suffix. For example,
suppose //inweb// sees the following in the web it is tangling:
= (text as Preform)
<competitor> ::=
the pacemaker | ==> 1
<ordinal-number> runner | ==> R[1]
runner no <cardinal-number> ==> R[1]
=
It then tangles this macro usage into //Nonterminals::register// above:
= (text as C)
REGISTER_NONTERMINAL(L"<competitor>", competitor_NTM);
=
And it also tangles matching declarations for:
(a) the global variable |competitor_NTM|, of type |nonterminal *|;
(b) the "compositor function" |competitor_NTMC|, which is a function to
deal with what happens when a successful match is made against the grammar --
this incorporates the material which //inweb// finds to the right of the |==>|
markers in the Preform definition.
But if we left things at that, we would find ourselves at run-time with
a null variable, a function not called from anywhere, and an instance
somewhere in memory of a nonterminal read in from Preform syntax and
called |"<competitor>"|, but which has no apparent connection to either
the function or the variable. We clearly need to join these together.
And so the |REGISTER_NONTERMINAL| macro expands to code which initialises the
variable to the nonterminal having its name, and then connects that to the
compositor function:
@d REGISTER_NONTERMINAL(quotedname, identifier)
identifier = Nonterminals::find(Vocabulary::entry_for_text(quotedname));
identifier->result_compositor = identifier##C;
@ For example, this might expand to:
= (text as C)
competitor_NTM = Nonterminals::find(Vocabulary::entry_for_text(L"<competitor>"));
competitor_NTM->result_compositor = competitor_NTMC;
=
Note that it is absolutely necessary that |Nonterminals::find| does
return a nonterminal. But we can be sure that it does, since the function creates
a nonterminal object of that name even if one does not already exist.
@ The position for internal nonterminals (i.e. those defined by a function
written by the programmer, not by Preform grammar lines) is similar:
(a) again there is a global variable, say |any_integer_NTM|, of type |nonterminal *|;
(b) but now there is no compositor, and instead there is a function |any_integer_NTMR|
which actually performs the parse directly.
The |INTERNAL_NONTERMINAL| macro similarly initialises and connects these
declarations. |min| and |max| are conveniences for speedy parsing, and supply
the minimum and maximum number of words that the nonterminal can match; these
are needed because the Preform optimiser can't see inside |any_integer_NTMR| to
calculate those bounds for itself. |max| can be infinity, in which case we
use the constant |INFINITE_WORD_COUNT| for it.
@d INFINITE_WORD_COUNT 1000000000
@d INTERNAL_NONTERMINAL(quotedname, identifier, min, max)
identifier = Nonterminals::find(Vocabulary::entry_for_text(quotedname));
identifier->min_nt_words = min; identifier->max_nt_words = max;
identifier->internal_definition = identifier##R;
identifier->marked_internal = TRUE;
@ So, then, the following rather lengthy class declaration shows what goes
into a nonterminal. Note that nonterminals are uniquely identifiable by their
names: there can be only one called, say, <any-integer>. This is why its
textual name is referred to as an "ID".
=
typedef struct nonterminal {
struct vocabulary_entry *nonterminal_id; /* e.g. |"<any-integer>"| */
/* For internal nonterminals */
int marked_internal; /* has, or will be given, an internal definition... */
int (*internal_definition)(wording W, int *result, void **result_p); /* ...this one */
int voracious; /* if true, scans whole rest of word range */
/* For regular nonterminals */
struct production_list *first_production_list; /* if not internal, this defines it */
int (*result_compositor)(int *r, void **rp, int *inters, void **inter_ps, wording *interW, wording W);
int multiplicitous; /* if true, matches are alternative syntax tree readings */
/* Storage for most recent correct match */
struct wording range_result[MAX_RANGES_PER_PRODUCTION]; /* storage for word ranges matched */
/* Optimiser data */
int optimised_in_this_pass; /* have the following been worked out yet? */
int min_nt_words, max_nt_words; /* for speed */
struct range_requirement nonterminal_req;
int nt_req_bit; /* which hashing category the words belong to, or $-1$ if none */
int number_words_by_production;
unsigned int flag_words_in_production;
/* For debugging only */
int watched; /* watch goings-on to the debugging log */
int nonterminal_tries; /* for statistics collected in instrumented mode */
int nonterminal_matches; /* ditto */
CLASS_DEFINITION
} nonterminal;
@ A few notes on this are in order:
(a) As noted above, every nonterminal is either "internal" or "regular". If
internal, it is defined by a function; if regular, it is defined by lines
of grammar (called "productions") and a compositor function.
(b) A few internal nonterminals are "voracious". These are given the entire
word range for their productions to eat, and encouraged to eat as much as they
like, returning a word number to show how far they got. While this effect
could be duplicated with non-voracious nonterminals, that would be quite a bit
slower, since it would have to test every possible word range.
(c) A few regular nonterminals are "multiplicitous". These composite their
results in a way special to the Inform compiler's syntax tree, by stacking
them up as alternative possible readings of the same text. Ordinarily, the
result of parsing text against a nonterminal is that the first grammar line
matching that text determines the meaning, but for a multiplicitous nonterminal,
every line matching the text determines one of perhaps many possible meanings.
(d) The optimisation data helps the parser to reject non-matching text quickly.
For example, if the optimiser can determine that <competitor> only ever matches
texts of between 3 and 7 words in length, it can quickly reject any run of
words outside that range. (However: note that a maximum of 0 means that the
maximum and minimum word counts are disregarded.) The other fields are harder
to explain -- see //The Optimiser//.
@ So, then, as noted above, nonterminals are identified by their name-words.
The following is not especially fast but doesn't need to be: it's used only
when Preform grammar is parsed, not when Inform text is parsed.
=
nonterminal *Nonterminals::detect(vocabulary_entry *name_word) {
nonterminal *nt;
LOOP_OVER(nt, nonterminal)
if (name_word == nt->nonterminal_id)
return nt;
return NULL;
}
@ And the following always returns one, creating it if necessary:
=
nonterminal *Nonterminals::find(vocabulary_entry *name_word) {
nonterminal *nt = Nonterminals::detect(name_word);
if (nt == NULL) {
nt = CREATE(nonterminal);
nt->nonterminal_id = name_word;
nt->marked_internal = FALSE; /* by default, nonterminals are regular */
nt->internal_definition = NULL;
nt->voracious = FALSE;
for (int i=0; i<MAX_RANGES_PER_PRODUCTION; i++)
nt->range_result[i] = EMPTY_WORDING;
nt->first_production_list = NULL;
nt->result_compositor = NULL;
nt->multiplicitous = FALSE;
nt->optimised_in_this_pass = FALSE;
nt->min_nt_words = 1; nt->max_nt_words = INFINITE_WORD_COUNT;
nt->nt_req_bit = -1;
nt->number_words_by_production = FALSE;
nt->flag_words_in_production = 0;
nt->watched = FALSE;
nt->nonterminal_tries = 0; nt->nonterminal_matches = 0;
}
return nt;
}
@h Word ranges in a nonterminal.
We now need to define the macros |GET_RW| and |PUT_RW|, which get and set
the results of a successful match against a nonterminal (see //About Preform//
for more on this).
We do so by giving each nonterminal a small array of |wording|s, which are
lightweight structures incurring little time or space overhead. The fact that
they are attached to the NT itself, rather than, say, being placed on a
parsing stack of some kind, makes them faster to access, but is possible only
because the parser never backtracks. Similarly, results word ranges are
overwritten if a nonterminal calls itself directly or indirectly: that is, the
inner one's results are wiped out by the outer one. But this is no problem,
since we never extract word-ranges from grammar which is recursive.
Word range 0 is reserved in case we ever need it for the entire text matched
by the nonterminal, though at present we don't need that.
@d MAX_RANGES_PER_PRODUCTION 5 /* in fact, one less than this, since range 0 is reserved */
@d GET_RW(nt, N) (nt->range_result[N])
@d PUT_RW(nt, N, W) { nt->range_result[N] = W; }
@d INHERIT_RANGES(from, to) {
for (int i=1; i<MAX_RANGES_PER_PRODUCTION; i++) /* not copying range 0 */
to->range_result[i] = from->range_result[i];
}
@d CLEAR_RW(from) {
for (int i=0; i<MAX_RANGES_PER_PRODUCTION; i++) /* including range 0 */
from->range_result[i] = EMPTY_WORDING;
}
@h Other results.
The parser records the result of the most recently matched nonterminal in the
following global variables -- which, unlike word ranges, are not attached to
any single NT.
//inweb// translates the notation |<<r>>| and |<<rp>>| to these variable names:
=
int most_recent_result = 0; /* the variable which |inweb| writes |<<r>>| */
void *most_recent_result_p = NULL; /* the variable which |inweb| writes |<<rp>>| */

View file

@ -93,7 +93,7 @@ an internal NT, or try all possible productions for an external one.
production_list *pl;
for (pl = nt->first_production_list; pl; pl = pl->next_production_list) {
NATURAL_LANGUAGE_WORDS_TYPE *nl = pl->definition_language;
if ((language_of_source_text == NULL) || (language_of_source_text == nl)) {
if ((primary_Preform_language == NULL) || (primary_Preform_language == nl)) {
production *pr;
int last_v = FALSE;
for (pr = pl->first_production; pr; pr = pr->next_production) {

View file

@ -28,6 +28,7 @@ Chapter 3: Words in Sequence
Chapter 4: Parsing
About Preform
Nonterminals
Loading Preform
The Optimiser
Preform

View file

@ -59,8 +59,8 @@ think it means. In our example,
= (text as InC)
Lexer::word(27) == COMMA_V /* the comma between "went" and "the" */
=
See //Vocabulary::create_punctuation//, and also //LoadPreform::begin//, where
further punctuation marks are created in order to parse Preform syntax --
See //Vocabulary::create_punctuation//, and also //LoadPreform::create_punctuation//,
where further punctuation marks are created in order to parse Preform syntax --
there are exotica such as |COLONCOLONEQUALS_V| there, for "::=".
@ Lexical errors occur if words are too long, or quoted text continues without

View file

@ -52,8 +52,7 @@ void Unit::test_preform(text_stream *arg) {
P = Pathnames::down(P, I"words-test");
P = Pathnames::down(P, I"Tangled");
filename *S = Filenames::in(P, I"Syntax.preform");
wording W = LoadPreform::load(S);
LoadPreform::parse(W, FALSE);
LoadPreform::load(S, NULL);
filename *F = Filenames::from_text(arg);
source_file *sf = TextFromFiles::feed_into_lexer(F, NULL_GENERAL_POINTER);