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:
parent
3ed31bef56
commit
4c86f53d74
|
@ -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
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
Prerelease: alpha.1
|
||||
Build Date: 12 May 2020
|
||||
Build Number: 6Q46
|
||||
Build Date: 17 May 2020
|
||||
Build Number: 6Q47
|
||||
|
|
|
@ -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">§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">§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>§7. </b>Preform errors are handled here:
|
||||
|
|
|
@ -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">§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>§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>
|
||||
|
|
|
@ -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">§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>§2.6. Target list. </b>This where we keep the list of targets, in which no copy occurs more than
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -224,7 +224,7 @@ include the Materials folder for any relevant project.
|
|||
<p class="commentary firstcommentary"><a id="SP9"></a><b>§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>
|
||||
|
|
|
@ -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">§7</a><br/>Project File Manager - <a href="4-pfm.html#SP7">§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">-></span><span class="element-syntax">language_of_syntax</span><span class="plain-syntax">, </span><span class="identifier-syntax">proj</span><span class="plain-syntax">-></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">-></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>
|
||||
|
|
|
@ -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"><language-modifying-sentence></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"><language-modifying-sentence></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">§6.9</a>.</li></ul>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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">§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">§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">§11</a><br/>Preform - <a href="4-prf.html#SP3">§3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP2">§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">§11</a><br/>Preform - <a href="4-prf.html#SP3">§3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP3">§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"><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>
|
||||
|
|
|
@ -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">§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">§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">-></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">-></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">§24.1.1</a>, <a href="4-lp.html#SP24_1_3">§24.1.3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP5">§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">§14.1.1</a>, <a href="4-lp.html#SP14_1_3">§14.1.3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP6">§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">-></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">-></span><span class="element-syntax">flags</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">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">§16</a><br/>Loading Preform - <a href="4-lp.html#SP24_1_1">§24.1.1</a>, <a href="4-lp.html#SP24_1_3">§24.1.3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP5">§5</a>, <a href="4-bn.html#SP6">§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">§16</a><br/>Loading Preform - <a href="4-lp.html#SP14_1_1">§14.1.1</a>, <a href="4-lp.html#SP14_1_3">§14.1.3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP6">§6</a>, <a href="4-bn.html#SP7">§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">)-></span><span class="element-syntax">flags</span><span class="plain-syntax">) & </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">§2</a>, <a href="2-vcb.html#SP3">§3</a><br/>Loading Preform - <a href="4-lp.html#SP20">§20</a>, <a href="4-lp.html#SP21">§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">§2</a>, <a href="2-vcb.html#SP3">§3</a><br/>Nonterminals - <a href="4-nnt.html#SP2">§2</a>, <a href="4-nnt.html#SP4">§4</a><br/>Loading Preform - <a href="4-lp.html#SP6">§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>
|
||||
|
|
|
@ -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">§3</a>, <a href="4-lp.html#SP22">§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">§2</a>, <a href="4-lp.html#SP3">§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">§3</a><br/>Loading Preform - <a href="4-lp.html#SP25_1">§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">§3</a><br/>Loading Preform - <a href="4-lp.html#SP15_1">§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>
|
||||
|
|
|
@ -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>§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">§6</a>, <a href="2-vcb.html#SP10">§10</a>, <a href="2-vcb.html#SP11">§11</a>, <a href="2-vcb.html#SP16">§16</a><br/>Word Assemblages - <a href="2-wa.html#SP4">§4</a>, <a href="2-wa.html#SP9">§9</a>, <a href="2-wa.html#SP10">§10</a>, <a href="2-wa.html#SP11">§11</a><br/>Numbered Words - <a href="2-nw.html#SP1">§1</a><br/>Wordings - <a href="3-wrd.html#SP8">§8</a>, <a href="3-wrd.html#SP18">§18</a>, <a href="3-wrd.html#SP19">§19</a>, <a href="3-wrd.html#SP20">§20</a><br/>Text From Files - <a href="3-tff.html#SP4">§4</a><br/>Loading Preform - <a href="4-lp.html#SP17">§17</a>, <a href="4-lp.html#SP22">§22</a>, <a href="4-lp.html#SP22_2">§22.2</a>, <a href="4-lp.html#SP22_3">§22.3</a>, <a href="4-lp.html#SP24_1_1">§24.1.1</a>, <a href="4-lp.html#SP24_1_3">§24.1.3</a>, <a href="4-lp.html#SP25_2">§25.2</a><br/>The Optimiser - <a href="4-to.html#SP4">§4</a>, <a href="4-to.html#SP5">§5</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2_3_3_3">§1.2.1.2.3.3.3</a>, <a href="4-prf.html#SP3">§3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP5">§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">§6</a>, <a href="2-vcb.html#SP10">§10</a>, <a href="2-vcb.html#SP11">§11</a>, <a href="2-vcb.html#SP16">§16</a><br/>Word Assemblages - <a href="2-wa.html#SP4">§4</a>, <a href="2-wa.html#SP9">§9</a>, <a href="2-wa.html#SP10">§10</a>, <a href="2-wa.html#SP11">§11</a><br/>Numbered Words - <a href="2-nw.html#SP1">§1</a><br/>Wordings - <a href="3-wrd.html#SP8">§8</a>, <a href="3-wrd.html#SP18">§18</a>, <a href="3-wrd.html#SP19">§19</a>, <a href="3-wrd.html#SP20">§20</a><br/>Text From Files - <a href="3-tff.html#SP4">§4</a><br/>Loading Preform - <a href="4-lp.html#SP7">§7</a>, <a href="4-lp.html#SP7_2">§7.2</a>, <a href="4-lp.html#SP7_3">§7.3</a>, <a href="4-lp.html#SP14_1_1">§14.1.1</a>, <a href="4-lp.html#SP14_1_3">§14.1.3</a>, <a href="4-lp.html#SP15_2">§15.2</a><br/>The Optimiser - <a href="4-to.html#SP4">§4</a>, <a href="4-to.html#SP5">§5</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2_3_3_3">§1.2.1.2.3.3.3</a>, <a href="4-prf.html#SP3">§3</a><br/>Basic Nonterminals - <a href="4-bn.html#SP1">§1</a>, <a href="4-bn.html#SP6">§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">§3</a><br/>Numbered Words - <a href="2-nw.html#SP1">§1</a>, <a href="2-nw.html#SP2">§2</a>, <a href="2-nw.html#SP4">§4</a>, <a href="2-nw.html#SP5">§5</a>, <a href="2-nw.html#SP6">§6</a>, <a href="2-nw.html#SP7">§7</a><br/>Wordings - <a href="3-wrd.html#SP16">§16</a>, <a href="3-wrd.html#SP22_3">§22.3</a>, <a href="3-wrd.html#SP22_4">§22.4</a><br/>Loading Preform - <a href="4-lp.html#SP25_1">§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">§3</a><br/>Numbered Words - <a href="2-nw.html#SP1">§1</a>, <a href="2-nw.html#SP2">§2</a>, <a href="2-nw.html#SP4">§4</a>, <a href="2-nw.html#SP5">§5</a>, <a href="2-nw.html#SP6">§6</a>, <a href="2-nw.html#SP7">§7</a><br/>Wordings - <a href="3-wrd.html#SP16">§16</a>, <a href="3-wrd.html#SP22_3">§22.3</a>, <a href="3-wrd.html#SP22_4">§22.4</a><br/>Loading Preform - <a href="4-lp.html#SP15_1">§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>
|
||||
|
||||
|
|
|
@ -117,11 +117,11 @@ if the wording is empty.
|
|||
<p class="commentary firstcommentary"><a id="SP6"></a><b>§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">§10</a><br/>Lexer - <a href="3-lxr.html#SP26">§26</a>, <a href="3-lxr.html#SP26_3">§26.3</a>, <a href="3-lxr.html#SP30">§30</a><br/>Feeds - <a href="3-fds.html#SP2">§2</a><br/>Loading Preform - <a href="4-lp.html#SP22_3">§22.3</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2">§1.2.1.2</a>, <a href="4-prf.html#SP1_2_1_2_3_3_5">§1.2.1.2.3.3.5</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3_1">§1.2.1.2.3.3.3.1</a>, <a href="4-prf.html#SP2">§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">§10</a><br/>Lexer - <a href="3-lxr.html#SP26">§26</a>, <a href="3-lxr.html#SP26_3">§26.3</a>, <a href="3-lxr.html#SP30">§30</a><br/>Feeds - <a href="3-fds.html#SP2">§2</a><br/>Loading Preform - <a href="4-lp.html#SP7_3">§7.3</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2">§1.2.1.2</a>, <a href="4-prf.html#SP1_2_1_2_3_3_5">§1.2.1.2.3.3.5</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3_1">§1.2.1.2.3.3.3.1</a>, <a href="4-prf.html#SP2">§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">§22</a>, <a href="4-lp.html#SP22_1">§22.1</a>, <a href="4-lp.html#SP25">§25</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2_3_3">§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">§7.1</a>, <a href="4-lp.html#SP15">§15</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2_3_3">§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>§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">§9</a>, <a href="3-wrd.html#SP14">§14</a>, <a href="3-wrd.html#SP21">§21</a><br/>Word Assemblages - <a href="2-wa.html#SP4">§4</a>, <a href="2-wa.html#SP10">§10</a>, <a href="2-wa.html#SP11">§11</a><br/>Lexer - <a href="3-lxr.html#SP30">§30</a><br/>Loading Preform - <a href="4-lp.html#SP25_2">§25.2</a><br/>The Optimiser - <a href="4-to.html#SP5">§5</a><br/>Preform - <a href="4-prf.html#SP1">§1</a>, <a href="4-prf.html#SP1_2_1">§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">§9</a>, <a href="3-wrd.html#SP14">§14</a>, <a href="3-wrd.html#SP21">§21</a><br/>Word Assemblages - <a href="2-wa.html#SP4">§4</a>, <a href="2-wa.html#SP10">§10</a>, <a href="2-wa.html#SP11">§11</a><br/>Lexer - <a href="3-lxr.html#SP30">§30</a><br/>Loading Preform - <a href="4-lp.html#SP15_2">§15.2</a><br/>The Optimiser - <a href="4-to.html#SP5">§5</a><br/>Preform - <a href="4-prf.html#SP1">§1</a>, <a href="4-prf.html#SP1_2_1">§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">§18</a>, <a href="3-wrd.html#SP21">§21</a>, <a href="3-wrd.html#SP22_3">§22.3</a>, <a href="3-wrd.html#SP22_4">§22.4</a><br/>Vocabulary - <a href="2-vcb.html#SP16">§16</a><br/>Word Assemblages - <a href="2-wa.html#SP9">§9</a>, <a href="2-wa.html#SP10">§10</a>, <a href="2-wa.html#SP11">§11</a><br/>Lexer - <a href="3-lxr.html#SP26">§26</a>, <a href="3-lxr.html#SP30">§30</a><br/>Loading Preform - <a href="4-lp.html#SP17">§17</a>, <a href="4-lp.html#SP22">§22</a>, <a href="4-lp.html#SP25_2">§25.2</a><br/>The Optimiser - <a href="4-to.html#SP4">§4</a>, <a href="4-to.html#SP5">§5</a><br/>Preform - <a href="4-prf.html#SP1_2">§1.2</a>, <a href="4-prf.html#SP1_2_1_2_2">§1.2.1.2.2</a>, <a href="4-prf.html#SP1_2_1_2_3_1">§1.2.1.2.3.1</a>, <a href="4-prf.html#SP1_2_1_2_3_3">§1.2.1.2.3.3</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3_1">§1.2.1.2.3.3.3.1</a><br/>Basic Nonterminals - <a href="4-bn.html#SP1">§1</a>, <a href="4-bn.html#SP2">§2</a>, <a href="4-bn.html#SP5">§5</a>, <a href="4-bn.html#SP6">§6</a>, <a href="4-bn.html#SP7">§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">§18</a>, <a href="3-wrd.html#SP21">§21</a>, <a href="3-wrd.html#SP22_3">§22.3</a>, <a href="3-wrd.html#SP22_4">§22.4</a><br/>Vocabulary - <a href="2-vcb.html#SP16">§16</a><br/>Word Assemblages - <a href="2-wa.html#SP9">§9</a>, <a href="2-wa.html#SP10">§10</a>, <a href="2-wa.html#SP11">§11</a><br/>Lexer - <a href="3-lxr.html#SP26">§26</a>, <a href="3-lxr.html#SP30">§30</a><br/>Loading Preform - <a href="4-lp.html#SP15_2">§15.2</a><br/>The Optimiser - <a href="4-to.html#SP4">§4</a>, <a href="4-to.html#SP5">§5</a><br/>Preform - <a href="4-prf.html#SP1_2">§1.2</a>, <a href="4-prf.html#SP1_2_1_2_2">§1.2.1.2.2</a>, <a href="4-prf.html#SP1_2_1_2_3_1">§1.2.1.2.3.1</a>, <a href="4-prf.html#SP1_2_1_2_3_3">§1.2.1.2.3.3</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3_1">§1.2.1.2.3.3.3.1</a><br/>Basic Nonterminals - <a href="4-bn.html#SP1">§1</a>, <a href="4-bn.html#SP2">§2</a>, <a href="4-bn.html#SP3">§3</a>, <a href="4-bn.html#SP6">§6</a>, <a href="4-bn.html#SP7">§7</a>, <a href="4-bn.html#SP8">§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">§18</a>, <a href="3-wrd.html#SP21">§21</a>, <a href="3-wrd.html#SP22_1">§22.1</a>, <a href="3-wrd.html#SP22_2">§22.2</a><br/>Word Assemblages - <a href="2-wa.html#SP11">§11</a><br/>Text From Files - <a href="3-tff.html#SP5">§5</a><br/>Loading Preform - <a href="4-lp.html#SP22">§22</a>, <a href="4-lp.html#SP22_3">§22.3</a>, <a href="4-lp.html#SP24_1_1">§24.1.1</a>, <a href="4-lp.html#SP24_1_3">§24.1.3</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2_2">§1.2.1.2.2</a>, <a href="4-prf.html#SP1_2_1_2_3_3">§1.2.1.2.3.3</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3">§1.2.1.2.3.3.3</a>, <a href="4-prf.html#SP1_2_1_2_3_3_5">§1.2.1.2.3.3.5</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3_1">§1.2.1.2.3.3.3.1</a>, <a href="4-prf.html#SP2">§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">§18</a>, <a href="3-wrd.html#SP21">§21</a>, <a href="3-wrd.html#SP22_1">§22.1</a>, <a href="3-wrd.html#SP22_2">§22.2</a><br/>Word Assemblages - <a href="2-wa.html#SP11">§11</a><br/>Text From Files - <a href="3-tff.html#SP5">§5</a><br/>Loading Preform - <a href="4-lp.html#SP7">§7</a>, <a href="4-lp.html#SP7_3">§7.3</a>, <a href="4-lp.html#SP14_1_1">§14.1.1</a>, <a href="4-lp.html#SP14_1_3">§14.1.3</a><br/>Preform - <a href="4-prf.html#SP1_2_1_2_2">§1.2.1.2.2</a>, <a href="4-prf.html#SP1_2_1_2_3_3">§1.2.1.2.3.3</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3">§1.2.1.2.3.3.3</a>, <a href="4-prf.html#SP1_2_1_2_3_3_5">§1.2.1.2.3.3.5</a>, <a href="4-prf.html#SP1_2_1_2_3_3_3_1">§1.2.1.2.3.3.3.1</a>, <a href="4-prf.html#SP2">§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">§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">§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"> > </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">§11</a>, <a href="3-wrd.html#SP14">§14</a><br/>Word Assemblages - <a href="2-wa.html#SP11">§11</a><br/>Identifiers - <a href="3-idn.html#SP3">§3</a><br/>Loading Preform - <a href="4-lp.html#SP13">§13</a>, <a href="4-lp.html#SP25_2">§25.2</a><br/>Basic Nonterminals - <a href="4-bn.html#SP6">§6</a>, <a href="4-bn.html#SP7">§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">§11</a>, <a href="3-wrd.html#SP14">§14</a><br/>Word Assemblages - <a href="2-wa.html#SP11">§11</a><br/>Identifiers - <a href="3-idn.html#SP3">§3</a><br/>Loading Preform - <a href="4-lp.html#SP15_2">§15.2</a>, <a href="4-lp.html#SP17">§17</a><br/>Basic Nonterminals - <a href="4-bn.html#SP7">§7</a>, <a href="4-bn.html#SP8">§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"> >= </span><span class="constant-syntax">0</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="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>
|
||||
|
|
|
@ -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>§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"><race-jersey></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>§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"><competitor></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(<competitor>, 1) GET_RW(<competitor>, 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 — 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"><competitor></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"><competitor></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">❮</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">❯</a></li></ul></div>
|
||||
<ul class="progressbar"><li class="progressprev"><a href="3-idn.html">❮</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">❯</a></li></ul></div>
|
||||
</nav><!--End of weave-->
|
||||
|
||||
</main>
|
||||
|
|
|
@ -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">§1. Text positions</a></li><li><a href="4-bn.html#SP3">§3. Balancing</a></li><li><a href="4-bn.html#SP5">§5. Literal numbers</a></li><li><a href="4-bn.html#SP6">§6. Literal text</a></li></ul><hr class="tocbar">
|
||||
<ul class="toc"><li><a href="4-bn.html#SP1">§1. Nonterminal names</a></li><li><a href="4-bn.html#SP2">§2. Text positions</a></li><li><a href="4-bn.html#SP4">§4. Balancing</a></li><li><a href="4-bn.html#SP6">§6. Literal numbers</a></li><li><a href="4-bn.html#SP7">§7. Literal text</a></li></ul><hr class="tocbar">
|
||||
|
||||
<p class="commentary firstcommentary"><a id="SP1"></a><b>§1. Text positions. </b>A useful nonterminal which matches no text, but detects the position:
|
||||
<p class="commentary firstcommentary"><a id="SP1"></a><b>§1. Nonterminal names. </b>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.)
|
||||
</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"><preform-nonterminal></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>§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>§2. </b>And another convenience:
|
||||
<p class="commentary firstcommentary"><a id="SP3"></a><b>§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>§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>§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>§4. </b>Inform contains relatively few syntaxes where commas are actually required,
|
||||
<p class="commentary firstcommentary"><a id="SP5"></a><b>§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>§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>§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>§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>§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"><quoted-text></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">)) && (</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">)) &&</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"><quoted-text-with-subs></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">)) && (</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">)) &&</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"><quoted-text-without-subs></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">)) && (</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">)) &&</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>§7. </b>For finicky technical reasons the easiest way to detect an empty piece
|
||||
<p class="commentary firstcommentary"><a id="SP8"></a><b>§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"><empty-text></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">)) && (</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">)) &&</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">❮</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">❯</li></ul></div>
|
||||
<ul class="progressbar"><li class="progressprev"><a href="4-prf.html">❮</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">❯</li></ul></div>
|
||||
</nav><!--End of weave-->
|
||||
|
||||
</main>
|
||||
|
|
File diff suppressed because it is too large
Load diff
360
docs/words-module/4-nnt.html
Normal file
360
docs/words-module/4-nnt.html
Normal 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">§1. How nonterminals are stored</a></li><li><a href="4-nnt.html#SP9">§9. Word ranges in a nonterminal</a></li><li><a href="4-nnt.html#SP10">§10. Other results</a></li></ul><hr class="tocbar">
|
||||
|
||||
<p class="commentary firstcommentary"><a id="SP1"></a><b>§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 <any-integer>, 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">"<any-integer>"</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> — 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">§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">-></span><span class="element-syntax">marked_internal</span><span class="plain-syntax">) && (</span><span class="identifier-syntax">nt</span><span class="plain-syntax">-></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>§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"><competitor></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">==></span><span class="Preform-plain-syntax"> 1</span>
|
||||
<span class="Preform-plain-syntax"> </span><span class="Preform-function-syntax"><ordinal-number></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">==></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"><cardinal-number></span><span class="Preform-plain-syntax"> </span><span class="Preform-reserved-syntax">==></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">"<competitor>"</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 —
|
||||
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">==></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">"<competitor>"</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">-></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>§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">"<competitor>"</span><span class="plain-syntax">));</span>
|
||||
<span class="plain-syntax"> </span><span class="identifier-syntax">competitor_NTM</span><span class="plain-syntax">-></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>§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">-></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">-></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">-></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">-></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>§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, <any-integer>. 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">"<any-integer>"</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>§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 <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 <a href="4-to.html" class="internal">The Optimiser</a>.
|
||||
</li></ul>
|
||||
<p class="commentary firstcommentary"><a id="SP7"></a><b>§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">§8</a><br/>Basic Nonterminals - <a href="4-bn.html#SP1">§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">-></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>§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">§2</a>, <a href="4-nnt.html#SP4">§4</a><br/>Loading Preform - <a href="4-lp.html#SP7_2">§7.2</a>, <a href="4-lp.html#SP7_3">§7.3</a>, <a href="4-lp.html#SP16">§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">-></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">-></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">-></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">-></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"><</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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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">-></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>§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">-></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">-></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"><</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">-></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">-></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"><</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">-></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>§10. Other results. </b>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.
|
||||
</p>
|
||||
|
||||
<p class="commentary"><a href="../../../inweb/docs/index.html" class="internal">inweb</a> translates the notation <span class="extract"><span class="extract-syntax"><<r>></span></span> and <span class="extract"><span class="extract-syntax"><<rp>></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"><<r>></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"><<rp>></span></span>
|
||||
</pre>
|
||||
<nav role="progress"><div class="progresscontainer">
|
||||
<ul class="progressbar"><li class="progressprev"><a href="4-ap.html">❮</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">❯</a></li></ul></div>
|
||||
</nav><!--End of weave-->
|
||||
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -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">-></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">-></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">-></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">-></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">-></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">-></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">": <%W> 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">(&(</span><span class="identifier-syntax">pr</span><span class="plain-syntax">-></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">-></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">❮</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">❯</a></li></ul></div>
|
||||
<ul class="progressbar"><li class="progressprev"><a href="4-to.html">❮</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">❯</a></li></ul></div>
|
||||
</nav><!--End of weave-->
|
||||
|
||||
</main>
|
||||
|
|
|
@ -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">§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">§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">(&(</span><span class="identifier-syntax">nt</span><span class="plain-syntax">-></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">-></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">-></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">§13</a><br/>Preform - <a href="4-prf.html#SP1_2">§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">§17</a><br/>Preform - <a href="4-prf.html#SP1_2">§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">-></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">-></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">-></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">-></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">-></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">-></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">❮</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">❯</a></li></ul></div>
|
||||
<ul class="progressbar"><li class="progressprev"><a href="4-lp.html">❮</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">❯</a></li></ul></div>
|
||||
</nav><!--End of weave-->
|
||||
|
||||
</main>
|
||||
|
|
|
@ -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 —
|
||||
<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 —
|
||||
there are exotica such as <span class="extract"><span class="extract-syntax">COLONCOLONEQUALS_V</span></span> there, for "::=".
|
||||
</p>
|
||||
|
||||
|
|
|
@ -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> -
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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@> =
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -51,7 +51,8 @@ void WordsModule::start(void) {
|
|||
|
||||
Lexer::start();
|
||||
Vocabulary::create_punctuation();
|
||||
LoadPreform::begin();
|
||||
LoadPreform::create_punctuation();
|
||||
Nonterminals::register();
|
||||
}
|
||||
|
||||
void WordsModule::end(void) {
|
||||
|
|
|
@ -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".
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
248
shared/words-module/Chapter 4/Nonterminals.w
Normal file
248
shared/words-module/Chapter 4/Nonterminals.w
Normal 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>>| */
|
|
@ -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) {
|
||||
|
|
|
@ -28,6 +28,7 @@ Chapter 3: Words in Sequence
|
|||
|
||||
Chapter 4: Parsing
|
||||
About Preform
|
||||
Nonterminals
|
||||
Loading Preform
|
||||
The Optimiser
|
||||
Preform
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue